Test Failed
Push — trunk ( 132e87...b3f953 )
by SuperNova.WS
11:54
created

FleetDispatchEvent::__construct()   C

Complexity

Conditions 16
Paths 96

Size

Total Lines 80
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 16
eloc 46
nc 96
nop 2
dl 0
loc 80
rs 5.5666
c 1
b 0
f 0

How to fix   Long Method    Complexity   

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 /** @noinspection PhpUnnecessaryCurlyVarSyntaxInspection, PhpCastIsUnnecessaryInspection, PhpDeprecationInspection */
2
3
/** Created by Gorlum 27.10.2024 18:42 */
4
5
namespace Fleet;
6
7
use mysqli_result;
8
use Planet\DBStaticPlanet;
9
use SN;
10
11
/**
12
 * @property array      $fleet          Fleet on which event time happens
13
 * @property string     $eventTimeStamp When event happened in timeline
14
 * @property string     $event          Event type
15
 *
16
 * @property ?int       $srcPlanetId
17
 * @property bool|array $srcPlanetRow
18
 * @property ?int       $srcPlanetOwnerId
19
 * @property ?int       $dstPlanetId
20
 * @property bool|array $dstPlanetRow
21
 * @property ?int       $dstPlanetOwnerId
22
 *
23
 * @property array      $missionInfoNew
24
 * @property int        $missionId
25
 */
