que_process()   F
last analyzed

Complexity

Conditions 40
Paths 5719

Size

Total Lines 192
Code Lines 106

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 40
eloc 106
nc 5719
nop 3
dl 0
loc 192
rs 0
c 0
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
2
3
use DBAL\db_mysql;
4
use DBAL\OldDbChangeSet;
5
use Planet\DBStaticPlanet;
6
use Que\DBStaticQue;
7
use Que\QueUnitStatic;
8
9
function que_get_unit_que($unit_id) {
10
  $que_type = false;
11
  foreach (sn_get_groups('ques') as $que_id => $que_data) {
12
    if (in_array($unit_id, $que_data['unit_list'])) {
13
      $que_type = $que_id;
14
      break;
15
    }
16
  }
17
18
  return $que_type;
19
}
20
21
22
function que_get_max_que_length($user, $planet, $que_id, $que_data = null) {
23
  global $config;
24
25
  if (empty($que_data)) {
26
    $que_data = sn_get_groups('ques');
27
    $que_data = $que_data[$que_id];
28
  }
29
30
31
  $que_length = 1;
32
  switch ($que_id) {
33
    case QUE_RESEARCH:
34
      $que_length = $config->server_que_length_research + mrc_get_level($user, '', UNIT_PREMIUM); // TODO - вынести в модуль
0 ignored issues
show
Bug introduced by
'' of type string is incompatible with the type array expected by parameter $planet of mrc_get_level(). ( Ignorable by Annotation )

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

34
      $que_length = $config->server_que_length_research + mrc_get_level($user, /** @scrutinizer ignore-type */ '', UNIT_PREMIUM); // TODO - вынести в модуль
Loading history...
35
    break;
36
37
    default:
38
      $que_length = isset($que_data['length']) ? $que_data['length'] + mrc_get_level($user, $planet, $que_data['mercenary']) : 1;
39
  }
40
41
  return $que_length;
42
}
43
44
function eco_que_str2arr($que_str) {
45
  $que_arr = explode(';', $que_str);
46
  foreach ($que_arr as $que_index => &$que_item) {
47
    if ($que_item) {
48
      $que_item = explode(',', $que_item);
49
    } else {
50
      unset($que_arr[$que_index]);
51
    }
52
  }
53
54
  return $que_arr;
55
}
56
57
function eco_que_arr2str($que_arr) {
58
  foreach ($que_arr as &$que_item) {
59
    $que_item = implode(',', $que_item);
60
  }
61
62
  return implode(';', $que_arr);
63
}
64
65
66
function que_build($user, $planet, $build_mode = BUILD_CREATE, $redirect = true) {
67
  global $lang, $config;
68
69
  $is_autoconvert = false;
70
  if ($build_mode == BUILD_AUTOCONVERT || sys_get_param_int('auto_convert')) {
71
    $build_mode     = BUILD_CREATE;
72
    $is_autoconvert = true;
73
  }
74
75
  $unit_amount_qued = 0;
76
  try {
77
    if (!$user['id']) {
78
      throw new exception('{Нет идентификатора пользователя - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
79
    }
80
81
    $unit_id = sys_get_param_int('unit_id');
82
    /*
83
    if(!$unit_id && is_array($unit_list = sys_get_param('fmenge')))
84
    {
85
      foreach($unit_list as $unit_id => $unit_amount) if($unit_amount) break;
86
    }
87
    */
88
    if (!$unit_id) {
89
      throw new exception('{Нет идентификатора юнита - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
90
    }
91
92
    $que_id = que_get_unit_que($unit_id);
93
    if (!$que_id) {
94
      throw new exception('{Неправильный тип очереди - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
95
    }
96
97
    if ($build_mode == BUILD_DESTROY && $que_id != QUE_STRUCTURES) {
98
      throw new exception('{Уничтожать можно только здания на планете}', ERR_ERROR); // TODO EXCEPTION
99
    }
100
101
    $que_data = sn_get_groups('ques');
102
    $que_data = $que_data[$que_id];
103
104
    // TODO Переделать под подочереди
105
    if ($que_id == QUE_STRUCTURES) {
106
      $sn_groups_build_allow = sn_get_groups('build_allow');
107
      $que_data['unit_list'] = $sn_groups_build_allow[$planet['planet_type']];
108
109
      if (!isset($que_data['unit_list'][$unit_id])) {
110
        throw new exception('{Это здание нельзя строить на ' . ($planet['planet_type'] == PT_PLANET ? 'планете' : 'луне'), ERR_ERROR); // TODO EXCEPTION
111
      }
112
    }
113
    /*
114
    // TODO Разделить очереди для Верфи и Обороны
115
    elseif($que_id == QUE_HANGAR)
116
    {
117
      $que_data['mercenary'] = in_array($unit_id, sn_get_groups('defense')) ? MRC_FORTIFIER : MRC_ENGINEER;
118
    }
119
    elseif($que_id == QUE_HANGAR)
120
    {
121
      $que_data['mercenary'] = in_array($unit_id, sn_get_groups('defense')) ? MRC_FORTIFIER : MRC_ENGINEER;
122
    }
123
    */
124
125
126
    db_mysql::db_transaction_start();
127
    // Это нужно, что бы заблокировать пользователя и работу с очередями
128
    $user = db_user_by_id($user['id']);
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

128
    $user = /** @scrutinizer ignore-deprecated */ db_user_by_id($user['id']);
Loading history...
129
    // Это нужно, что бы заблокировать планету от списания ресурсов
130
    if (isset($planet['id']) && $planet['id']) {
131
      $planet = DBStaticPlanet::db_planet_by_id($planet['id'], true);
132
    } else {
133
      $planet['id'] = 0;
134
    }
135
136
    $planet_id = $que_id == QUE_RESEARCH ? 0 : intval($planet['id']);
137
138
    $que            = que_get($user['id'], $planet['id'], $que_id, true);
139
    $in_que         = &$que['in_que'][$que_id][$user['id']][$planet_id];
140
    $que_max_length = que_get_max_que_length($user, $planet, $que_id, $que_data);
141
    // TODO Добавить вызовы функций проверок текущей и максимальной длин очередей
142
    if ((empty($in_que) ? 0 : count($in_que)) >= $que_max_length) {
143
      throw new exception('{Все слоты очереди заняты}', ERR_ERROR); // TODO EXCEPTION
144
    }
145
146
    // TODO Отдельно посмотреть на уничтожение зданий - что бы можно было уничтожать их без планов
147
    switch (eco_can_build_unit($user, $planet, $unit_id)) {
148
      case BUILD_ALLOWED:
149
      break;
150
      case BUILD_UNIT_BUSY:
151
        throw new exception('{Строение занято}', ERR_ERROR);
152
      break; // TODO EXCEPTION eco_bld_msg_err_laboratory_upgrading
153
      // case BUILD_REQUIRE_NOT_MEET:
154
      default:
155
        if ($build_mode == BUILD_CREATE) {
156
          throw new exception('{Требования не удовлетворены}', ERR_ERROR);
157
        }
158
      break; // TODO EXCEPTION eco_bld_msg_err_requirements_not_meet
159
    }
160
161
    $unit_amount      = floor(sys_get_param_float('unit_amount', 1));
162
    $unit_amount_qued = $unit_amount;
163
    $units_qued       = isset($in_que[$unit_id]) ? $in_que[$unit_id] : 0;
164
    $unit_level       = mrc_get_level($user, $planet, $unit_id, true, true) + $units_qued;
165
    if ($unit_max = get_unit_param($unit_id, P_MAX_STACK)) {
166
      if ($unit_level >= $unit_max) {
167
        throw new exception('{Максимальное количество юнитов данного типа уже достигнуто или будет достигнуто по окончанию очереди}', ERR_ERROR); // TODO EXCEPTION
168
      }
169
      $unit_amount = max(0, min($unit_amount, $unit_max - $unit_level));
170
    }
171
172
    if ($unit_amount < 1) {
173
      throw new exception('{Неправильное количество юнитов - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
174
    }
175
176
    /*
177
    if($unit_max && $unit_level + $unit_amount > $unit_max)
178
    {
179
      throw new exception("Постройка {$unit_amount} {$lang['tech'][$unit_id]} приведет к привышению максимально возможного количества юнитов данного типа", ERR_ERROR); // TODO EXCEPTION
180
    }
181
    */
182
183
    // TODO Переделать eco_unit_busy для всех типов зданий
184
    //  if(eco_unit_busy($user, $planet, $que, $unit_id))
185
    //  {
186
    //    die('Unit busy'); // TODO EXCEPTION
187
    //  }
188
    if (get_unit_param($unit_id, P_STACKABLE)) {
189
      // TODO Поле 'max_Lot_size' для ограничения размера стэка в очереди - то ли в юниты, то ли в очередь
190
      if (in_array($unit_id, $group_missile = sn_get_groups('missile'))) {
191
        // TODO Поле 'container' - указывает на родительску структуру, в которой хранится данный юнит и по вместительности которой нужно применять размер юнита
192
        $used_silo = 0;
193
        foreach ($group_missile as $missile_id) {
194
          $missile_qued = isset($in_que[$missile_id]) ? $in_que[$missile_id] : 0;
195
          $used_silo    += (mrc_get_level($user, $planet, $missile_id, true, true) + $missile_qued) * get_unit_param($missile_id, P_UNIT_SIZE);
196
        }
197
        $free_silo = mrc_get_level($user, $planet, STRUC_SILO) * get_unit_param(STRUC_SILO, P_CAPACITY) - $used_silo;
198
        if ($free_silo <= 0) {
199
          throw new exception('{Ракетная шахта уже заполнена или будет заполнена по окончанию очереди}', ERR_ERROR); // TODO EXCEPTION
200
        }
201
        $unit_size = get_unit_param($unit_id, P_UNIT_SIZE);
202
        if ($free_silo < $unit_size) {
203
          throw new exception("{В ракетной шахте нет места для {$lang['tech'][$unit_id]}}", ERR_ERROR); // TODO EXCEPTION
204
        }
205
        $unit_amount = max(0, min($unit_amount, floor($free_silo / $unit_size)));
206
      }
207
      $unit_level = $new_unit_level = 0;
208
    } else {
209
      $unit_amount = 1;
210
      if ($que_id == QUE_STRUCTURES) {
211
        // if($build_mode == BUILD_CREATE && eco_planet_fields_max($planet) - $planet['field_current'] - $que['sectors'][$planet['id']] <= 0)
212
        $sectors_qued = is_array($in_que) ? array_sum($in_que) : 0;
213
        if ($build_mode == BUILD_CREATE && eco_planet_fields_max($planet) - $planet['field_current'] - $sectors_qued <= 0) {
214
          throw new exception('{Не хватает секторов на планете}', ERR_ERROR); // TODO EXCEPTION
215
        }
216
        // И что это я такое написал? Зачем?
217
        //if($build_mode == BUILD_DESTROY && $planet['field_current'] <= $que['amounts'][$que_id])
218
        //{
219
        //  die('Too much buildings'); // TODO EXCEPTION
220
        //}
221
      }
222
      $build_multiplier = $build_mode == BUILD_CREATE ? 1 : -1;
223
      $new_unit_level   = $unit_level + $unit_amount * $build_multiplier;
224
    }
225
226
    $build_data = eco_get_build_data($user, $planet, $unit_id, $unit_level);
227
228
    $exchange                    = array();
229
    $market_get_autoconvert_cost = market_get_autoconvert_cost();
230
    if ($is_autoconvert && $build_data[BUILD_AUTOCONVERT]) {
231
      $dark_matter = mrc_get_level($user, null, RES_DARK_MATTER);
232
      if (mrc_get_level($user, null, RES_DARK_MATTER) < $market_get_autoconvert_cost) {
233
        throw new exception("{Нет хватает " . ($market_get_autoconvert_cost - $dark_matter) . "ТМ на постройки с автоконвертацией ресурсов}", ERR_ERROR); // TODO EXCEPTION
234
      }
235
236
      !get_unit_param($unit_id, P_STACKABLE) ? $unit_amount = 1 : false;
237
      $resources_loot          = sn_get_groups('resources_loot');
238
      $resource_got            = array();
239
      $resource_exchange_rates = array();
240
      $resource_diff           = array();
241
      $all_positive            = true;
242
      foreach ($resources_loot as $resource_id) {
243
        $resource_db_name                      = pname_resource_name($resource_id);
244
        $resource_got[$resource_id]            = floor(mrc_get_level($user, $planet, $resource_id));
245
        $resource_exchange_rates[$resource_id] = $config->__get("rpg_exchange_{$resource_db_name}");
246
        $resource_diff[$resource_id]           = $resource_got[$resource_id] - $build_data[BUILD_CREATE][$resource_id] * $unit_amount;
247
        $all_positive                          = $all_positive && ($resource_diff[$resource_id] > 0);
248
      }
249
      // Нужна автоконвертация
250
      if ($all_positive) {
251
        $is_autoconvert = false;
252
      } else {
253
        foreach ($resource_diff as $resource_diff_id => &$resource_diff_amount) {
254
          if ($resource_diff_amount >= 0) {
255
            continue;
256
          }
257
          foreach ($resource_diff as $resource_got_id => &$resource_got_amount) {
258
            if ($resource_got_amount <= 0) {
259
              continue;
260
            }
261
            $current_exchange = $resource_exchange_rates[$resource_got_id] / $resource_exchange_rates[$resource_diff_id];
262
263
            $will_exchage_to   = min(-$resource_diff_amount, floor($resource_got_amount * $current_exchange));
264
            $will_exchage_from = $will_exchage_to / $current_exchange;
265
266
            $resource_diff_amount        += $will_exchage_to;
267
            $resource_got_amount         -= $will_exchage_from;
268
            $exchange[$resource_diff_id] += $will_exchage_to;
269
            $exchange[$resource_got_id]  -= $will_exchage_from;
270
          }
271
        }
272
273
        $is_autoconvert_ok = true;
274
        foreach ($resource_diff as $resource_diff_amount2) {
275
          if ($resource_diff_amount2 < 0) {
276
            $is_autoconvert_ok = false;
277
            break;
278
          }
279
        }
280
281
        if ($is_autoconvert_ok) {
282
          $build_data['RESULT'][$build_mode] = BUILD_ALLOWED;
283
          $build_data['CAN'][$build_mode]    = $unit_amount;
284
        } else {
285
          $unit_amount = 0;
286
        }
287
      }
288
    }
289
    $unit_amount = min($build_data['CAN'][$build_mode], $unit_amount);
290
    if ($unit_amount <= 0) {
291
      throw new exception('{Не хватает ресурсов}', ERR_ERROR); // TODO EXCEPTION
292
    }
293
294
    if ($new_unit_level < 0) {
295
      throw new exception('{Нельзя уничтожить больше юнитов, чем есть}', ERR_ERROR); // TODO EXCEPTION
296
    }
297
298
    if ($build_data['RESULT'][$build_mode] != BUILD_ALLOWED) {
299
      throw new exception('{Строительство блокировано}', ERR_ERROR); // TODO EXCEPTION
300
    }
301
302
    if ($is_autoconvert) {
303
      ksort($exchange);
304
      ksort($resource_got);
305
      db_change_units($user, $planet, array(
306
        RES_METAL     => !empty($exchange[RES_METAL]) ? $exchange[RES_METAL] : 0,
307
        RES_CRYSTAL   => !empty($exchange[RES_CRYSTAL]) ? $exchange[RES_CRYSTAL] : 0,
308
        RES_DEUTERIUM => !empty($exchange[RES_DEUTERIUM]) ? $exchange[RES_DEUTERIUM] : 0,
309
      ));
310
      rpg_points_change($user['id'], RPG_BUILD_AUTOCONVERT, -$market_get_autoconvert_cost, sprintf(
311
        $lang['bld_autoconvert'], $unit_id, $unit_amount, uni_render_planet_full($planet, '', false, true), $lang['tech'][$unit_id],
312
        sys_unit_arr2str($build_data[BUILD_CREATE]), sys_unit_arr2str($resource_got), sys_unit_arr2str($exchange)
313
      ));
314
    }
315
316
    $unit_amount_qued = 0;
317
    while (
318
      $unit_amount > 0
319
      &&
320
      (empty($que['ques'][$que_id][$user['id']][$planet_id]) ? 0 : count($que['ques'][$que_id][$user['id']][$planet_id])) < $que_max_length
321
    ) {
322
      $place = min($unit_amount, MAX_FLEET_OR_DEFS_PER_ROW);
323
//      $sqlBlock = QueUnitStatic::que_unit_make_sql($unit_id, $user, $planet, $build_data, $new_unit_level, $place, $build_mode);
324
      $sqlBlock = SN::$gc->pimp->que_unit_make_sql($unit_id, $user, $planet, $build_data, $new_unit_level, $place, $build_mode);
325
326
      array_walk($sqlBlock, function (&$value, $field) {
327
        if ($value === null) {
328
          $value = 'NULL';
329
        } elseif (is_string($value)) {
330
          $value = "'{$value}'";
331
        }
332
333
        $value = "`{$field}` = {$value}";
334
      });
335
336
      DBStaticQue::db_que_set_insert(implode(',', $sqlBlock)
337
//        "`que_player_id` = {$user['id']},
338
//      `que_planet_id` = {$planet_id},
339
//      `que_planet_id_origin` = {$planet_id_origin},
340
//      `que_type` = {$que_type},
341
//      `que_time_left` = {$build_data[RES_TIME][$build_mode]},
342
//      `que_unit_id` = {$unit_id},
343
//      `que_unit_amount` = {$unit_amount},
344
//      `que_unit_mode` = {$build_mode},
345
//      `que_unit_level` = {$unit_level},
346
//      `que_unit_time` = {$build_data[RES_TIME][$build_mode]},
347
//      `que_unit_price` = '{$resource_list}'"
348
      );
349
350
351
      $unit_amount      -= $place;
352
      $que              = que_get($user['id'], $planet['id'], $que_id, true);
353
      $unit_amount_qued += $place;
354
    }
355
356
    db_mysql::db_transaction_commit();
357
358
    if ($redirect) {
359
      sys_redirect("{$_SERVER['PHP_SELF']}?mode=" . sys_get_param_str('mode') . "&ally_id=" . sys_get_param_id('ally_id'));
360
    }
361
362
    $operation_result = array(
363
      'STATUS'  => ERR_NONE,
364
      'MESSAGE' => '{Строительство начато}',
365
    );
366
  } catch (exception $e) {
367
    db_mysql::db_transaction_rollback();
368
    $operation_result = array(
369
      'STATUS'  => in_array($e->getCode(), array(ERR_NONE, ERR_WARNING, ERR_ERROR)) ? $e->getCode() : ERR_ERROR,
370
      'MESSAGE' => $e->getMessage()
371
    );
372
  }
373
374
  if (!empty($operation_result['MESSAGE'])) {
375
    $operation_result['MESSAGE'] .= ' ' . ($unit_amount_qued ? $unit_amount_qued : $unit_amount) . 'x[' . $lang['tech'][$unit_id] . ']';
376
  }
377
378
  return $operation_result;
379
}
380
381
382
function que_recalculate($old_que) {
383
  $new_que = array();
384
385
  if (!is_array($old_que['items'])) {
386
    return $new_que;
387
  }
388
  foreach ($old_que['items'] as $row) {
389
    if (!isset($row) || !$row || $row['que_unit_amount'] <= 0) {
390
      continue;
391
    }
392
393
    $new_que['items'][] = $row;
394
395
    $new_que['in_que'][$row['que_type']][$row['que_player_id']][intval($row['que_planet_id'])][$row['que_unit_id']]     += $row['que_unit_amount'] * ($row['que_unit_mode'] == BUILD_CREATE ? 1 : -1);
396
    $new_que['in_que_abs'][$row['que_type']][$row['que_player_id']][intval($row['que_planet_id'])][$row['que_unit_id']] += $row['que_unit_amount'];
397
398
    $last_id = count($new_que['items']) - 1;
399
400
    if ($row['que_planet_id']) {
401
      $new_que['planets'][$row['que_planet_id']][$row['que_type']][] = &$new_que['items'][$last_id];
402
    } elseif ($row['que_type'] == QUE_RESEARCH) {
403
      $new_que['players'][$row['que_player_id']][$row['que_type']][] = &$new_que['items'][$last_id];
404
    }
405
    $new_que['ques'][$row['que_type']][$row['que_player_id']][intval($row['que_planet_id'])][] = &$new_que['items'][$last_id];
406
407
    // Это мы можем посчитать по длине очереди в players и planets
408
    //$ques['used_slots'][$row['que_type']][$row['que_player_id']][intval($row['que_planet_id'])][$row['que_unit_id']]++;
409
  }
410
411
  return $new_que;
412
}
413
414
function que_get($user_id, $planet_id = null, $que_type = false, $for_update = false) {
415
  return SN::db_que_list_by_type_location($user_id, $planet_id, $que_type, $for_update);
416
}
417
418
function que_delete($que_type, $user = array(), $planet = array(), $clear = false) {
419
  $planets_locked = array();
420
421
  // TODO: Some checks
422
  db_mysql::db_transaction_start();
423
  $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

423
  $user         = /** @scrutinizer ignore-deprecated */ db_user_by_id($user['id'], true);
Loading history...
424
  $planet['id'] = $planet['id'] && $que_type !== QUE_RESEARCH ? $planet['id'] : 0;
425
  $global_que   = que_get($user['id'], $planet['id'], $que_type, true);
426
427
  if (!empty($global_que['ques'][$que_type][$user['id']][$planet['id']])) {
428
    $que = array_reverse($global_que['ques'][$que_type][$user['id']][$planet['id']]);
429
430
    foreach ($que as $que_item) {
431
      DBStaticQue::db_que_delete_by_id($que_item['que_id']);
432
433
      if ($que_item['que_planet_id_origin']) {
434
        $planet['id'] = $que_item['que_planet_id_origin'];
435
      }
436
437
      if (!isset($planets_locked[$planet['id']])) {
438
        $planets_locked[$planet['id']] = $planet['id'] ? DBStaticPlanet::db_planet_by_id($planet['id'], true) : $planet;
439
      }
440
441
      $build_data = sys_unit_str2arr($que_item['que_unit_price']);
442
443
      db_change_units($user, $planets_locked[$planet['id']], array(
444
        RES_METAL     => $build_data[RES_METAL] * $que_item['que_unit_amount'],
445
        RES_CRYSTAL   => $build_data[RES_CRYSTAL] * $que_item['que_unit_amount'],
446
        RES_DEUTERIUM => $build_data[RES_DEUTERIUM] * $que_item['que_unit_amount'],
447
      ));
448
449
      if (!$clear) {
450
        break;
451
      }
452
    }
453
454
    if (is_numeric($planet['id'])) {
455
      DBStaticPlanet::db_planet_set_by_id($planet['id'], "`que_processed` = UNIX_TIMESTAMP(NOW())");
456
    } elseif (is_numeric($user['id'])) {
457
      db_user_set_by_id($user['id'], '`que_processed` = UNIX_TIMESTAMP(NOW())');
0 ignored issues
show
Deprecated Code introduced by
The function db_user_set_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

457
      /** @scrutinizer ignore-deprecated */ db_user_set_by_id($user['id'], '`que_processed` = UNIX_TIMESTAMP(NOW())');
Loading history...
458
    }
459
460
    db_mysql::db_transaction_commit();
461
  } else {
462
    db_mysql::db_transaction_rollback();
463
  }
464
465
  sys_redirect("{$_SERVER['PHP_SELF']}?mode={$que_type}" . "&ally_id=" . sys_get_param_id('ally_id'));
466
}
467
468
469
function que_tpl_parse_element($que_element, $short_names = false) {
470
  global $lang;
471
472
  return
473
    array(
474
      'ID'        => $que_element['que_unit_id'],
475
      'QUE'       => $que_element['que_type'],
476
      'NAME'      => $short_names && !empty($lang['tech_short'][$que_element['que_unit_id']])
477
        ? $lang['tech_short'][$que_element['que_unit_id']]
478
        : $lang['tech'][$que_element['que_unit_id']],
479
      'TIME'      => $que_element['que_time_left'],
480
      'TIME_FULL' => $que_element['que_unit_time'],
481
      'AMOUNT'    => $que_element['que_unit_amount'],
482
      'LEVEL'     => $que_element['que_unit_level'],
483
    );
484
}
485
486
/*
487
 *
488
 * Процедура парсит очереди текущего игрока в темплейт
489
 *
490
 * TODO: Переместить в хелперы темплейтов
491
 * TODO: Сделать поддержку нескольких очередей
492
 *
493
 * $que_type - тип очереди ОБЯЗАТЕЛЬНО
494
 * $que - либо результат $que_get(), либо конкретная очередь
495
 *
496
 */
497
function que_tpl_parse(&$template, $que_type, $user, $planet = array(), $que = null, $short_names = false) {
498
  // TODO: Переделать для $que_type === false
499
  $planet['id'] = $planet['id'] ? $planet['id'] : 0;
500
501
  if (!is_array($que)) {
502
    $que = que_get($user['id'], $planet['id'], $que_type);
503
  }
504
505
  if (is_array($que) && isset($que['items'])) {
506
    $que = $que['ques'][$que_type][$user['id']][$planet['id']];
507
  }
508
509
  if ($que) {
510
    foreach ($que as $que_element) {
511
      $template->assign_block_vars('que', que_tpl_parse_element($que_element, $short_names));
512
    }
513
  }
514
515
  if ($que_type == QUE_RESEARCH) {
516
    // TODO Исправить
517
//    $template->assign_var('RESEARCH_ONGOING', count($global_que[QUE_RESEARCH][0]) >= $config->server_que_length_research);
518
  }
519
}
520
521
522
/*
523
 *
524
 * Эта процедура должна вызываться исключительно в транзакции!!!
525
 *
526
 * $user_id
527
 *   (integer) - обрабатываются глообальные очереди пользователя
528
 * $planet_id
529
 *   null - обработка очередей планет не производится
530
 * // TODO    false/0 - обрабатываются очереди всех планет по $user_id
531
 *   (integer) - обрабатываются локальные очереди для планеты. Нужно, например, в обработчике флотов
532
 *
533
 */
534
function que_process(&$user, $planet = null, $on_time = SN_TIME_NOW) {
535
  db_mysql::db_transaction_check(true);
536
537
  $que = array();
538
539
  // Блокируем пользователя. Собственно, запись о нём нам не нужна - будем использовать старую
540
  $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

540
  $user = /** @scrutinizer ignore-deprecated */ db_user_by_id($user['id'], true);
Loading history...
541
542
  $time_left[$user['id']][0] = max(0, $on_time - $user['que_processed']);
543
  if ($planet === null && !$time_left[$user['id']][0]) {
544
    // TODO
545
    return $que;
546
  }
547
548
  // Определяем, какие очереди нам нужны и получаем их
549
  $que_type_id = $planet === null ? QUE_RESEARCH : false;
550
  $planet      = intval(is_array($planet) ? $planet['id'] : $planet); // В $planet у нас теперь только её ID или шаблон null/0/false
551
  $que         = que_get($user['id'], $planet, $que_type_id, true);
552
  if (empty($que['items'])) {
553
    return $que;
554
  }
555
556
  $planet_list = array();
557
  if ($planet !== null) {
558
    // Если нужно изменять данные на планетах - блокируем планеты и получаем данные о них
559
    // TODO - от них не надо ничего, кроме ID и que_processed
560
    $planet_row                                            = DBStaticPlanet::db_planet_list_by_user_or_planet($user['id'], $planet);
561
    $planet_list[$planet_row['id']]                        = $planet_row;
562
    $time_left[$planet_row['id_owner']][$planet_row['id']] = max(0, $on_time - $planet_row['que_processed']);
563
  }
564
565
  // Теперь в $time_left лежит время обсчета всех очередей по каждой из планеты
566
  if (array_sum($time_left[$user['id']]) == 0) {
567
    return $que;
568
  }
569
570
  $db_changeset = array();
571
  $unit_changes = array();
572
  foreach ($que['items'] as &$que_item) {
573
    $que_player_id = &$que_item['que_player_id'];
574
    $que_planet_id = intval($que_item['que_planet_id']);
575
576
    $que_time_left = &$que['time_left'][$que_player_id][$que_planet_id][$que_item['que_type']];
577
    if (!isset($que_time_left)) {
578
      $que_time_left = $time_left[$que_player_id][$que_planet_id];
579
    }
580
    if ($que_time_left <= 0 || $que_item['que_unit_amount'] <= 0) {
581
      continue;
582
    }
583
    // Дальше мы идем, если только осталось время в очереди И юниты к постройке
584
585
    // Вычисляем, сколько целых юнитов будет построено - от 0 до количества юнитов в очереди
586
    $unit_processed = min($que_item['que_unit_amount'] - 1, floor($que_time_left / $que_item['que_unit_time']));
587
    // Вычитаем это время из остатков
588
    $que_time_left -= $unit_processed * $que_item['que_unit_time'];
589
590
    // Теперь работаем с остатком времени на юните. Оно не может быть равно или меньше нуля
591
592
    // Если времени в очереди осталось не меньше, чем время текущего юнита - значит мы достроили юнит
593
    if ($que_time_left >= $que_item['que_time_left']) {
594
      // Увеличиваем количество отстроенных юнитов
595
      $unit_processed++;
596
      // Вычитаем из времени очереди потраченное на постройку время
597
      $que_time_left -= $que_item['que_time_left'];
598
      // Полное время юнита равно времени нового юнита
599
      $que_item['que_time_left'] = $que_item['que_unit_time'];
600
      // Тут у нас может остатся время очереди - если постройка была не последняя
601
    }
602
    // Изменяем количество оставшихся юнитов
603
    $que_item['que_unit_amount'] -= $unit_processed;
604
605
    // Если еще остались юниты - значит ВСЁ оставшееся время приходится на достройку следующего юнита
606
    if ($que_item['que_unit_amount'] > 0) {
607
      $que_item['que_time_left'] = $que_item['que_time_left'] - $que_time_left;
608
      $que_time_left             = 0;
609
    }
610
611
    if ($que_item['que_unit_amount'] <= 0) {
612
      $db_changeset['que'][] = array(
613
        'action'  => SQL_OP_DELETE,
614
        P_VERSION => 1,
615
        'where'   => array(
616
          "que_id" => $que_item['que_id'],
617
        ),
618
      );
619
    } else {
620
      $db_changeset['que'][] = array(
621
        'action'  => SQL_OP_UPDATE,
622
        P_VERSION => 1,
623
        'where'   => array(
624
          "que_id" => $que_item['que_id'],
625
        ),
626
        'fields'  => array(
627
          'que_unit_amount' => array(
628
            'delta' => -$unit_processed
629
          ),
630
          'que_time_left'   => array(
631
            'set' => $que_item['que_time_left']
632
          ),
633
        ),
634
      );
635
    }
636
637
    if ($unit_processed) {
638
      $unit_processed_delta                                                   = $unit_processed * ($que_item['que_unit_mode'] == BUILD_CREATE ? 1 : -1);
639
      $unit_changes[$que_player_id][$que_planet_id][$que_item['que_unit_id']] += $unit_processed_delta;
640
    }
641
  }
642
643
  foreach ($time_left as $player_id => $planet_data) {
644
    foreach ($planet_data as $planet_id => $time_on_planet) {
645
      $table                  = $planet_id ? 'planets' : 'users';
646
      $id                     = $planet_id ? $planet_id : $player_id;
647
      $db_changeset[$table][] = array(
648
        'action'  => SQL_OP_UPDATE,
649
        P_VERSION => 1,
650
        'where'   => array(
651
          "id" => $id,
652
        ),
653
        'fields'  => array(
654
          'que_processed' => array(
655
            'set' => $on_time,
656
          ),
657
        ),
658
      );
659
660
      if (is_array($unit_changes[$player_id][$planet_id])) {
661
        foreach ($unit_changes[$player_id][$planet_id] as $unit_id => $unit_amount) {
662
          $db_changeset['unit'][] = OldDbChangeSet::db_changeset_prepare_unit($unit_id, $unit_amount, $user, $planet_id ? $planet_id : null);
663
        }
664
      }
665
    }
666
  }
667
668
  $que = que_recalculate($que);
669
670
  // TODO: Re-enable quests for Alliances
671
  if (!empty($unit_changes) && !$user['user_as_ally']) {
672
    $quest_list     = qst_get_quests($user['id'], QUEST_STATUS_ALL);
673
    $quest_triggers = qst_active_triggers($quest_list);
674
    $quest_rewards  = array();
675
    $quest_statuses = array();
676
677
678
    $xp_incoming = array();
679
    foreach ($unit_changes as $user_id => $planet_changes) {
680
      foreach ($planet_changes as $planet_id => $changes) {
681
        $planet_this = $planet_id ? SN::db_get_record_by_id(LOC_PLANET, $planet_id) : array();
682
        foreach ($changes as $unit_id => $unit_value) {
683
          $que_id         = que_get_unit_que($unit_id);
684
          $unit_level_new = mrc_get_level($user, $planet_this, $unit_id, false, true) + $unit_value;
685
          if ($que_id == QUE_STRUCTURES || $que_id == QUE_RESEARCH) {
686
            $build_data = eco_get_build_data($user, $planet_this, $unit_id, $unit_level_new - 1);
687
            $build_data = $build_data[BUILD_CREATE];
688
            foreach (sn_get_groups('resources_loot') as $resource_id) {
689
              $xp_incoming[$que_id] += $build_data[$resource_id]; // TODO - добавить конверсию рейтов обмена
690
            }
691
          }
692
693
          if (is_array($quest_triggers)) {
694
            // TODO: Check mutiply condition quests
695
            $quest_trigger_list = array_keys($quest_triggers, $unit_id);
696
697
            if (is_array($quest_trigger_list)) {
698
              foreach ($quest_trigger_list as $quest_id) {
699
                if ($quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE) {
700
                  if ($quest_list[$quest_id]['quest_unit_amount'] <= $unit_level_new) {
701
                    $quest_rewards[$quest_id][$user_id][$planet_id] = $quest_list[$quest_id]['quest_rewards_list'];
702
                    $quest_statuses[$quest_id]                      = QUEST_STATUS_COMPLETE;
703
                  } else {
704
                    $quest_statuses[$quest_id] = QUEST_STATUS_STARTED;
705
                  }
706
                }
707
              }
708
            }
709
          }
710
        }
711
      }
712
    }
713
    // TODO: Изменить начисление награды за квесты на ту планету, на которой происходил ресеч
714
    qst_reward($user, $quest_rewards, $quest_list, $quest_statuses);
715
716
    foreach ($xp_incoming as $que_id => $xp) {
717
      rpg_level_up($user, $que_id == QUE_RESEARCH ? RPG_TECH : RPG_STRUCTURE, $xp / 1000);
718
    }
719
  }
720
721
  OldDbChangeSet::db_changeset_apply($db_changeset);
722
723
  // TODO Сообщения о постройке
724
725
  return $que;
726
}
727