PlanetField   C
last analyzed

Complexity

Total Complexity 57

Size/Duplication

Total Lines 321
Duplicated Lines 0 %

Test Coverage

Coverage 44.96%

Importance

Changes 0
Metric Value
eloc 133
c 0
b 0
f 0
dl 0
loc 321
ccs 58
cts 129
cp 0.4496
rs 5.04
wmc 57

36 Methods

Rating   Name   Duplication   Size   Complexity  
A getTerraformingId() 0 3 1
A getId() 0 3 1
A getBuildingState() 0 6 2
A isActivateable() 0 10 3
A getTerraforming() 0 3 1
A isUnderConstruction() 0 3 1
A setTerraforming() 0 5 1
A setColonySandbox() 0 4 1
A setIntegrity() 0 4 1
A getFieldType() 0 3 1
A setFieldId() 0 4 1
B getCssClass() 0 25 8
A getActivateAfterBuild() 0 3 1
A getPictureType() 0 3 1
A getBuildtime() 0 3 1
A setFieldType() 0 4 1
A getBuilding() 0 3 1
A getBuildingId() 0 3 1
A isColonizeAble() 0 3 1
A setActivateAfterBuild() 0 4 1
A setColony() 0 4 1
A setBuildMode() 0 3 1
A setBuilding() 0 5 1
A isActive() 0 3 1
A getBuildProgress() 0 9 2
A getFieldId() 0 3 1
A hasBuilding() 0 3 1
A getOverlayWidth() 0 10 2
A setActive() 0 4 1
A isDamaged() 0 10 3
A hasHighDamage() 0 12 3
A getHost() 0 10 3
A clearBuilding() 0 5 1
A getDayNightPrefix() 0 9 4
A getActive() 0 3 1
A getIntegrity() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like PlanetField 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.

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 PlanetField, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Entity;
6
7
use Doctrine\ORM\Mapping\Column;
8
use Doctrine\ORM\Mapping\Entity;
9
use Doctrine\ORM\Mapping\GeneratedValue;
10
use Doctrine\ORM\Mapping\Id;
11
use Doctrine\ORM\Mapping\Index;
12
use Doctrine\ORM\Mapping\JoinColumn;
13
use Doctrine\ORM\Mapping\ManyToOne;
14
use Doctrine\ORM\Mapping\Table;
15
use RuntimeException;
16
use Stu\Orm\Repository\PlanetFieldRepository;
17
18
#[Table(name: 'stu_colonies_fielddata')]
19
#[Index(name: 'planet_field_field_idx', columns: ['field_id'])]
20
#[Index(name: 'planet_field_aktiv_idx', columns: ['aktiv'])]
21
#[Entity(repositoryClass: PlanetFieldRepository::class)]
22
class PlanetField
23
{
24
    #[Id]
25
    #[Column(type: 'integer')]
26
    #[GeneratedValue(strategy: 'IDENTITY')]
27
    private int $id;
28
29
    #[Column(type: 'integer', nullable: true)]
30
    private ?int $colonies_id = null;
0 ignored issues
show
introduced by
The private property $colonies_id is not used, and could be removed.
Loading history...
31
32
    #[Column(type: 'integer', nullable: true)]
33
    private ?int $colony_sandbox_id = null;
0 ignored issues
show
introduced by
The private property $colony_sandbox_id is not used, and could be removed.
Loading history...
34
35
    #[Column(type: 'smallint')]
36
    private int $field_id = 0;
37
38
    #[Column(type: 'integer')]
39
    private int $type_id = 0;
40
41
    #[Column(type: 'integer', nullable: true)]
42
    private ?int $buildings_id = null;
43
44
    #[Column(type: 'integer', nullable: true)]
45
    private ?int $terraforming_id = null;
46
47
    #[Column(type: 'smallint')]
48
    private int $integrity = 0;
49
50
    #[Column(type: 'integer')]
51
    private int $aktiv = 0;
52
53
    #[Column(type: 'boolean')]
54
    private bool $activate_after_build = true;
55
56
    #[ManyToOne(targetEntity: Building::class)]
57
    #[JoinColumn(name: 'buildings_id', referencedColumnName: 'id')]
58
    private ?Building $building = null;
59
60
    #[ManyToOne(targetEntity: Terraforming::class)]
61
    #[JoinColumn(name: 'terraforming_id', referencedColumnName: 'id')]
62
    private ?Terraforming $terraforming = null;
63
64
    #[ManyToOne(targetEntity: Colony::class)]
65
    #[JoinColumn(name: 'colonies_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
66
    private ?Colony $colony = null;
67
68
    #[ManyToOne(targetEntity: ColonySandbox::class)]
69
    #[JoinColumn(name: 'colony_sandbox_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
70
    private ?ColonySandbox $sandbox = null;
71
72
    private bool $buildmode = false;
73
74 7
    public function getId(): int
75
    {
76 7
        return $this->id;
77
    }
78
79 6
    public function getFieldId(): int
80
    {
81 6
        return $this->field_id;
82
    }
83
84
    public function setFieldId(int $fieldId): PlanetField
85
    {
86
        $this->field_id = $fieldId;
87
        return $this;
88
    }
89
90 7
    public function getFieldType(): int
91
    {
92 7
        return $this->type_id;
93
    }
94
95
    public function setFieldType(int $planetFieldTypeId): PlanetField
96
    {
97
        $this->type_id = $planetFieldTypeId;
98
        return $this;
99
    }
100
101 1
    public function getBuildingId(): ?int
102
    {
103 1
        return $this->buildings_id;
104
    }
105
106 4
    public function getTerraformingId(): ?int
107
    {
108 4
        return $this->terraforming_id;
109
    }
110
111 6
    public function getIntegrity(): int
112
    {
113 6
        return $this->integrity;
114
    }
115
116
    public function setIntegrity(int $integrity): PlanetField
117
    {
118
        $this->integrity = $integrity;
119
        return $this;
120
    }
121
122 7
    public function getActive(): int
123
    {
124 7
        return $this->aktiv;
125
    }
126
127
    public function setActive(int $aktiv): PlanetField
128
    {
129
        $this->aktiv = $aktiv;
130
        return $this;
131
    }
132
133
    public function getActivateAfterBuild(): bool
134
    {
135
        return $this->activate_after_build;
136
    }
137
138
    public function setActivateAfterBuild(bool $activateAfterBuild): PlanetField
139
    {
140
        $this->activate_after_build = $activateAfterBuild;
141
        return $this;
142
    }
143
144
    public function setBuildMode(bool $value): void
145
    {
146
        $this->buildmode = $value;
147
    }
148
149
    public function getBuildtime(): int
150
    {
151
        return $this->getActive();
152
    }
153
154 7
    public function isActive(): bool
155
    {
156 7
        return $this->getActive() === 1;
157
    }
158
159 7
    public function isActivateable(): bool
160
    {
161 7
        $building = $this->building;
162 7
        if ($building === null) {
163
            return false;
164
        }
165 7
        if ($this->isUnderConstruction()) {
166
            return false;
167
        }
168 7
        return $building->isActivateable();
169
    }
170
171 6
    public function hasHighDamage(): bool
172
    {
173 6
        if (!$this->isDamaged()) {
174 6
            return false;
175
        }
176
177
        $building = $this->getBuilding();
178
        if ($building === null) {
179
            throw new RuntimeException('should only be called on fields with building!');
180
        }
181
182
        return round((100 / $building->getIntegrity()) * $this->getIntegrity()) < 50;
183
    }
184
185 7
    public function isUnderConstruction(): bool
186
    {
187 7
        return $this->getActive() > 1;
188
    }
189
190 5
    public function hasBuilding(): bool
191
    {
192 5
        return $this->getBuilding() !== null;
193
    }
194
195 5
    public function getCssClass(): string
196
    {
197 5
        if ($this->buildmode === true) {
198
            return 'cfb';
199
        }
200 5
        if ($this->isActive()) {
201 5
            if ($this->isDamaged()) {
202
                return 'cfld';
203
            }
204 5
            return 'cfa';
205
        }
206 5
        if ($this->hasHighDamage()) {
207
            return 'cfhd';
208
        }
209 5
        if ($this->hasBuilding()) {
210
            if ($this->isUnderConstruction()) {
211
                return 'cfc';
212
            }
213
214
            if ($this->isActivateable()) {
215
                return 'cfd';
216
            }
217
        }
218
219 5
        return 'cfu';
220
    }
221
222 6
    public function getBuildingState(): string
223
    {
224 6
        if ($this->isUnderConstruction()) {
225
            return 'b';
226
        }
227 6
        return 'a';
228
    }
229
230 10
    public function getBuilding(): ?Building
231
    {
232 10
        return $this->building;
233
    }
234
235
    public function setBuilding(?Building $building): PlanetField
236
    {
237
        $this->building = $building;
238
239
        return $this;
240
    }
241
242 6
    public function isDamaged(): bool
243
    {
244 6
        $building = $this->building;
245 6
        if ($building === null) {
246 5
            return false;
247
        }
248 6
        if ($this->isUnderConstruction()) {
249
            return false;
250
        }
251 6
        return $this->getIntegrity() !== $building->getIntegrity();
252
    }
253
254
    public function clearBuilding(): void
255
    {
256
        $this->setBuilding(null);
257
        $this->setIntegrity(0);
258
        $this->setActive(0);
259
    }
260
261 9
    public function getHost(): Colony|ColonySandbox
262
    {
263 9
        $colony = $this->colony;
264 9
        $sandbox = $this->sandbox;
265
266 9
        if ($colony === null && $sandbox === null) {
267
            throw new RuntimeException('Both colony and sandbox are null. Ensure one is set before calling getHost().');
268
        }
269
270 9
        return $colony ?? $sandbox;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $colony ?? $sandbox could return the type null which is incompatible with the type-hinted return Stu\Orm\Entity\Colony|Stu\Orm\Entity\ColonySandbox. Consider adding an additional type-check to rule them out.
Loading history...
271
    }
272
273
    public function setColony(Colony $colony): PlanetField
274
    {
275
        $this->colony = $colony;
276
        return $this;
277
    }
278
279
    public function setColonySandbox(ColonySandbox $sandbox): PlanetField
280
    {
281
        $this->sandbox = $sandbox;
282
        return $this;
283
    }
284
285 5
    public function getTerraforming(): ?Terraforming
286
    {
287 5
        return $this->terraforming;
288
    }
289
290
    public function setTerraforming(?Terraforming $terraforming): PlanetField
291
    {
292
        $this->terraforming = $terraforming;
293
294
        return $this;
295
    }
296
297 6
    public function getDayNightPrefix(int $timestamp): string
298
    {
299 6
        $twilightZone = $this->getHost()->getTwilightZone($timestamp);
300
301 6
        if ($twilightZone >= 0) {
302 6
            return $this->getFieldId() % $this->getHost()->getSurfaceWidth() >= $twilightZone ? 'n' : 't';
303
        }
304
305
        return $this->getFieldId() % $this->getHost()->getSurfaceWidth() < -$twilightZone ? 'n' : 't';
306
    }
307
308
    public function getBuildProgress(): int
309
    {
310
        $building = $this->getBuilding();
311
        if ($building === null) {
312
            return 0;
313
        }
314
315
        $start = $this->getBuildtime() - $building->getBuildTime();
316
        return time() - $start;
317
    }
318
319
    public function getOverlayWidth(): int
320
    {
321
        $building = $this->getBuilding();
322
        if ($building === null) {
323
            throw new RuntimeException('building is null');
324
        }
325
326
        $buildtime = $building->getBuildtime();
327
        $perc = max(0, @round((100 / $buildtime) * min($this->getBuildProgress(), $buildtime)));
328
        return (int) round((40 / 100) * $perc);
329
    }
330
331
    public function getPictureType(): string
332
    {
333
        return $this->getBuildingId() . "/" . ($this->getBuilding()?->getBuildingType() ?? 'UNDEFINED') . $this->getBuildingState();
334
    }
335
336
    public function isColonizeAble(): bool
337
    {
338
        return in_array($this->getFieldType(), $this->getHost()->getColonyClass()->getColonizeableFields());
339
    }
340
}
341