26
class FleetDispatchEvent {
27
  const IS_ATTACK = 'isAttack';
28
  const IS_TRANSPORT = 'isTransport';
29
30
  const F_FLEET_ID = 'fleet_id';
31
  const F_FLEET_OWNER_ID = 'fleet_owner';
32
  const F_PLANET_ID = 'id';
33
  const F_PLANET_OWNER_ID = 'id_owner';
34
  const IS_LOCK_SOURCE = 'isLockSource';
35
36
  /** @var array[] $sn_groups_mission */
37
  public static $sn_groups_mission = [];
38
  /** @var int[] $userIdsToLock */
39
  public $userIdsToLock = [];
40
  /** @var int[] $planetIdsToLock */
41
  public $planetIdsToLock = [];
42
  /** @var int[] $fleetIdsToLock */
43
  public $fleetIdsToLock = [];
44
45
  public static $MISSIONS = [
46
    MT_ATTACK    => [self::IS_TRANSPORT => false, self::IS_ATTACK => true,],
47
    MT_AKS       => [self::IS_TRANSPORT => false, self::IS_ATTACK => true,],
48
    MT_DESTROY   => [self::IS_TRANSPORT => false, self::IS_ATTACK => true,],
49
    MT_HOLD      => [self::IS_TRANSPORT => false,],
50
    MT_SPY       => [self::IS_TRANSPORT => false, self::IS_LOCK_SOURCE => true, 'AJAX' => true,],
51
    MT_TRANSPORT => [self::IS_TRANSPORT => true, self::IS_LOCK_SOURCE => true,],
52
    MT_RELOCATE  => [self::IS_TRANSPORT => true, self::IS_LOCK_SOURCE => true,],
53
    MT_RECYCLE   => [self::IS_TRANSPORT => false, 'AJAX' => true,],
54
    MT_EXPLORE   => [self::IS_TRANSPORT => false,],
55
    MT_COLONIZE  => [self::IS_TRANSPORT => true,],
56
    MT_MISSILE   => [self::IS_TRANSPORT => false, 'AJAX' => true,],
57
  ];
58
59
  public function __construct($fleetRow, $eventType) {
60
    if (empty(self::$sn_groups_mission)) {
61
      self::$sn_groups_mission = sn_get_groups('missions');
62
    }
63
64
    $this->fleet = $fleetRow;
65
    $this->event = $eventType;
66
67
    $this->srcPlanetOwnerId = $fleetRow[self::F_FLEET_OWNER_ID];
68
69
    $this->missionId      = (int)$this->fleet[FleetDispatcher::F_FLEET_MISSION];
70
    $this->missionInfoNew = self::$MISSIONS[$this->missionId];
71
72
    $this->eventTimeStamp = (int)$this->fleet[$this->event === EVENT_FLT_ARRIVE ? 'fleet_start_time' :
73
      ($this->event === EVENT_FLT_ACCOMPLISH ? 'fleet_end_stay' : /* EVENT_FLT_RETURN */
74
        'fleet_end_time')];
75
76
    /** @var Fleet $fleetObject */
77
    $fleetObject = (object)$this->fleet;
78
79
    // Always locking flying fleet and fleet owner
80
    $this->userIdsToLock   = [(int)$fleetObject->fleet_owner ?: 0 => true,];
0 ignored issues
show
Documentation Bug introduced by
It seems like array((int)$fleetObject-...eet_owner ?: 0 => true) of type array<integer,true> is incompatible with the declared type integer[] of property $userIdsToLock.

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...
81
    $this->fleetIdsToLock  = [(int)$fleetObject->fleet_id => true,];
0 ignored issues
show
Documentation Bug introduced by
It seems like array((int)$fleetObject->fleet_id => true) of type array<integer,true> is incompatible with the declared type integer[] of property $fleetIdsToLock.

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...
82
    $this->planetIdsToLock = [];
83
84
    // Some locks make sense only on specific event types
85
    if ($this->event === EVENT_FLT_RETURN) {
86
      // There is no means or ways how returning fleet can influence other planet(s) then starting one
87
      $isLockSource = true;
88
    } else {
89
      // Locking destination planet always
90
      // There are no means or sense to make a mission which does not affect destination planet
91
      $this->getDstPlanetRowFromFleet();
92
      // Locking dest planet
93
      $this->planetIdsToLock[$this->dstPlanetId] = true;
94
      // Locking destination planet always implies locking destination user
95
      // Locking planet owner ID
96
      $this->userIdsToLock[$this->dstPlanetOwnerId] = true;
97
98
      // If the fleet is a part of existing fleet group - locking also fleets in group and their respected owners
99
      // Only doing it for EVENT_FLT_ARRIVE - currently no other event types does trigger fleet group actions
100
      if (!empty($fleetObject->fleet_group) && $this->event === EVENT_FLT_ARRIVE) {
101
        $fleetGroupId = (int)$fleetObject->fleet_group;
102
        foreach (DbFleetStatic::db_fleet_list("`fleet_group` = {$fleetGroupId}") as $fleetInGroup) {
103
          $this->userIdsToLock[(int)$fleetInGroup[self::F_FLEET_OWNER_ID] ?: 0] = true;
104
          $this->fleetIdsToLock[(int)$fleetInGroup[self::F_FLEET_ID] ?: 0]      = true;
105
        }
106
      }
107
108
      // We may need to lock source planet/user for some extra info such as planet name/username, coordinates etc
109
      $isLockSource = !empty($this->missionInfoNew[self::IS_LOCK_SOURCE]);
110
    }
111
112
    if ($isLockSource) {
113
      $this->getSrcPlanetRowFromFleet();
114
      $this->planetIdsToLock[$this->srcPlanetId]    = true;
115
      $this->userIdsToLock[$this->srcPlanetOwnerId] = true;
116
    }
117
118
    if (!empty($this->missionInfoNew[self::IS_ATTACK])) {
119
      $fleetsOnHold = DbFleetStatic::fleet_list_on_hold(
120
        $fleetObject->fleet_end_galaxy,
121
        $fleetObject->fleet_end_system,
122
        $fleetObject->fleet_end_planet,
123
        $fleetObject->fleet_end_type,
124
        $this->eventTimeStamp
125
      );
126
      foreach ($fleetsOnHold as $aFleet) {
127
        $this->userIdsToLock[(int)$aFleet[self::F_FLEET_OWNER_ID] ?: 0] = true;
128
        $this->fleetIdsToLock[(int)$aFleet[self::F_FLEET_ID] ?: 0]      = true;
129
      }
130
    }
131
132
    unset($this->userIdsToLock[0]);
133
    unset($this->planetIdsToLock[0]);
134
    unset($this->fleetIdsToLock[0]);
135
136
    $this->userIdsToLock   = array_keys($this->userIdsToLock);
137
    $this->planetIdsToLock = array_keys($this->planetIdsToLock);
138
    $this->fleetIdsToLock  = array_keys($this->fleetIdsToLock);
139
  }
140
141
  /**
142
   * LOCK - Lock all records which can be used with mission
143
   *
144
   * @return array|bool|mysqli_result|null
145
   */
146
  public function lockEventRecords() {
147
    // $query = [];
148
    $locks = [];
149
150
    if (!empty($this->userIdsToLock)) {
151
      $locks['users'] = $this->userIdsToLock;
152
//      /** @noinspection SqlResolve */
153
//      $query[] = "SELECT 1 FROM `{{users}}` WHERE `id` IN (" . implode(',', $this->userIdsToLock) . ") FOR UPDATE";
154
    }
155
    if (!empty($this->planetIdsToLock)) {
156
      $locks['planets'] = $this->planetIdsToLock;
157
//      /** @noinspection SqlResolve */
158
//      $query[] = "SELECT 1 FROM `{{planets}}` WHERE `id` IN (" . implode(',', $this->planetIdsToLock) . ") FOR UPDATE";
159
    }
160
    if (!empty($this->fleetIdsToLock)) {
161
      $locks['fleets'] = $this->fleetIdsToLock;
162
//      /** @noinspection SqlResolve */
163
//      $query[] = "SELECT 1 FROM `{{fleets}}` WHERE `fleet_id` IN (" . implode(',', $this->fleetIdsToLock) . ") FOR UPDATE";
164
    }
165
166
    // Really - no checks here. We should lock at least flying fleet and fleet owner
167
168
//    return doquery(implode(' UNION ', $query));
169
    return SN::$gc->db->lockRecords($locks);
170
  }
171
172
  public static function sortEvents(&$eventList) {
173
    uasort($eventList, function (FleetDispatchEvent $a, FleetDispatchEvent $b) {
174
      return
175
        // Сравниваем время флотов - кто раньше, тот и первый обрабатывается
176
          $a->eventTimeStamp > $b->eventTimeStamp ? 1 : ($a->eventTimeStamp < $b->eventTimeStamp ? -1 :
177
          // Если время - одинаковое, сравниваем события флотов
178
          // Если события - одинаковые, то флоты равны
179
          ($a->event == $b->event ? 0 :
180
            // Если события разные - первыми считаем прибывающие флоты
181
            ($a->event == EVENT_FLT_ARRIVE ? 1 : ($b->event == EVENT_FLT_ARRIVE ? -1 :
182
              // Если нет прибывающих флотов - дальше считаем флоты, которые закончили миссию
183
              ($a->event == EVENT_FLT_ACCOMPLISH ? 1 : ($b->event == EVENT_FLT_ACCOMPLISH ? -1 :
184
                // Если нет флотов, закончивших задание - остались возвращающиеся флоты, которые равны между собой
185
                // TODO: Добавить еще проверку по ID флота и/или времени запуска - что бы обсчитывать их в порядке запуска
186
                (
187
                0 // Вообще сюда доходить не должно - будет отсекаться на равенстве событий
188
                )
189
              ))
190
            ))
191
          )
192
        );
193
    });
194
  }
195
196
  /**
197
   */
198
  public function refreshMissionData() {
199
    if (!empty($this->srcPlanetId) && !empty($this->srcPlanetOwnerId)) {
200
//       $this->srcPlanetRow = DBStaticPlanet::db_planet_by_vector($this->fleet, 'fleet_start_');
201
      $updateResult = sys_o_get_updated($this->srcPlanetOwnerId, $this->srcPlanetId, $this->eventTimeStamp);
0 ignored issues
show
Bug introduced by
$this->eventTimeStamp of type string is incompatible with the type integer expected by parameter $UpdateTime of sys_o_get_updated(). ( Ignorable by Annotation )

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

201
      $updateResult = sys_o_get_updated($this->srcPlanetOwnerId, $this->srcPlanetId, /** @scrutinizer ignore-type */ $this->eventTimeStamp);
Loading history...
202
203
      $this->updateSrcPlanetRow($updateResult['planet']);
204
    }
205
206
    if (!empty($this->dstPlanetId) && !empty($this->dstPlanetOwnerId)) {
207
      $updateResult = sys_o_get_updated($this->dstPlanetOwnerId, $this->dstPlanetId, $this->eventTimeStamp);
208
209
      $this->updateDstPlanetRow($updateResult['planet']);
210
    }
211
  }
212
213
  /**
214
   * @return array|false
215
   */
216
  public function refreshFleet() {
217
    $this->fleet = DbFleetStatic::db_fleet_get($this->fleet[self::F_FLEET_ID]);
0 ignored issues
show
Documentation Bug introduced by
It seems like Fleet\DbFleetStatic::db_...leet[self::F_FLEET_ID]) can also be of type false. However, the property $fleet is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
218
219
    return $this->fleet;
220
  }
