Completed
Push — trunk ( 76e427...0e7f64 )
by SuperNova.WS
05:41
created

Fleet   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 383
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 383
ccs 0
cts 148
cp 0
rs 6
c 0
b 0
f 0
wmc 55

25 Methods

Rating   Name   Duplication   Size   Complexity  
A getFleetOwnerRecord() 0 7 4
A _getContainer() 0 2 1
B setUnits() 0 16 6
A save() 0 2 1
A getShipListArray() 0 2 1
A calcShipLossByMultiplier() 0 9 2
A getShipCapacity() 0 6 2
A getUnitInfo() 0 6 2
B returnForce() 0 21 6
B setSourceFromPlanetRecord() 0 13 5
A calcTravelTimes() 0 16 3
A getCostInMetal() 0 2 1
A getCapacityActual() 0 9 2
A setSpeedPercentInTenth() 0 4 1
A getShipCostInMetal() 0 2 1
A getResourceList() 0 2 1
A changeResource() 0 2 1
A __construct() 0 2 1
A changeShipCount() 0 2 1
B setDestinationFromPlanetRecord() 0 11 6
A setMission() 0 5 1
A setFleetOwnerRecord() 0 5 2
A getShipCount() 0 2 1
A getShipsBasicCosts() 0 7 2
A isEmpty() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like Fleet 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 Fleet, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Created by Gorlum 18.04.2018 16:30
4
 */
5
6
namespace Fleet;
7
8
9
use Core\EntityDb;
10
use SN;
11
12
/**
13
 * Class Fleet
14
 * @package Fleet
15
 *
16
 * @property int|string $id                       - bigint     -
17
 * @property int|string $ownerId                  - bigint     - Fleet player owner ID
18
 * @property int        $fleet_mission            - int        -
19
 * @property int|string $fleet_amount             - bigint     -
20
 * @property string     $fleet_array              - mediumtext -
21
 * @property int        $timeLaunch               - int        - Fleet launched from source planet (unix)
22
 * @property int        $timeArrive               - int        - Time fleet arrive to destination (unix)
23
 * @property int        $timeEndStay              - int        - Time when fleet operation on destination complete (if any) (unix)
24
 * @property int        $timeReturn               - int        - Time fleet would return to source planet (unix)
25
 * @property int|string $fleet_start_planet_id    - bigint     -
26
 * @property int        $fleet_start_galaxy       - int        -
27
 * @property int        $fleet_start_system       - int        -
28
 * @property int        $fleet_start_planet       - int        -
29
 * @property int        $fleet_start_type         - int        -
30
 * @property int|string $fleet_end_planet_id      - bigint     -
31
 * @property int        $fleet_end_galaxy         - int        -
32
 * @property int        $fleet_end_system         - int        -
33
 * @property int        $fleet_end_planet         - int        -
34
 * @property int        $fleet_end_type           - int        -
35
 * @property int|string $fleet_resource_metal     - decimal    -
36
 * @property int|string $fleet_resource_crystal   - decimal    -
37
 * @property int|string $fleet_resource_deuterium - decimal    -
38
 * @property int|string $fleet_target_owner       - int        -
39
 * @property int|string $fleet_group              - varchar    -
40
 * @property int        $status                   - int        - Current fleet status: flying to destination; returning
41
 */
