Completed
Push — master ( 332511...198978 )
by Julien
02:42
created

Championship   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 9

Importance

Changes 10
Bugs 1 Features 0
Metric Value
wmc 44
c 10
b 1
f 0
lcom 3
cbo 9
dl 0
loc 256
rs 8.3396

24 Methods

Rating   Name   Duplication   Size   Complexity  
A boot() 0 13 1
A competitors() 0 4 1
A getSettings() 0 4 1
A groupsByRound() 0 4 1
A fightsByRound() 0 4 1
A isPlayoffCompetitor() 0 5 3
A isPlayoffTeam() 0 5 3
A isDirectEliminationCompetitor() 0 4 3
A isDirectEliminationTeam() 0 4 3
B chooseGenerationStrategy() 0 21 5
A fighters() 0 7 2
A category() 0 4 1
A tournament() 0 4 1
A users() 0 6 1
A settings() 0 4 1
A teams() 0 4 1
A hasPreliminary() 0 4 2
A isPlayOffType() 0 4 2
A isDirectEliminationType() 0 4 2
A fightersGroups() 0 4 1
A fights() 0 4 1
A firstRoundFights() 0 5 1
A hasNoCustomSettings() 0 4 1
B buildName() 0 21 5

How to fix   Complexity   

Complex Class