221
222
  public function getSrcPlanetRowFromFleet() {
223
    $this->srcPlanetRow = DBStaticPlanet::db_planet_by_vector($this->fleet, 'fleet_start_');
224
225
    $this->updateSrcPlanetRow($this->srcPlanetRow);
0 ignored issues
show
Bug introduced by
It seems like $this->srcPlanetRow can also be of type boolean; however, parameter $srcPlanetRow of Fleet\FleetDispatchEvent::updateSrcPlanetRow() does only seem to accept 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

225
    $this->updateSrcPlanetRow(/** @scrutinizer ignore-type */ $this->srcPlanetRow);
Loading history...
226
227
    return $this->srcPlanetRow;
228
  }
229
230
  /**
231
   * @param array $srcPlanetRow
232
   *
233
   * @return array|bool
234
   */
235
  public function updateSrcPlanetRow($srcPlanetRow) {
236
//    $this->srcPlanetRow = is_array($srcPlanetRow) ? $srcPlanetRow : DBStaticPlanet::db_planet_by_vector($this->fleet, 'fleet_start_');
237
    $this->srcPlanetRow = $srcPlanetRow;
238
239
    $this->srcPlanetId = !empty($this->srcPlanetRow[self::F_PLANET_ID]) ? (int)$this->srcPlanetRow[self::F_PLANET_ID] : 0;
240
    // Starting planet can change owner while fleet mission - and even change planet ID
241
    // It can happen due to teleport shenanigans or because of planet capturing (in certain game modes)
242
    $this->srcPlanetOwnerId = !empty($this->srcPlanetRow[self::F_PLANET_OWNER_ID]) ? (int)$this->srcPlanetRow[self::F_PLANET_OWNER_ID] : $this->srcPlanetOwnerId;
243
244
    return $this->srcPlanetRow;
245
  }
