Completed
Push — trunk ( 8c8cf8...dc0cf2 )
by SuperNova.WS
04:27
created

que_add_unit()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 39
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 26
nc 24
nop 7
dl 0
loc 39
rs 8.439
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A que_get() 0 2 1
1
<?php
2
3
use DBAL\OldDbChangeSet;
4
use Planet\DBStaticPlanet;
5
use Que\DBStaticQue;
6
use Que\QueUnitStatic;
7
8
function que_get_unit_que($unit_id) {
9
  $que_type = false;
10
  foreach(sn_get_groups('ques') as $que_id => $que_data) {
11
    if(in_array($unit_id, $que_data['unit_list'])) {
12
      $que_type = $que_id;
13
      break;
14
    }
15
  }
16
17
  return $que_type;
18
}
19
20
21
function que_get_max_que_length($user, $planet, $que_id, $que_data = null) {
22
  global $config;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
23
24
  if(empty($que_data)) {
25
    $que_data = sn_get_groups('ques');
26
    $que_data = $que_data[$que_id];
27
  }
28
29
30
  $que_length = 1;
31
  switch($que_id) {
32
    case QUE_RESEARCH:
33
      $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

33
      $que_length = $config->server_que_length_research + mrc_get_level($user, /** @scrutinizer ignore-type */ '', UNIT_PREMIUM); // TODO - вынести в модуль
Loading history...
34
    break;
35
36
    default:
37
      $que_length = isset($que_data['length']) ? $que_data['length'] + mrc_get_level($user, $planet, $que_data['mercenary']) : 1;
38
  }
39
40
  return $que_length;
41
}
42
43
function eco_que_str2arr($que_str) {
44
  $que_arr = explode(';', $que_str);
45
  foreach($que_arr as $que_index => &$que_item) {
46
    if($que_item) {
47
      $que_item = explode(',', $que_item);
48
    } else {
49
      unset($que_arr[$que_index]);
50
    }
51
  }
52
  return $que_arr;
53
}
54
55
function eco_que_arr2str($que_arr) {
56
  foreach($que_arr as &$que_item) {
57
    $que_item = implode(',', $que_item);
58
  }
59
  return implode(';', $que_arr);
60
}
61
62
63
function que_build($user, $planet, $build_mode = BUILD_CREATE, $redirect = true) {
64
  global $lang, $config;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
65
66
  $is_autoconvert = false;
67
  if($build_mode == BUILD_AUTOCONVERT || sys_get_param_int('auto_convert')) {
68
    $build_mode = BUILD_CREATE;
69
    $is_autoconvert = true;
70
  }
71
72
  $unit_amount_qued = 0;
73
  try {
74
    if(!$user['id']) {
75
      throw new exception('{Нет идентификатора пользователя - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
76
    }
77
78
    $unit_id = sys_get_param_int('unit_id');
79
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
80
    if(!$unit_id && is_array($unit_list = sys_get_param('fmenge')))
81
    {
82
      foreach($unit_list as $unit_id => $unit_amount) if($unit_amount) break;
83
    }
84
    */
85
    if(!$unit_id) {
86
      throw new exception('{Нет идентификатора юнита - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
87
    }
88
89
    $que_id = que_get_unit_que($unit_id);
90
    if(!$que_id) {
91
      throw new exception('{Неправильный тип очереди - сообщите Администрации}', ERR_ERROR); // TODO EXCEPTION
92
    }
93
94
    if($build_mode == BUILD_DESTROY && $que_id != QUE_STRUCTURES) {
95
      throw new exception('{Уничтожать можно только здания на планете}', ERR_ERROR); // TODO EXCEPTION
96
    }
97
98
    $que_data = sn_get_groups('ques');
99
    $que_data = $que_data[$que_id];
100
101
    // TODO Переделать под подочереди
102
    if($que_id == QUE_STRUCTURES) {
103
      $sn_groups_build_allow = sn_get_groups('build_allow');
104
      $que_data['unit_list'] = $sn_groups_build_allow[$planet['planet_type']];
105
106
      if(!isset($que_data['unit_list'][$unit_id])) {
107
        throw new exception('{Это здание нельзя строить на ' . ($planet['planet_type'] == PT_PLANET ? 'планете' : 'луне'), ERR_ERROR); // TODO EXCEPTION
108
      }
109
    }
110
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
111
    // TODO Разделить очереди для Верфи и Обороны
112
    elseif($que_id == QUE_HANGAR)
113
    {
114
      $que_data['mercenary'] = in_array($unit_id, sn_get_groups('defense')) ? MRC_FORTIFIER : MRC_ENGINEER;
115
    }
116
    elseif($que_id == QUE_HANGAR)
117
    {
118
      $que_data['mercenary'] = in_array($unit_id, sn_get_groups('defense')) ? MRC_FORTIFIER : MRC_ENGINEER;
119
    }
120
    */
121
122
123
    sn_db_transaction_start();
124
    // Это нужно, что бы заблокировать пользователя и работу с очередями
125
    $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

125
    $user = /** @scrutinizer ignore-deprecated */ db_user_by_id($user['id']);
Loading history...
126
    // Это нужно, что бы заблокировать планету от списания ресурсов
127
    if(isset($planet['id']) && $planet['id']) {
128
      $planet = DBStaticPlanet::db_planet_by_id($planet['id'], true);
129
    } else {
130
      $planet['id'] = 0;
131
    }
132
133
    $planet_id = $que_id == QUE_RESEARCH ? 0 : intval($planet['id']);
134
135
    $que = que_get($user['id'], $planet['id'], $que_id, true);
136
    $in_que = &$que['in_que'][$que_id][$user['id']][$planet_id];
137
    $que_max_length = que_get_max_que_length($user, $planet, $que_id, $que_data);
138
    // TODO Добавить вызовы функций проверок текущей и максимальной длин очередей
139
    if(count($in_que) >= $que_max_length) {
140
      throw new exception('{Все слоты очереди заняты}', ERR_ERROR); // TODO EXCEPTION
141
    }
142
143
    // TODO Отдельно посмотреть на уничтожение зданий - что бы можно было уничтожать их без планов
144
    switch(eco_can_build_unit($user, $planet, $unit_id)) {
145
      case BUILD_ALLOWED: break;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
146
      case BUILD_UNIT_BUSY: throw new exception('{Строение занято}', ERR_ERROR); break; // TODO EXCEPTION eco_bld_msg_err_laboratory_upgrading
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

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

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

452
      /** @scrutinizer ignore-deprecated */ db_user_set_by_id($user['id'], '`que_processed` = UNIX_TIMESTAMP(NOW())');
Loading history...
453
    }
454
455
    sn_db_transaction_commit();
456
  } else {
457
    sn_db_transaction_rollback();
458
  }
459
460
  sys_redirect("{$_SERVER['PHP_SELF']}?mode={$que_type}" . "&ally_id=" . sys_get_param_id('ally_id'));
461
}
462
463
464
function que_tpl_parse_element($que_element, $short_names = false) {
465
  global $lang;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
466
467
  return
468
    array(
469
      'ID' => $que_element['que_unit_id'],
470
      'QUE' => $que_element['que_type'],
471
      'NAME' => $short_names && !empty($lang['tech_short'][$que_element['que_unit_id']])
472
                  ? $lang['tech_short'][$que_element['que_unit_id']]
473
                  : $lang['tech'][$que_element['que_unit_id']],
474
      'TIME' => $que_element['que_time_left'],
475
      'TIME_FULL' => $que_element['que_unit_time'],
476
      'AMOUNT' => $que_element['que_unit_amount'],
477
      'LEVEL' => $que_element['que_unit_level'],
478
    );
479
}
480
481
/*
482
 *
483
 * Процедура парсит очереди текущего игрока в темплейт
484
 *
485
 * TODO: Переместить в хелперы темплейтов
486
 * TODO: Сделать поддержку нескольких очередей
487
 *
488
 * $que_type - тип очереди ОБЯЗАТЕЛЬНО
489
 * $que - либо результат $que_get(), либо конкретная очередь
490
 *
491
 */
492
function que_tpl_parse(&$template, $que_type, $user, $planet = array(), $que = null, $short_names = false) {
493
  // TODO: Переделать для $que_type === false
494
  $planet['id'] = $planet['id'] ? $planet['id'] : 0;
495
496
  if(!is_array($que)) {
497
    $que = que_get($user['id'], $planet['id'], $que_type);
498
  }
499
500
  if(is_array($que) && isset($que['items'])) {
501
    $que = $que['ques'][$que_type][$user['id']][$planet['id']];
502
  }
503
504
  if($que) {
505
    foreach($que as $que_element) {
506
      $template->assign_block_vars('que', que_tpl_parse_element($que_element, $short_names));
507
    }
508
  }
509
510
  if($que_type == QUE_RESEARCH) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
511
    // TODO Исправить
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
512
//    $template->assign_var('RESEARCH_ONGOING', count($global_que[QUE_RESEARCH][0]) >= $config->server_que_length_research);
513
  }
514
}
515
516
517
/*
518
 *
519
 * Эта процедура должна вызываться исключительно в транзакции!!!
520
 *
521
 * $user_id
522
 *   (integer) - обрабатываются глообальные очереди пользователя
523
 * $planet_id
524
 *   null - обработка очередей планет не производится
525
 * // TODO    false/0 - обрабатываются очереди всех планет по $user_id
526
 *   (integer) - обрабатываются локальные очереди для планеты. Нужно, например, в обработчике флотов
527
 *
528
 */
529
function que_process(&$user, $planet = null, $on_time = SN_TIME_NOW) {
530
  sn_db_transaction_check(true);
531
532
  $que = array();
533
534
  // Блокируем пользователя. Собственно, запись о нём нам не нужна - будем использовать старую
535
  $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

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