Complex classes like Championship often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Championship, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Xoco70\KendoTournaments\Models;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Relations\HasMany;
7
use Illuminate\Database\Eloquent\SoftDeletes;
8
use Illuminate\Foundation\Auth\User;
9
use Xoco70\KendoTournaments\Contracts\TreeGenerable;
10
use Xoco70\KendoTournaments\TreeGen\DirectEliminationCompetitorTreeGen;
11
use Xoco70\KendoTournaments\TreeGen\DirectEliminationTeamTreeGen;
12
use Xoco70\KendoTournaments\TreeGen\PlayOffCompetitorTreeGen;
13
use Xoco70\KendoTournaments\TreeGen\PlayOffTeamTreeGen;
14
use Xoco70\KendoTournaments\TreeGen\TreeGen;
15
16
class Championship extends Model
17
{
18
    use SoftDeletes;
19
    protected $dates = ['created_at', 'updated_at', 'deleted_at'];
20
    protected $table = 'championship';
21
22
    public $timestamps = true;
23
    protected $fillable = [
24
        'tournament_id',
25
        'category_id',
26
    ];
27
28
    protected static function boot()
29
    {
30
        parent::boot();
31
32
        static::deleting(function ($championship) {
33
            $championship->competitors()->delete();
34
            $championship->settings()->delete();
35
        });
36
        static::restoring(function ($championship) {
37
            $championship->competitors()->restore();
38
            $championship->settings()->restore();
39
        });
40
    }
41
42
    /**
43
     * A championship has many Competitors.
44
     *
45
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
46
     */
47
    public function competitors()
48
    {
49
        return $this->hasMany(Competitor::class);
50
    }
51
52
    public function fighters()
53
    {
54
        if ($this->category->isTeam) {
55
            return $this->hasMany(Team::class);
56
        }
57
        return $this->hasMany(Competitor::class);
58
    }
59
60
    /**
61
     * A championship belongs to a Category.
62
     *
63
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
64
     */
65
    public function category()
66
    {
67
        return $this->belongsTo(Category::class);
68
    }
69
70
    /**
71
     * A championship belongs to a Tournament.
72
     *
73
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
74
     */
75
    public function tournament()
76
    {
77
        return $this->belongsTo(Tournament::class);
78
    }
79
80
    /**
81
     * Get All competitors from a Championships.
82
     *
83
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
84
     */
85
    public function users()
86
    {
87
        return $this->belongsToMany(User::class, 'competitor', 'championship_id')
88
            ->withPivot('confirmed')
89
            ->withTimestamps();
90
    }
91
92
    /**
93
     * A championship only has 1 Settings.
94
     *
95
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
96
     */
97
    public function settings()
98
    {
99
        return $this->hasOne(ChampionshipSettings::class);
100
    }
101
102
    /**
103
     * A championship has Many Teams.
104
     *
105
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
106
     */
107
    public function teams()
108
    {
109
        return $this->hasMany(Team::class);
110
    }
111
112
    /**
113
     * Check if Championship has Preliminary Round Configured.
114
     *
115
     * @return bool
116
     */
117
    public function hasPreliminary()
118
    {
119
        return $this->settings == null || $this->settings->hasPreliminary;
120
    }
121
122
    /**
123
     * Check if 2nd Round of Championship is Round Robin.
124
     *
125
     * @return bool
126
     */
127
    public function isPlayOffType()
128
    {
129
        return $this->settings != null && $this->settings->treeType == ChampionshipSettings::PLAY_OFF;
130
    }
131
132
    /**
133
     * Check if 2nd Round of Championship is Direct Elimination.
134
     *
135
     * @return bool
136
     */
137
    public function isDirectEliminationType()
138
    {
139
        return $this->settings != null && $this->settings->treeType == ChampionshipSettings::DIRECT_ELIMINATION;
140
    }
141
142
    /**
143
     * A championship has Many Groups of Fighters.
144
     *
145
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
146
     */
147
    public function fightersGroups()
148
    {
149
        return $this->hasMany(FightersGroup::class);
150
    }
151
152
    /**
153
     * A championship has Many fights.
154
     *
155
     * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
156
     */
157
    public function fights()
158
    {
159
        return $this->hasManyThrough(Fight::class, FightersGroup::class);
160
    }
161
162
    /**
163
     * Get the fights that happen to the first round
164
     * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
165
     */
166
    public function firstRoundFights()
167
    {
168
        return $this->hasManyThrough(Fight::class, FightersGroup::class)
169
            ->where('fighters_groups.round', 1);
170
    }
171
172
    private function hasNoCustomSettings()
173
    {
174
        return $this->settings == null;
175
    }
176
177
    public function buildName()
178
    {
179
        if ($this->settings != null && $this->settings->alias != null)
180
            return $this->settings->alias;
181
182
        if ($this->hasNoCustomSettings()) {
183
            return $this->category->name;
184
        }
185
186
        $genders = [
187
            'M' => trans('categories.male'),
188
            'F' => trans('categories.female'),
189
            'X' => trans('categories.mixt')
190
        ];
191
192
        $teamText = $this->category->isTeam == 1 ? trans_choice('core.team', 1) : trans('categories.single');
193
        $ageCategoryText = $this->category->getAgeString();
194
        $gradeText = $this->category->getGradeString();
195
196
        return $teamText . ' ' . $genders[$this->category->gender] . ' ' . $ageCategoryText . ' ' . $gradeText;
197
    }
198
199
    public function getSettings()
200
    {
201
        return $this->settings ?? new ChampionshipSettings(ChampionshipSettings::DEFAULT_SETTINGS);
202
    }
203
204
    /**
205
     * Return Groups that belongs to a round
206
     * @param integer $round
207
     * @return HasMany
208
     */
209
    public function groupsByRound($round)
210
    {
211
        return $this->fightersGroups()->where('round', $round);
212
    }
213
214
    /**
215
     * Return Fights that belongs to a round
216
     *
217
     * @param integer $round
218
     * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
219
     */
220
    public function fightsByRound($round)
221
    {
222
        return $this->hasManyThrough(Fight::class, FightersGroup::class)->where('round', $round);
223
    }
224
225
    public function isPlayoffCompetitor()
226
    {
227
        return !$this->category->isTeam() &&
228
            ($this->isPlayOffType() || $this->hasPreliminary());
229
    }
230
231
    public function isPlayoffTeam()
232
    {
233
        return $this->category->isTeam() &&
234
            ($this->isPlayOffType() || $this->hasPreliminary());
235
    }
236
237
    public function isDirectEliminationCompetitor()
238
    {
239
        return !$this->category->isTeam() && $this->isDirectEliminationType() && !$this->hasPreliminary();
240
    }
241
242
    public function isDirectEliminationTeam()
243
    {
244
        return $this->category->isTeam() && $this->isDirectEliminationType() && !$this->hasPreliminary();
245
    }
246
247
    /**
248
     * @return TreeGenerable
249
     */
250
    public function chooseGenerationStrategy()
251
    {
252
        $generation = new TreeGen($this, null);
253
        switch (true) {
254
            case $this->isDirectEliminationCompetitor():
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
255
                $generation = new DirectEliminationCompetitorTreeGen($this, null);
256
                break;
257
            case $this->isDirectEliminationTeam():
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
258
                $generation = new DirectEliminationTeamTreeGen($this, null);
259
                break;
260
            case $this->isPlayoffCompetitor():
261
                $generation = new PlayOffCompetitorTreeGen($this, null);
262
                break;
263
            case $this->isPlayoffTeam():
264
                $generation = new PlayOffTeamTreeGen($this, null);
265
                break;
266
            default:
267
                dd("bad choice");
268
        }
269
        return $generation;
270
    }
271
}
272