246
247
248
  public function getDstPlanetRowFromFleet() {
249
    $this->dstPlanetRow = DBStaticPlanet::db_planet_by_vector($this->fleet, 'fleet_end_');
250
251
    $this->updateDstPlanetRow($this->dstPlanetRow);
0 ignored issues
show
Bug introduced by
It seems like $this->dstPlanetRow can also be of type boolean; however, parameter $dstPlanetRow of Fleet\FleetDispatchEvent::updateDstPlanetRow() does only seem to accept array|null, 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

251
    $this->updateDstPlanetRow(/** @scrutinizer ignore-type */ $this->dstPlanetRow);
Loading history...
252
253
    return $this->dstPlanetRow;
254
  }
255
256
  /**
257
   * @param ?array $dstPlanetRow
258
   *
259
   * @return array|bool|null
260
   */
261
  public function updateDstPlanetRow($dstPlanetRow = null) {
262
    $this->dstPlanetRow = $dstPlanetRow;
263
264
    $this->dstPlanetId = !empty($this->dstPlanetRow[self::F_PLANET_ID]) ? (int)$this->dstPlanetRow[self::F_PLANET_ID] : 0;
265
    // Retrieving destination owner ID
266
    $this->dstPlanetOwnerId = !empty($this->dstPlanetRow[self::F_PLANET_OWNER_ID]) ? (int)$this->dstPlanetRow[self::F_PLANET_OWNER_ID] : 0;
267
268
    return $this->dstPlanetRow;
269
  }
270
271
}
272