42
class Fleet extends EntityDb {
43
44
  /**
45
   * @var string $_activeClass
46
   */
47
  protected $_activeClass = '\\Fleet\\RecordFleet';
48
49
  /**
50
   * @var RecordFleet $_container
51
   */
52
  protected $_container;
53
54
  protected $_containerTranslateNames = [
55
    'ownerId' => 'fleet_owner',
56
57
    'timeLaunch'  => 'start_time',
58
    'timeArrive'  => 'fleet_start_time',
59
    'timeEndStay' => 'fleet_end_stay',
60
    'timeReturn'  => 'fleet_end_time',
61
62
    'status' => 'fleet_mess',
63
  ];
64
65
  /**
66
   * Information about ships
67
   *
68
   * @var array[] $shipInfo
69
   */
70
  protected static $shipInfo = [];
71
72
  protected $speedPercentTenth = 10;
73
74
  /**
75
   * @var null|array $ownerRecord
76
   */
77
  protected $ownerRecord = null;
78
  /**
79
   * @var null|array $sourcePlanet
80
   */
81
  protected $sourcePlanet = null;
82
83
84
  /**
85
   * Fleet constructor.
86
   *
87
   * @throws \Exception
88
   */
89
  public function __construct() {
90
    parent::__construct();
91
  }
92
93
  // Real fleet actions ------------------------------------------------------------------------------------------------
94
95
  /**
96
   * Forced return fleet to source planet
97
   *
98
   * @param int|string $byPlayerId
99
   *
100
   * @return bool
101
   */
102
  public function returnForce($byPlayerId) {
103
    if ($this->ownerId != $byPlayerId) {
104
      return false;
105
    }
106
107
    if ($this->status == FLEET_STATUS_RETURNING) {
108
      return true;
109
    }
110
111
//    $ReturnFlyingTime = ($this->timeEndStay != 0 && $this->timeArrive < SN_TIME_NOW ? $this->timeArrive : SN_TIME_NOW) - $this->timeLaunch + SN_TIME_NOW + 1;
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
112
    $timeToReturn = SN_TIME_NOW - $this->timeLaunch + 1;
113
    $ReturnFlyingTime = (!empty($this->timeEndStay) && $this->timeArrive < SN_TIME_NOW ? $this->timeArrive : SN_TIME_NOW) + $timeToReturn;
114
115
    // TODO - Those two lines should be removed - fleet times should be filtered on interface side
116
    $this->timeArrive = SN_TIME_NOW;
117
    !empty($this->timeEndStay) ? $this->timeEndStay = SN_TIME_NOW : false;
118
119
    $this->timeReturn = $ReturnFlyingTime;
120
    $this->status = FLEET_STATUS_RETURNING;
121
122
    return $this->dbUpdate();
123
  }
124
125
  // Service functions  -----------------------------------------------------------------------------------------------
126
127
  /**
128
   * @return RecordFleet
129
   */
130
  public function _getContainer() {
131
    return $this->_container;
132
  }
133
134
  /**
135
   * @param int $shipId
136
   *
137
   * @return array
138
   */
139
  protected static function getUnitInfo($shipId) {
140
    if (!isset(static::$shipInfo[$shipId])) {
141
      static::$shipInfo[$shipId] = get_unit_param($shipId);
142
    }
143
144
    return static::$shipInfo[$shipId];
145
  }
146
147
  /**
148
   * @param int $resourceId
149
   *
150
   * @return float[] - [(int)$shipId => (float)costInMetal]
151
   */
152
  public function getShipsBasicCosts($resourceId = RES_METAL) {
153
    $result = [];
154
    foreach ($this->getShipListArray() as $shipId => $shipAmount) {
155
      $result[$shipId] = getStackableUnitsCost([$shipId => 1], $resourceId);
156
    }
157
158
    return $result;
159
  }
160
161
  /**
162
   * Get cost of single ship in metal
163
   *
164
   * @param int $shipId
165
   *
166
   * @return int|float
167
   */
168
  public function getShipCostInMetal($shipId) {
169
    return getStackableUnitsCost([$shipId => 1], RES_METAL);
170
//
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% 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...
171
//    if(!isset(static::getUnitInfo($shipId)[P_COST_METAL])) {
172
//      static::$shipInfo[$shipId][P_COST_METAL] = get_unit_cost_in(static::getUnitInfo($shipId)[P_COST], RES_METAL);
173
//    }
174
//
175
//    return static::getUnitInfo($shipId)[P_COST_METAL];
176
  }
177
178
  /**
179
   * Get fleet cost in metal
180
   *
181
   * @return float|int
182
   */
183
  public function getCostInMetal() {
184
    return getStackableUnitsCost($this->getShipListArray(), RES_METAL);
185
//
0 ignored issues
show
Unused Code Comprehensibility introduced by
49% 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...
186
//    $result = 0;
187
//    foreach($this->getShipList() as $shipId => $amount) {
188
//      $result += $amount * $this->getShipCostInMetal($shipId);
189
//    }
190
//
191
//    return $result;
192
  }
193
194
  /**
195
   * Get single ship basic capacity
196
   *
197
   * @param int $shipId
198
   *
199
   * @return int|mixed
200
   */
201
  public function getShipCapacity($shipId) {
202
    if (!isset(static::getUnitInfo($shipId)[P_CAPACITY])) {
203
      static::$shipInfo[$shipId][P_CAPACITY] = 0;
204
    }
205
206
    return static::getUnitInfo($shipId)[P_CAPACITY];
207
  }
208
209
  /**
210
   * Get current fleet capacity counting loaded resources and fuel
211
   *
212
   * @return float|int
213
   */
214
  public function getCapacityActual() {
215
    $result = 0;
216
    foreach ($this->getShipListArray() as $shipId => $amount) {
217
      $result += $amount * $this->getShipCapacity($shipId);
218
    }
219
220
    $result = max(0, $result - array_sum($this->getResourceList()));
221
222
    return $result;
223
  }
224
225
  public function isEmpty() {
226
    return $this->getShipCount() < 1;
227
  }
228
229
  // Using RecordFleet functions ---------------------------------------------------------------------------------------
230
231
  /**
232
   * @param int   $shipSnId
233
   * @param float $shipCount
234
   *
235
   * @throws \Exception
236
   */
237
  public function changeShipCount($shipSnId, $shipCount) {
238
    $this->_getContainer()->changeShipCount($shipSnId, $shipCount);
239
  }
240
241
  /**
242
   * @param int   $resourceId
243
   * @param float $resourceCount
244
   *
245
   * @throws \Exception
246
   */
247
  public function changeResource($resourceId, $resourceCount) {
248
    $this->_getContainer()->changeResource($resourceId, $resourceCount);
249
  }
250
251
  /**
252
   * @return float[] - [shipSnId => $shipAmount]
253
   */
254
  public function getShipListArray() {
255
    return $this->_getContainer()->getShipList();
256
  }
257
258
  /**
259
   * @return float[] - [$resourceSnId => $resourceAmount]
260
   */
261
  public function getResourceList() {
262
    return $this->_getContainer()->getResourceList();
263
  }
264
265
  /**
266
   * @return float|int
267
   */
268
  public function getShipCount() {
269
    return array_sum($this->getShipListArray());
270
  }
271
272
  /**
273
   * @param float $multiplier
274
   *
275
   * @return int[]|float[]
276
   */
277
  public function calcShipLossByMultiplier($multiplier) {
278
    $result = [];
279
280
    foreach ($this->getShipListArray() as $unit_id => $unit_amount) {
281
      $shipsLost = ceil($unit_amount * $multiplier);
282
      $result[$unit_id] += $shipsLost;
283
    }
284
285
    return $result;
286
  }
287
288
  /**
289
   * @param int $missionId
290
   *
291
   * @return Fleet
292
   */
293
  public function setMission($missionId) {
294
    $this->fleet_mission = $missionId;
295
    $this->status = FLEET_STATUS_FLYING;
296
297
    return $this;
298
  }
299
300
  /**
301
   * @param array $playerRecord
302
   *
303
   * @return Fleet
304
   */
305
  public function setFleetOwnerRecord($playerRecord) {
306
    $this->ownerRecord = $playerRecord;
307
    !empty($this->ownerRecord['id']) ? $this->ownerId = $this->ownerRecord['id'] : false;
308
309
    return $this;
310
  }
311
312
  /**
313
   * @return array|false|null
314
   */
315
  public function getFleetOwnerRecord() {
316
    if (!isset($this->ownerRecord['id']) && !empty($this->ownerId)) {
317
      // Trying to get owner record by id
318
      empty($this->ownerRecord = db_user_by_id($this->ownerId)) ? $this->ownerRecord = null : false;
0 ignored issues
show
Deprecated Code introduced by
The function db_user_by_id() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

318
      empty($this->ownerRecord = /** @scrutinizer ignore-deprecated */ db_user_by_id($this->ownerId)) ? $this->ownerRecord = null : false;
Loading history...
Documentation Bug introduced by
It seems like db_user_by_id($this->ownerId) of type false is incompatible with the declared type null|array of property $ownerRecord.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug introduced by
It seems like $this->ownerId can also be of type string; however, parameter $user_id_unsafe of db_user_by_id() does only seem to accept integer|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

318
      empty($this->ownerRecord = db_user_by_id(/** @scrutinizer ignore-type */ $this->ownerId)) ? $this->ownerRecord = null : false;
Loading history...
319
    }
320
321
    return $this->ownerRecord;
322
  }
323
324
  /**
325
   * @param array $from
326
   *
327
   * @return Fleet
328
   */
329
  public function setSourceFromPlanetRecord($from) {
330
    empty($this->ownerId) && !empty($from['id_owner']) ? $this->ownerId = $from['id_owner'] : false;
331
332
    $this->fleet_start_planet_id = !empty($from['id']) && intval($from['id']) ? $from['id'] : null;
333
334
    $this->fleet_start_galaxy = $from['galaxy'];
335
    $this->fleet_start_system = $from['system'];
336
    $this->fleet_start_planet = $from['planet'];
337
    $this->fleet_start_type = $from['planet_type'];
338
339
    $this->sourcePlanet = $from;
340
341
    return $this;
342
  }
343
344
345
  /**
346
   * @param $to
347
   *
348
   * @return Fleet
349
   */
350
  public function setDestinationFromPlanetRecord($to) {
351
    empty($this->fleet_target_owner) ? $this->fleet_target_owner = !empty($to['id_owner']) && intval($to['id_owner']) ? $to['id_owner'] : 0 : false;
352
353
    $this->fleet_end_planet_id = !empty($to['id']) && intval($to['id']) ? $to['id'] : null;
354
355
    $this->fleet_end_galaxy = $to['galaxy'];
356
    $this->fleet_end_system = $to['system'];
357
    $this->fleet_end_planet = $to['planet'];
358
    $this->fleet_end_type = $to['planet_type'];
359
360
    return $this;
361
  }
362
363
  /**
364
   * @param array $fleet - list of units [(int)unitId => (float)unitAmount]
365
   *
366
   * @return Fleet
367
   * @throws \Exception
368
   */
369
  public function setUnits($fleet) {
370
    foreach ($fleet as $unit_id => $amount) {
371
      if (!$amount || !$unit_id) {
372
        continue;
373
      }
374
375
      if (in_array($unit_id, sn_get_groups('fleet'))) {
376
        /** @noinspection PhpUnhandledExceptionInspection */
377
        $this->changeShipCount($unit_id, $amount);
378
      } elseif (in_array($unit_id, sn_get_groups('resources_loot'))) {
379
        /** @noinspection PhpUnhandledExceptionInspection */
380
        $this->changeResource($unit_id, $amount);
381
      }
382
    }
383
384
    return $this;
385
  }
386
387
  /**
388
   * @param int $speedPercentTenth - fleet speed percent in 10% from 1..10 - i.e. 1 = 10%, 10 = 100%
389
   *
390
   * @return Fleet
391
   */
392
  public function setSpeedPercentInTenth($speedPercentTenth) {
393
    $this->speedPercentTenth = max(0, min(10, intval($speedPercentTenth)));
394
395
    return $this;
396
  }
397
398
  /**
399
   * @param int $launchTime   - unix timestamp when fleet leave source planet
400
   * @param int $stayDuration - seconds how long fleet should stay executing mission task (i.e. HOLD or EXPLORE)
401
   *
402
   * @return array
403
   */
404
  public function calcTravelTimes($launchTime = SN_TIME_NOW, $stayDuration = 0) {
405
    $this->timeLaunch = $launchTime;
406
407
    $travel_data = flt_travel_data(
408
      $this->getFleetOwnerRecord(),
409
      ['galaxy' => $this->fleet_start_galaxy, 'system' => $this->fleet_start_system, 'planet' => $this->fleet_start_planet,],
410
      ['galaxy' => $this->fleet_end_galaxy, 'system' => $this->fleet_end_system, 'planet' => $this->fleet_end_planet,],
411
      $this->getShipListArray(),
412
      $this->speedPercentTenth
413
    );
414
415
    $this->timeArrive = $this->timeLaunch + $travel_data['duration'];
416
    $this->timeEndStay = $this->fleet_mission == MT_EXPLORE || $this->fleet_mission == MT_HOLD ? $this->timeArrive + $stayDuration : 0;
417
    $this->timeReturn = $this->timeArrive + $stayDuration + $travel_data['duration'];
418
419
    return $travel_data;
420
  }
421
422
423
  public function save() {
424
    return parent::save(); // TODO: Change the autogenerated stub
425
  }
426
427
}
428