Test Failed
Push — trunk ( e02d87...314b8c )
by SuperNova.WS
07:20
created

FleetDispatcher::getLock()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 3
nop 0
dl 0
loc 22
rs 9.9
c 0
b 0
f 0
ccs 0
cts 14
cp 0
crap 12
1
<?php
2
/**
3
 * Created by Gorlum 15.06.2017 4:12
4
 */
5
6
namespace Fleet;
7
8
use Core\Scheduler\Lock;
9
use SN;
10
use debug;
11
use classConfig;
12
use Core\GlobalContainer;
13
use DBAL\OldDbChangeSet;
14
use Planet\DBStaticPlanet;
15
16
/**
17
 * Class Fleet\FleetDispatcher
18
 *
19
 */
20
class FleetDispatcher {
21
  const TASK_COMPLETE = 0;
22
  const TASK_TERMINATED = 1;
23
  const TASK_ALREADY_LOCKED = -1;
24
  /**
25
   * @var GlobalContainer $gc
26
   */
27
  protected $gc;
28
29
  /**
30
   * @var classConfig $gameConfig
31
   */
32
  protected $gameConfig;
33
34
  /**
35
   * @var debug $debug
36
   */
37
  protected $debug;
38
39
  /**
40
   * List of timed events
41
   *
42
   * [
43
   *   'start'
44
   *   'finish'
45
   * ]
46
   *
47
   * @var float[] $timers
48
   */
49
  protected $timers;
50
51
52
  public function __construct(GlobalContainer $gc) {
53
    $this->gc = $gc;
54
55
    $this->gameConfig = $gc->config;
56
    $this->debug      = $gc->debug;
57
  }
58
59
  /**
60
   * @deprecated
61
   */
62
  public function dispatch() {
63
    if (
64
      SN::$options[PAGE_OPTION_FLEET_UPDATE_SKIP]
65
      ||
66
      SN::gameIsDisabled()
67
      ||
68
      !$this->getLockOld()
0 ignored issues
show
Deprecated Code introduced by
The function Fleet\FleetDispatcher::getLockOld() 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

68
      !/** @scrutinizer ignore-deprecated */ $this->getLockOld()
Loading history...
69
    ) {
70
      return;
71
    }
72
73
    $this->flt_flying_fleet_handler();
74
75
    $this->releaseLock();
76
77
    set_time_limit(60);
78
  }
79
80
81
  /**
82
   * @return bool
83
   * @deprecated
84
   */
85
  protected function getLockOld() {
86
    sn_db_transaction_start();
87
88
    // Watchdog timer
89
    if ($this->gameConfig->db_loadItem('fleet_update_lock')) {
90
//      var_dump($this->gameConfig->db_loadItem('fleet_update_lock'));
91
//      var_dump(SN_TIME_NOW - strtotime($this->gameConfig->fleet_update_lock));
92
//      if (SN_TIME_NOW - strtotime($this->gameConfig->fleet_update_lock) <= mt_rand(90, 120)) {
93
      if (SN_TIME_NOW - strtotime($this->gameConfig->fleet_update_lock) <= mt_rand(20, 40)) {
94
        sn_db_transaction_rollback();
95
96
        return false;
97
      } else {
98
        $this->debug->warning('Fleet dispatcher was locked too long - watchdog unlocked', 'FFH Error', 504);
99
      }
100
    }
101
102
    $this->gameConfig->db_saveItem('fleet_update_last', SN_TIME_SQL);
103
    $this->gameConfig->db_saveItem('fleet_update_lock', SN_TIME_SQL);
104
    sn_db_transaction_commit();
105
106
    return true;
107
  }
108
109
  /**
110
   * @deprecated
111
   */
112
  protected function releaseLock() {
113
    sn_db_transaction_start();
114
    $this->gameConfig->db_saveItem('fleet_update_lock', '');
115
    sn_db_transaction_commit();
116
  }
117
118
  /**
119
   * Gets active fleets on current tick for Flying Fleet Handler
120
   *
121
   * @return array
122
   */
123
  protected function fleet_list_current_tick() {
124
    return DbFleetStatic::db_fleet_list(
125
      "
126
    (`fleet_start_time` <= " . SN_TIME_NOW . " AND `fleet_mess` = 0)
127
    OR
128
    (`fleet_end_stay` <= " . SN_TIME_NOW . " AND `fleet_end_stay` > 0 AND `fleet_mess` = 0)
129
    OR
130
    (`fleet_end_time` <= " . SN_TIME_NOW . ")"
131
      , DB_SELECT_PLAIN
132
    );
133
  }
134
135
136
  // ------------------------------------------------------------------
137
  public function flt_flying_fleet_handler() {
138
    /*
139
140
    [*] Нужно ли заворачивать ВСЕ в одну транзакцию?
141
        С одной стороны - да, что бы данные были гарантированно на момент снапшота
142
        С другой стороны - нет, потому что при большой активности это все будет блокировать слишком много рядов, да и таймаут будет большой для ожидания всего разлоченного
143
        Стоит завернуть каждую миссию отдельно? Это сильно увеличит количество запросов, зато так же сильно снизит количество блокировок.
144
145
        Resume: НЕТ! Надо оставить все в одной транзакции! Так можно будет поддерживать consistency кэша. Там буквально сантисекунды блокировки
146
147
    [*] Убрать кэшированние данных о пользователях и планета. Офигенно освободит память - проследить!
148
        НЕТ! Считать, скольким флотам нужна будет инфа и кэшировать только то, что используется больше раза!
149
        Заодно можно будет исключить перересчет очередей/ресурсов - сильно ускорит дело!
150
        Особенно будет актуально, когда все бонусы будут в одной таблице
151
        Ну и никто не заставляет как сейчас брать ВСЕ из таблицы - только по полям. Гемор, но не сильный - сделать запрос по группам sn_data
152
        И писать в БД только один раз результат
153
154
    [*] Нужно ли на этом этапе знать полную информацию о флотах?
155
        Заблокировать флоты можно и неполным запросом. Блокировка флотов - это не страшно. Ну, не пройдет одна-две отмены - так никто и не гарантировал реалтайма!
156
        С одной стороны - да, уменьшит количество запросов
157
        С другой стооны - расход памяти
158
        Все равно надо будет знать полную инфу о флоте в момент обработки
159
160
    [*] Сделать тестовую БД для расчетов
161
162
    [*] Но не раньше, чем переписать все миссии
163
164
    */
165
//    $this->log_file('Dispatch started');
166
167
    // Trying to acquire lock for current task
168
    $runLock = $this->buildLock();
169
    if (!$runLock->attemptLock()) {
170
//      $this->log_file('Dispatch stopped: lock ' . $runLock->isLocked() .'s' );
171
      return self::TASK_ALREADY_LOCKED;
172
    }
173
    register_shutdown_function(function () use ($runLock) {
174
//      $this->log_file('Shutting down');
175
      $timeLock = $runLock->isLocked();
176
      if ($timeLock > 0 || $timeLock === 0) {
177
        $runLock->unLock(true);
178
        $this->logTermination(0, 0, 0, 0, 0);
179
//        $this->log_file('UNLOCKING');
180
      }
181
182
//      $this->log_file(SN::$gc->config->pass()->fleet_update_run_lock);
183
//      $this->log_file('ALL RELEASED');
184
    });
185
186
    $result = self::TASK_COMPLETE;
187
188
    set_time_limit(max(3, SN::$gc->config->fleet_update_max_run_time - 3));
189
190
    $workBegin = microtime(true);
191
//log_file('Начинаем обсчёт флотов');
192
193
//log_file('Обсчёт ракет');
194
    sn_db_transaction_start();
195
    coe_o_missile_calculate();
196
    sn_db_transaction_commit();
197
198
    $fleet_list       = array();
199
    $fleet_event_list = array();
200
    $missions_used    = array();
201
202
    $fleet_list_current_tick = $this->fleet_list_current_tick();
203
    foreach ($fleet_list_current_tick as $fleet_row) {
204
//      set_time_limit(15);
205
206
      // TODO - Унифицировать код с темплейтным разбором эвентов на планете!
207
      $fleet_list[$fleet_row['fleet_id']]         = $fleet_row;
208
      $missions_used[$fleet_row['fleet_mission']] = 1;
209
      if ($fleet_row['fleet_start_time'] <= SN_TIME_NOW && $fleet_row['fleet_mess'] == 0) {
210
        $fleet_event_list[] = array(
211
          'fleet_row'   => &$fleet_list[$fleet_row['fleet_id']],
212
          'fleet_time'  => $fleet_list[$fleet_row['fleet_id']]['fleet_start_time'],
213
          'fleet_event' => EVENT_FLT_ARRIVE,
214
        );
215
      }
216
217
      if ($fleet_row['fleet_end_stay'] > 0 && $fleet_row['fleet_end_stay'] <= SN_TIME_NOW && $fleet_row['fleet_mess'] == 0) {
218
        $fleet_event_list[] = array(
219
          'fleet_row'   => &$fleet_list[$fleet_row['fleet_id']],
220
          'fleet_time'  => $fleet_list[$fleet_row['fleet_id']]['fleet_end_stay'],
221
          'fleet_event' => EVENT_FLT_ACOMPLISH,
222
        );
223
      }
224
225
      if ($fleet_row['fleet_end_time'] <= SN_TIME_NOW) {
226
        $fleet_event_list[] = array(
227
          'fleet_row'   => &$fleet_list[$fleet_row['fleet_id']],
228
          'fleet_time'  => $fleet_list[$fleet_row['fleet_id']]['fleet_end_time'],
229
          'fleet_event' => EVENT_FLT_RETURN,
230
        );
231
      }
232
    }
233
234
//    set_time_limit(5);
235
236
//log_file('Сортировка и подгрузка модулей');
237
    uasort($fleet_event_list, array($this, 'flt_flyingFleetsSort'));
238
//  unset($fleets_query);
239
240
// TODO: Грузить только используемые модули из $missions_used
241
    $mission_files = array(
242
      MT_ATTACK  => 'flt_mission_attack',
243
      MT_AKS     => 'flt_mission_attack',
244
      // MT_DESTROY => 'flt_mission_destroy.php',
245
      MT_DESTROY => 'flt_mission_attack',
246
247
      MT_TRANSPORT => 'flt_mission_transport',
248
      MT_RELOCATE  => 'flt_mission_relocate',
249
      MT_HOLD      => 'flt_mission_hold',
250
      MT_SPY       => '',
251
      MT_COLONIZE  => 'flt_mission_colonize',
252
      MT_RECYCLE   => 'flt_mission_recycle',
253
//    MT_MISSILE => 'flt_mission_missile.php',
254
      MT_EXPLORE   => 'flt_mission_explore',
255
    );
256
    foreach ($missions_used as $mission_id => $cork) {
257
      if (empty($mission_files[$mission_id])) {
258
        continue;
259
      }
260
261
      require_once(SN_ROOT_PHYSICAL . "includes/includes/{$mission_files[$mission_id]}" . DOT_PHP_EX);
262
    }
263
264
//log_file('Обработка миссий');
265
    $lastEventBegin  = microtime(true);
266
    $lastMission     = MT_NONE;
267
    $eventsProcessed = 0;
268
    $lastEvent       = EVENT_FLEET_NONE;
269
270
    $sn_groups_mission = sn_get_groups('missions');
271
    foreach ($fleet_event_list as $fleet_event) {
272
      $lastEventEnd = microtime(true);
273
      // Watchdog timer
274
      // If flying fleet handler works more then 10 seconds - stopping it
275
      // Let next run handle rest of fleets
276
      $workTime = microtime(true) - $workBegin;
277
      if ($workTime > GAME_FLEET_HANDLER_MAX_TIME) {
278
        $this->logTermination($workTime, $eventsProcessed, $lastMission, $lastEvent, $lastEventEnd - $lastEventBegin);
279
280
        $result = self::TASK_TERMINATED;
281
        break;
282
      }
283
284
      // TODO: Указатель тут потом сделать
285
      // TODO: СЕЙЧАС НАДО ПРОВЕРЯТЬ ПО БАЗЕ - А ЖИВОЙ ЛИ ФЛОТ?!
286
      $fleet_row = $fleet_event['fleet_row'];
287
      if (!$fleet_row) {
288
        // Fleet was destroyed in course of previous actions
289
        continue;
290
      }
291
292
      $lastEventBegin = microtime(true);
293
      $lastMission    = $fleet_row['fleet_mission'];
294
      $lastEvent      = $fleet_event['fleet_event'];
295
      $eventsProcessed++;
296
297
//log_file('Миссия');
298
      // TODO Обернуть всё в транзакции. Начинать надо заранее, блокируя все таблицы внутренним локом SELECT 1 FROM {{users}}
299
      sn_db_transaction_start();
300
      // а текущее время
301
      SN::$gc->config->db_saveItem('fleet_update_last', date(FMT_DATE_TIME_SQL, time()));
302
303
      $mission_data = $sn_groups_mission[$fleet_row['fleet_mission']];
304
      // Формируем запрос, блокирующий сразу все нужные записи
305
306
      DbFleetStatic::db_fleet_lock_flying($fleet_row['fleet_id'], $mission_data);
307
308
//    $fleet_row = doquery("SELECT * FROM {{fleets}} WHERE fleet_id = {$fleet_row['fleet_id']} FOR UPDATE", true);
309
      $fleet_row = DbFleetStatic::db_fleet_get($fleet_row['fleet_id']);
310
      if (!$fleet_row || empty($fleet_row)) {
311
        // Fleet was destroyed in course of previous actions
312
        sn_db_transaction_commit();
313
        continue;
314
      }
315
316
      if ($fleet_event['fleet_event'] == EVENT_FLT_RETURN) {
317
        // Fleet returns to planet
318
        RestoreFleetToPlanet($fleet_row, true, false, true);
0 ignored issues
show
Deprecated Code introduced by
The function RestoreFleetToPlanet() 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
        /** @scrutinizer ignore-deprecated */ RestoreFleetToPlanet($fleet_row, true, false, true);
Loading history...
319
        sn_db_transaction_commit();
320
        continue;
321
      }
322
323
      if ($fleet_event['fleet_event'] == EVENT_FLT_ARRIVE && $fleet_row['fleet_mess'] != 0) {
324
        // При событии EVENT_FLT_ARRIVE флот всегда должен иметь fleet_mess == 0
325
        // В противном случае это означает, что флот уже был обработан ранее - например, при САБе
326
        sn_db_transaction_commit();
327
        continue;
328
      }
329
330
      // TODO: Здесь тоже указатели
331
      // TODO: Кэширование
332
      // TODO: Выбирать только нужные поля
333
334
      // шпионаж не дает нормальный ID fleet_end_planet_id 'dst_planet'
335
      $mission_data = array(
336
        'fleet'       => &$fleet_row,
337
        'dst_user'    => $mission_data['dst_user'] || $mission_data['dst_planet'] ? db_user_by_id($fleet_row['fleet_target_owner'], true) : null,
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

337
        'dst_user'    => $mission_data['dst_user'] || $mission_data['dst_planet'] ? /** @scrutinizer ignore-deprecated */ db_user_by_id($fleet_row['fleet_target_owner'], true) : null,
Loading history...
338
        // TODO 'dst_planet' => $mission_data['dst_planet'] ? db_planet_by_id($fleet_row['fleet_end_planet_id'], true) : null,
339
        'dst_planet'  => $mission_data['dst_planet'] ? DBStaticPlanet::db_planet_by_vector($fleet_row, 'fleet_end_', true, '`id`, `id_owner`, `name`') : null,
340
        'src_user'    => $mission_data['src_user'] || $mission_data['src_planet'] ? db_user_by_id($fleet_row['fleet_owner'], true) : null,
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

340
        'src_user'    => $mission_data['src_user'] || $mission_data['src_planet'] ? /** @scrutinizer ignore-deprecated */ db_user_by_id($fleet_row['fleet_owner'], true) : null,
Loading history...
341
        // TODO 'src_planet' => $mission_data['src_planet'] ? db_planet_by_id($fleet_row['fleet_start_planet_id'], true) : null,
342
        'src_planet'  => $mission_data['src_planet'] ? DBStaticPlanet::db_planet_by_vector($fleet_row, 'fleet_start_', true, '`id`, `id_owner`, `name`') : null,
343
        'fleet_event' => $fleet_event['fleet_event'],
344
      );
345
346
      if ($mission_data['dst_planet']) {
347
        // $mission_data['dst_planet'] = sys_o_get_updated($mission_data['dst_user'], $mission_data['dst_planet']['id'], $fleet_row['fleet_start_time']);
348
        if ($mission_data['dst_planet']['id_owner']) {
349
          $mission_data['dst_planet'] = sys_o_get_updated($mission_data['dst_planet']['id_owner'], $mission_data['dst_planet']['id'], $fleet_row['fleet_start_time']);
350
        }
351
        $mission_data['dst_user']   = $mission_data['dst_user'] ? $mission_data['dst_planet']['user'] : null;
352
        $mission_data['dst_planet'] = $mission_data['dst_planet']['planet'];
353
      }
354
355
      switch ($fleet_row['fleet_mission']) {
356
        // Для боевых атак нужно обновлять по САБу и по холду - таки надо возвращать данные из обработчика миссий!
357
        case MT_AKS:
358
        case MT_ATTACK:
359
        case MT_DESTROY:
360
          $attack_result  = flt_mission_attack($mission_data);
0 ignored issues
show
Unused Code introduced by
The assignment to $attack_result is dead and can be removed.
Loading history...
361
          $mission_result = CACHE_COMBAT;
0 ignored issues
show
Unused Code introduced by
The assignment to $mission_result is dead and can be removed.
Loading history...
362
        break;
363
364
        /*
365
        case MT_DESTROY:
366
          $attack_result = flt_mission_destroy($mission_data);
367
          $mission_result = CACHE_COMBAT;
368
        break;
369
        */
370
371
        case MT_TRANSPORT:
372
          $mission_result = flt_mission_transport($mission_data);
373
        break;
374
375
        case MT_HOLD:
376
          $mission_result = flt_mission_hold($mission_data);
377
        break;
378
379
        case MT_RELOCATE:
380
          $mission_result = flt_mission_relocate($mission_data);
381
        break;
382
383
        case MT_EXPLORE:
384
          $mission_result = flt_mission_explore($mission_data);
385
//          $theMission = \Fleet\MissionExplore::buildFromArray($mission_data);
386
//          $theMission->process();
387
//
388
//          unset($theMission);
389
        break;
390
391
        case MT_RECYCLE:
392
          $mission_result = flt_mission_recycle($mission_data);
393
        break;
394
395
        case MT_COLONIZE:
396
          $mission_result = flt_mission_colonize($mission_data);
397
        break;
398
399
        case MT_SPY:
400
          require_once(SN_ROOT_PHYSICAL . 'includes/includes/coe_simulator_helpers.php');
401
402
          $theMission = MissionEspionage::buildFromArray($mission_data);
403
          $theMission->flt_mission_spy();
404
405
          unset($theMission);
406
        break;
407
408
        case MT_MISSILE:  // Missiles !!
409
        break;
410
411
//      default:
412
//        doquery("DELETE FROM `{{fleets}}` WHERE `fleet_id` = '{$fleet_row['fleet_id']}' LIMIT 1;");
413
//      break;
414
      }
415
      sn_db_transaction_commit();
416
    }
417
418
//    set_time_limit(30); // TODO - Optimize
419
420
    $runLock->unLock(true);
421
422
//    $that->log_file('Dispatch finished - NORMAL SHUTDOWN');
423
424
    return $result;
425
426
//  log_file('Закончили обсчёт флотов');
427
  }
428
429
430
  /**
431
   * @param array $fleet_row
432
   * @param bool  $start
433
   * @param bool  $only_resources
434
   * @param bool  $safe_fleet
435
   * @param mixed $result
436
   *
437
   * @return int
438
   * @deprecated
439
   */
440
  public function sn_RestoreFleetToPlanet(&$fleet_row, $start = true, $only_resources = false, $safe_fleet = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $safe_fleet is not used and could be removed. ( Ignorable by Annotation )

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

440
  public function sn_RestoreFleetToPlanet(&$fleet_row, $start = true, $only_resources = false, /** @scrutinizer ignore-unused */ $safe_fleet = false, &$result) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
441
    sn_db_transaction_check(true);
442
443
    $result = CACHE_NOTHING;
444
    if (!is_array($fleet_row)) {
445
      return $result;
446
    }
447
448
    $prefix = $start ? 'start' : 'end';
449
450
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
451
    // TODO Проеверить от многократного срабатывания !!!
452
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
453
//  $fleet_row = doquery("SELECT * FROM {{fleets}} WHERE `fleet_id`='{$fleet_row['fleet_id']}' LIMIT 1", true);
454
    // Узнаем ИД владельца планеты - без блокировки
455
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
456
    $user_id = DBStaticPlanet::db_planet_by_vector($fleet_row, "fleet_{$prefix}_", false, 'id_owner');
457
    $user_id = $user_id['id_owner'];
458
    // Блокируем пользователя
459
    $user = db_user_by_id($user_id, true);
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

459
    $user = /** @scrutinizer ignore-deprecated */ db_user_by_id($user_id, true);
Loading history...
460
    // Блокируем планету
461
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($fleet_row, "fleet_{$prefix}_", true);
462
    // Блокируем флот
463
//  $fleet_row = doquery("SELECT * FROM {{fleets}} WHERE `fleet_id`='{$fleet_row['fleet_id']}' LIMIT 1 FOR UPDATE;", true);
464
465
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
466
    if (!$fleet_row || !is_array($fleet_row) || ($fleet_row['fleet_mess'] == 1 && $only_resources)) {
467
      return $result;
468
    }
469
470
    // Флот, который возвращается на захваченную планету, пропадает
471
    if ($start && $fleet_row['fleet_mess'] == 1 && $planet_arrival['id_owner'] != $fleet_row['fleet_owner']) {
472
      DbFleetStatic::db_fleet_delete($fleet_row['fleet_id']);
473
474
      return $result;
475
    }
476
477
    $db_changeset = array();
478
    if (!$only_resources) {
479
      DbFleetStatic::db_fleet_delete($fleet_row['fleet_id']);
480
481
      if ($fleet_row['fleet_owner'] == $planet_arrival['id_owner']) {
482
        $fleet_array = sys_unit_str2arr($fleet_row['fleet_array']);
483
        foreach ($fleet_array as $ship_id => $ship_count) {
484
          if ($ship_count) {
485
            $db_changeset['unit'][] = OldDbChangeSet::db_changeset_prepare_unit($ship_id, $ship_count, $user, $planet_arrival['id']);
486
          }
487
        }
488
      } else {
489
        return CACHE_NOTHING;
490
      }
491
    } else {
492
      $fleet_set = array(
493
        'fleet_resource_metal'     => 0,
494
        'fleet_resource_crystal'   => 0,
495
        'fleet_resource_deuterium' => 0,
496
        'fleet_mess'               => 1,
497
      );
498
      DbFleetStatic::fleet_update_set($fleet_row['fleet_id'], $fleet_set);
499
    }
500
501
    if (!empty($db_changeset)) {
502
      OldDbChangeSet::db_changeset_apply($db_changeset);
503
    }
504
505
    DBStaticPlanet::db_planet_set_by_id($planet_arrival['id'],
506
      "`metal` = `metal` + '{$fleet_row['fleet_resource_metal']}', `crystal` = `crystal` + '{$fleet_row['fleet_resource_crystal']}', `deuterium` = `deuterium` + '{$fleet_row['fleet_resource_deuterium']}'");
507
    $result = CACHE_FLEET | ($start ? CACHE_PLANET_SRC : CACHE_PLANET_DST);
508
509
    return $result;
510
  }
511
512
  /**
513
   * @param $workTime
514
   * @param $eventsProcessed
515
   * @param $lastMissionId
516
   * @param $lastEventId
517
   * @param $lastEventLength
518
   */
519
  public function logTermination($workTime, $eventsProcessed, $lastMissionId, $lastEventId, $lastEventLength) {
520
    SN::$debug->warning(sprintf(
521
      'Flying fleet handler works %1$s (> %2$s) seconds - skip rest. Processed %3$d events. Last event: mission %4$s event %6$s (%5$ss)',
522
      number_format($workTime, 4),
523
      GAME_FLEET_HANDLER_MAX_TIME,
524
      $eventsProcessed,
525
      $lastMissionId ? SN::$lang['type_mission'][$lastMissionId] : '!TERMINATED BY TIMEOUT!',
526
      number_format($lastEventLength, 4),
527
      $lastEventId ? SN::$lang['fleet_events'][$lastEventId] : '!TERMINATED BY TIMEOUT!'
528
    ),
529
      'FFH Warning',
530
      504
531
    );
532
  }
533
534
  /**
535
   * @return Lock
536
   */
537
  public function buildLock() {
538
    $runLock = new Lock($this->gc, classConfig::FLEET_UPDATE_RUN_LOCK, SN::$gc->config->fleet_update_max_run_time, 1, classConfig::DATE_TYPE_UNIX);
539
540
    return $runLock;
541
  }
542
543
544
  /**
545
   * Sort flying fleets events by time+event
546
   *
547
   * @param $a
548
   * @param $b
549
   *
550
   * @return int
551
   */
552
  protected function flt_flyingFleetsSort($a, $b) {
553
    return
554
      // Сравниваем время флотов - кто раньше, тот и первый обрабатывается
555
      $a['fleet_time'] > $b['fleet_time'] ? 1 : ($a['fleet_time'] < $b['fleet_time'] ? -1 :
556
        // Если время - одинаковое, сравниваем события флотов
557
        // Если события - одинаковые, то флоты равны
558
        ($a['fleet_event'] == $b['fleet_event'] ? 0 :
559
          // Если события разные - первыми считаем прибывающие флоты
560
          ($a['fleet_event'] == EVENT_FLT_ARRIVE ? 1 : ($b['fleet_event'] == EVENT_FLT_ARRIVE ? -1 :
561
            // Если нет прибывающих флотов - дальше считаем флоты, которые закончили миссию
562
            ($a['fleet_event'] == EVENT_FLT_ACOMPLISH ? 1 : ($b['fleet_event'] == EVENT_FLT_ACOMPLISH ? -1 :
563
              // Если нет флотов, закончивших задание - остались возвращающиеся флоты, которые равны между собой
564
              // TODO: Добавить еще проверку по ID флота и/или времени запуска - что бы обсчитывать их в порядке запуска
565
              (
566
              0 // Вообще сюда доходить не должно - будет отсекаться на равенстве событий
567
              )
568
            ))
569
          ))
570
        )
571
      );
572
  }
573
574
  /**
575
   * @param string $msg
576
   */
577
  public function log_file($msg) {
578
    static $handler;
579
580
    if (!$handler) {
581
      $handler = fopen('event.log', 'a+');
582
    }
583
584
    fwrite($handler, date(FMT_DATE_TIME_SQL, time()) . ' ' . $msg . "\r\n");
585
  }
586
587
}
588