Completed
Push — master ( b13aa8...0a3a64 )
by Julien
11:57
created

TreeGen::pushGroups()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 3
eloc 6
nc 3
nop 2
1
<?php
2
3
namespace Xoco70\KendoTournaments\TreeGen;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Support\Facades\App;
7
use Xoco70\KendoTournaments\Contracts\TreeGenerable;
8
use Xoco70\KendoTournaments\Exceptions\TreeGenerationException;
9
use Xoco70\KendoTournaments\Models\Championship;
10
use Xoco70\KendoTournaments\Models\ChampionshipSettings;
11
use Xoco70\KendoTournaments\Models\Fight;
12
use Xoco70\KendoTournaments\Models\FightersGroup;
13
14
class TreeGen implements TreeGenerable
15
{
16
    protected $groupBy;
17
    protected $tree;
18
    public $championship;
19
    public $settings;
20
    protected $numFighters;
21
22
    /**
23
     * @param Championship $championship
24
     * @param $groupBy
25
     */
26
    public function __construct(Championship $championship, $groupBy)
27
    {
28
        $this->championship = $championship;
29
        $this->groupBy = $groupBy;
30
        $this->settings = $championship->getSettings();
31
        $this->tree = new Collection();
32
    }
33
34
    /**
35
     * Generate tree groups for a championship.
36
     *
37
     * @throws TreeGenerationException
38
     */
39
    public function run()
40
    {
41
        $usersByArea = $this->getFightersByArea();
42
        $numFighters = sizeof($usersByArea->collapse());
43
44
        $this->generateGroupsForRound($usersByArea, 1, 1);
45
        $this->pushEmptyGroupsToTree($numFighters);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method pushEmptyGroupsToTree() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
46
        $this->addParentToChildren($numFighters);
47
        $this->generateFights();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method generateFights() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
48
        $this->generateNextRoundsFights();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method generateNextRoundsFights() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
49
//        Fight::generateFightsId($this->championship);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
50
//dd("ok");
51
    }
52
53
    /**
54
     * Get the biggest entity group
55
     * @param $userGroups
56
     *
57
     * @return int
58
     */
59
    private function getMaxFightersByEntity($userGroups): int
60
    {
61
        return $userGroups
62
            ->sortByDesc(function ($group) {
63
                return $group->count();
64
            })
65
            ->first()
66
            ->count();
67
68
    }
69
70
    /**
71
     * Get Competitor's list ordered by entities
72
     * Countries for Internation Tournament, State for a National Tournament, etc.
73
     *
74
     * @param $fighters
75
     * @return Collection
76
     */
77
    private function getFightersByEntity($fighters): Collection
78
    {
79
        // Right now, we are treating users and teams as equals.
80
        // It doesn't matter right now, because we only need name attribute which is common to both models
81
82
        // $this->groupBy contains federation_id, association_id, club_id, etc.
83
        if (($this->groupBy) != null) {
84
            $fighterGroups = $fighters->groupBy($this->groupBy); // Collection of Collection
85
        } else {
86
            $fighterGroups = $fighters->chunk(1); // Collection of Collection
87
        }
88
        return $fighterGroups;
89
    }
90
91
    /**
92
     * Get the size the first round will have
93
     * @param $fighterCount
94
     * @param $groupSize
95
     * @return int
96
     */
97
    protected function getTreeSize($fighterCount, $groupSize)
98
    {
99
        $square = collect([1, 2, 4, 8, 16, 32, 64]);
100
        $squareMultiplied = $square->map(function ($item) use ($groupSize) {
101
            return $item * $groupSize;
102
        });
103
104
        foreach ($squareMultiplied as $limit) {
105
            if ($fighterCount <= $limit) {
106
                return $limit;
107
            }
108
        }
109
        return 64 * $groupSize;
110
    }
111
112
    /**
113
     * Repart BYE in the tree,
114
     * @param $fighterGroups
115
     * @param int $max
116
     *
117
     * @return Collection
118
     */
119
    private function repart($fighterGroups, $max)
120
    {
121
        $fighters = new Collection();
122
        for ($i = 0; $i < $max; $i++) {
123
            foreach ($fighterGroups as $fighterGroup) {
124
                $fighter = $fighterGroup->values()->get($i);
125
                if ($fighter != null) {
126
                    $fighters->push($fighter);
127
                }
128
            }
129
        }
130
131
        return $fighters;
132
    }
133
134
    /**
135
     * Insert byes in an homogen way.
136
     *
137
     * @param Collection $fighters
138
     * @param Collection $byeGroup
139
     *
140
     * @return Collection
141
     */
142
    private function insertByes(Collection $fighters, Collection $byeGroup)
143
    {
144
        $bye = count($byeGroup) > 0 ? $byeGroup[0] : [];
145
        $sizeFighters = count($fighters);
146
        $sizeGroupBy = count($byeGroup);
147
148
        $frequency = $sizeGroupBy != 0
149
            ? (int)floor($sizeFighters / $sizeGroupBy)
150
            : -1;
151
152
        // Create Copy of $competitors
153
        return $this->getFullFighterList($fighters, $frequency, $sizeGroupBy, $bye);
154
    }
155
156
    /**
157
     * @param Collection $usersByArea
158
     * @param integer $area
159
     * @param integer $round
160
     *
161
     */
162
    public function generateGroupsForRound($usersByArea, $area, $round)
163
    {
164
        foreach ($usersByArea as $fightersByEntity) {
165
            // Chunking to make small round robin groups
166
            $fightersGroup = $this->chunkAndShuffle($round, $fightersByEntity);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method chunkAndShuffle() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
167
            $order = 1;
168
            foreach ($fightersGroup as $fighters) {
169
                $fighters = $fighters->pluck('id');
170
                if (!App::runningUnitTests()) {
171
                    $fighters = $fighters->shuffle();
172
                }
173
                $group = $this->saveGroup($area, $order, $round, null);
174
                $this->syncGroup($group, $fighters);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method syncGroup() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
175
                $order++;
176
            }
177
            $area++;
178
        }
179
    }
180
181
    /**
182
     * @param $area
183
     * @param $order
184
     * @param $round
185
     * @param $parent
186
     * @return FightersGroup
187
     */
188
    protected function saveGroup($area, $order, $round, $parent): FightersGroup
189
    {
190
        $group = new FightersGroup();
191
        $group->area = $area;
192
        $group->order = $order;
193
        $group->round = $round;
194
        $group->championship_id = $this->championship->id;
195
        if ($parent != null) {
196
            $group->parent_id = $parent->id;
197
        }
198
        $group->save();
199
        return $group;
200
    }
201
202
203
    /**
204
     * @param integer $groupSize
205
     * @return Collection
206
     */
207 View Code Duplication
    public function createByeGroup($groupSize): Collection
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
208
    {
209
        $byeFighter = $this->createByeFighter();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method createByeFighter() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
210
        $group = new Collection();
211
        for ($i = 0; $i < $groupSize; $i++) {
212
            $group->push($byeFighter);
213
        }
214
        return $group;
215
    }
216
217
    /**
218
     * @param $fighters
219
     * @param Collection $fighterGroups
220
     * @return Collection
221
     */
222
    public function adjustFightersGroupWithByes($fighters, $fighterGroups): Collection
223
    {
224
        $tmpFighterGroups = clone $fighterGroups;
225
        $byeGroup = $this->getByeGroup($fighters);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method getByeGroup() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
226
227
        // Get biggest competitor's group
228
        $max = $this->getMaxFightersByEntity($tmpFighterGroups);
229
230
        // We reacommodate them so that we can mix them up and they don't fight with another competitor of his entity.
231
232
        $fighters = $this->repart($fighterGroups, $max);
233
        $fighters = $this->insertByes($fighters, $byeGroup);
234
235
        return $fighters;
236
    }
237
238
    /**
239
     * Get All Groups on previous round
240
     * @param $currentRound
241
     * @return Collection
242
     */
243
    private function getPreviousRound($currentRound)
244
    {
245
        $previousRound = $this->championship->groupsByRound($currentRound + 1)->get();
246
        return $previousRound;
247
    }
248
249
    /**
250
     * Get the next group on the right ( parent ), final round being the ancestor
251
     * @param $matchNumber
252
     * @param Collection $previousRound
253
     * @return mixed
254
     */
255
    private function getParentGroup($matchNumber, $previousRound)
256
    {
257
        $parentIndex = intval(($matchNumber + 1) / 2);
258
        $parent = $previousRound->get($parentIndex - 1);
259
        return $parent;
260
    }
261
262
263
264
    /**
265
     * Group Fighters by area
266
     * @return Collection
267
     * @throws TreeGenerationException
268
     */
269
    private function getFightersByArea()
270
    {
271
        // If previous trees already exists, delete all
272
        $this->championship->fightersGroups()->delete();
273
        $areas = $this->settings->fightingAreas;
274
        $fighters = $this->getFighters();
0 ignored issues
show
Bug introduced by
The method getFighters() does not exist on Xoco70\KendoTournaments\TreeGen\TreeGen. Did you maybe mean getFightersByEntity()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
275
276
277
        if ($fighters->count() / $areas < ChampionshipSettings::MIN_COMPETITORS_BY_AREA) {
278
            throw new TreeGenerationException();
279
        }
280
        // Get Competitor's / Team list ordered by entities ( Federation, Assoc, Club, etc...)
281
        $fighterByEntity = $this->getFightersByEntity($fighters); // Chunk(1)
282
        $fightersWithBye = $this->adjustFightersGroupWithByes($fighters, $fighterByEntity);
283
284
        // Chunk user by areas
285
        return $fightersWithBye->chunk(count($fightersWithBye) / $areas);
286
    }
287
288
    /**
289
     * Attach a parent to every child for nestedSet Navigation
290
     * @param $numFightersElim
291
     */
292
    private function addParentToChildren($numFightersElim)
293
    {
294
        $numRounds  = $this->getNumRounds($numFightersElim);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method getNumRounds() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...irectEliminationTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
295
        $groupsDesc = $this->championship
296
            ->fightersGroups()
297
            ->where('round', '<', $numRounds)
298
            ->orderByDesc('id')->get();
299
300
        $groupsDescByRound = $groupsDesc->groupBy('round');
301
302
        foreach ($groupsDescByRound as $round => $groups) {
303
            $previousRound = $this->getPreviousRound($round);
304
            foreach ($groups->reverse()->values() as $matchNumber => $group) {
305
                $parent = $this->getParentGroup($matchNumber + 1, $previousRound);
306
                $group->parent_id = $parent->id;
307
                $group->save();
308
            }
309
        }
310
    }
311
312
    /**
313
     * Create Bye Groups to adjust tree
314
     * @param $byeCount
315
     * @return Collection
316
     */
317 View Code Duplication
    protected function createNullsGroup($byeCount): Collection
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
318
    {
319
        $byeFighter = $this->createByeFighter();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Xoco70\KendoTournaments\TreeGen\TreeGen as the method createByeFighter() does only exist in the following sub-classes of Xoco70\KendoTournaments\TreeGen\TreeGen: Xoco70\KendoTournaments\...nationCompetitorTreeGen, Xoco70\KendoTournaments\...tEliminationTeamTreeGen, Xoco70\KendoTournaments\...layOffCompetitorTreeGen, Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
320
        $byeGroup = new Collection();
321
        for ($i = 0; $i < $byeCount; $i++) {
322
            $byeGroup->push($byeFighter);
323
        }
324
        return $byeGroup;
325
    }
326
327
    /**
328
     * @param Collection $fighters
329
     * @param $frequency
330
     * @param $sizeGroupBy
331
     * @param $bye
332
     * @return Collection
333
     */
334
    private function getFullFighterList(Collection $fighters, $frequency, $sizeGroupBy, $bye): Collection
335
    {
336
        $newFighters = new Collection();
337
        $count = 0;
338
        $byeCount = 0;
339
        foreach ($fighters as $fighter) {
340
            if ($this->shouldInsertBye($frequency, $sizeGroupBy, $count, $byeCount)) {
341
                $newFighters->push($bye);
342
                $byeCount++;
343
            }
344
            $newFighters->push($fighter);
345
            $count++;
346
        }
347
        return $newFighters;
348
    }
349
350
    /**
351
     * @param $frequency
352
     * @param $sizeGroupBy
353
     * @param $count
354
     * @param $byeCount
355
     * @return bool
356
     */
357
    private function shouldInsertBye($frequency, $sizeGroupBy, $count, $byeCount): bool
358
    {
359
        return $frequency != -1 && $count % $frequency == 0 && $byeCount < $sizeGroupBy;
360
    }
361
362
363
    /**
364
     * @param Championship $championship
0 ignored issues
show
Bug introduced by
There is no parameter named $championship. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
365
     */
366
    protected function destroyPreviousFights()
367
    {
368
        // Delete previous fight for this championship
369
        $arrGroupsId = $this->championship->fightersGroups()->get()->pluck('id');
370
        Fight::destroy($arrGroupsId);
371
    }
372
}
373