Completed
Push — trunk ( 0e7a2e...6a6c5e )
by SuperNova.WS
07:28
created

PageMercenary::fillDiscountTable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 7
ccs 0
cts 7
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by Gorlum 30.09.2017 8:28
4
 */
5
6
namespace Pages\Deprecated;
7
8
use \Exception;
9
use \SN;
10
use Unit\DBStaticUnit;
11
use \template;
12
13
class PageMercenary {
14
15
  /**
16
   * @var \classConfig $config
17
   */
18
  protected $config;
19
  /**
20
   * @var \classLocale $lang
21
   */
22
  protected $lang;
23
24
  /**
25
   * @var float[] $sn_powerup_buy_discounts
26
   */
27
  protected $sn_powerup_buy_discounts;
28
29
  /**
30
   * What we purchasing - Plans or Mercenaries?
31
   * @var int $mode
32
   */
33
  protected $mode = UNIT_MERCENARIES; // Or UNIT_PLANS
34
35
  /**
36
   * If purchased units are permanent?
37
   * @var bool $isUnitsPermanent
38
   */
39
  protected $isUnitsPermanent = false;
40
41
  /**
42
   * Multiplier for Alliance's purchases
43
   *
44
   * @var float $cost_alliance_multiplier
45
   */
46
  protected $cost_alliance_multiplier;
47
48
  public function __construct() {
49
    global $lang, $sn_powerup_buy_discounts;
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...
50
51
    lng_include('mrc_mercenary');
52
    lng_include('infos');
53
54
    $this->config = SN::$config;
55
    $this->lang = $lang;
56
    $this->sn_powerup_buy_discounts = $sn_powerup_buy_discounts;
57
58
    $this->loadParams();
59
  }
60
61
  protected function loadParams() {
62
    // Getting page mode
63
    $this->mode = sys_get_param_int('mode', UNIT_MERCENARIES);
64
    $this->mode = in_array($this->mode, array(UNIT_MERCENARIES, UNIT_PLANS)) ? $this->mode : UNIT_MERCENARIES;
65
66
    $this->isUnitsPermanent = $this->mode == UNIT_PLANS || !$this->config->empire_mercenary_temporary;
67
    $this->cost_alliance_multiplier = min(1, SN_IN_ALLY === true && $this->mode == UNIT_PLANS ? $this->config->ali_bonus_members : 1);
68
  }
69
70
71
  /**
72
   * @param array $user
73
   */
74
  public function mrc_mercenary_render($user) {
75
    $template = gettemplate('mrc_mercenary_hire');
76
77
    $operation_result = $this->modelMercenaryHire($user);
78
    if (!empty($operation_result)) {
79
      $template->assign_block_vars('result', $operation_result);
80
    }
81
82
    $this->fillDiscountTable($template);
83
84
    $user_dark_matter = mrc_get_level($user, [], RES_DARK_MATTER);
85
    foreach (sn_get_groups($this->mode == UNIT_PLANS ? 'plans' : 'mercenaries') as $mercenary_id) {
86
      $mercenary = get_unit_param($mercenary_id);
87
88
      $mercenary_level = mrc_get_level($user, [], $mercenary_id, false, true);
89
      $mercenary_level_bonus = max(0, mrc_get_level($user, [], $mercenary_id) - $mercenary_level);
90
91
      $currentUnitCostDM = 0;
92
      if ($this->isUnitsPermanent) {
93
        $currentUnitCostDM = eco_get_total_cost($mercenary_id, $mercenary_level);
94
        $currentUnitCostDM = $currentUnitCostDM[BUILD_CREATE][RES_DARK_MATTER] * $this->cost_alliance_multiplier;
95
      }
96
      $nextLevelCostData = eco_get_total_cost($mercenary_id, $mercenary_level + 1);
97
      $nextLevelCostDM = $nextLevelCostData[BUILD_CREATE][RES_DARK_MATTER] * $this->cost_alliance_multiplier;
98
99
      $mercenary_unit = DBStaticUnit::db_unit_by_location($user['id'], LOC_USER, $user['id'], $mercenary_id);
100
      $mercenary_time_start = strtotime($mercenary_unit['unit_time_start']);
101
      $mercenary_time_finish = strtotime($mercenary_unit['unit_time_finish']);
102
      $unitIsOutdated = $mercenary_time_finish && $mercenary_time_finish >= SN_TIME_NOW;
103
      $template->assign_block_vars('officer', array(
104
        'ID'                => $mercenary_id,
105
        'NAME'              => $this->lang['tech'][$mercenary_id],
106
        'DESCRIPTION'       => $this->lang['info'][$mercenary_id]['description'],
107
        'EFFECT'            => $this->lang['info'][$mercenary_id]['effect'],
108
        'COST'              => $nextLevelCostDM - $currentUnitCostDM,
109
        'COST_TEXT'         => prettyNumberStyledCompare($nextLevelCostDM - $currentUnitCostDM, $user_dark_matter),
0 ignored issues
show
Bug introduced by
It seems like $user_dark_matter can also be of type boolean; however, parameter $compareTo of prettyNumberStyledCompare() does only seem to accept integer|double, maybe add an additional type check? ( Ignorable by Annotation )

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

109
        'COST_TEXT'         => prettyNumberStyledCompare($nextLevelCostDM - $currentUnitCostDM, /** @scrutinizer ignore-type */ $user_dark_matter),
Loading history...
110
        'LEVEL'             => $mercenary_level,
111
        'LEVEL_BONUS'       => $mercenary_level_bonus,
112
        'LEVEL_MAX'         => $mercenary['max'],
113
        'BONUS'             => tpl_render_unit_bonus_data($mercenary),
114
        'BONUS_TYPE'        => $mercenary[P_BONUS_TYPE],
115
        'HIRE_END'          => $unitIsOutdated ? date(FMT_DATE_TIME, $mercenary_time_finish) : '',
116
        'HIRE_LEFT_PERCENT' => $unitIsOutdated ? round(($mercenary_time_finish - SN_TIME_NOW) / ($mercenary_time_finish - $mercenary_time_start) * 100, 1) : 0,
117
        'CAN_BUY'           => $this->mrc_officer_accessible($user, $mercenary_id),
118
      ));
119
120
      $this->renderMercenaryLevelsAvail($user_dark_matter, $mercenary_id, $currentUnitCostDM, $template, $mercenary_level, $mercenary['max']);
0 ignored issues
show
Bug introduced by
It seems like $mercenary_level can also be of type boolean and double; however, parameter $mercenary_level of Pages\Deprecated\PageMer...rMercenaryLevelsAvail() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

120
      $this->renderMercenaryLevelsAvail($user_dark_matter, $mercenary_id, $currentUnitCostDM, $template, /** @scrutinizer ignore-type */ $mercenary_level, $mercenary['max']);
Loading history...
Bug introduced by
It seems like $user_dark_matter can also be of type boolean; however, parameter $user_dark_matter of Pages\Deprecated\PageMer...rMercenaryLevelsAvail() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

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

120
      $this->renderMercenaryLevelsAvail(/** @scrutinizer ignore-type */ $user_dark_matter, $mercenary_id, $currentUnitCostDM, $template, $mercenary_level, $mercenary['max']);
Loading history...
121
122
      $this->renderMercenaryReq($user, $mercenary, $template);
123
    }
124
125
    $template->assign_vars(array(
126
      'PAGE_HEADER'                => $this->lang['tech'][$this->mode],
127
      'MODE'                       => $this->mode,
128
      'IS_PERMANENT'               => intval($this->isUnitsPermanent),
129
      'EMPIRE_MERCENARY_TEMPORARY' => $this->config->empire_mercenary_temporary,
130
      'DARK_MATTER'                => $user_dark_matter,
131
    ));
132
133
    display($template, $this->lang['tech'][$this->mode]);
134
  }
135
136
  protected function mrc_mercenary_hire($user, $mercenary_id) {
137
    if (!in_array($mercenary_id, sn_get_groups($this->mode == UNIT_PLANS ? 'plans' : 'mercenaries'))) {
138
      throw new Exception('mrc_msg_error_wrong_mercenary', ERR_ERROR);
139
    }
140
141
    if (!$this->mrc_officer_accessible($user, $mercenary_id)) {
142
      throw new Exception('mrc_msg_error_requirements', ERR_ERROR);
143
    }
144
145
    $mercenary_level = sys_get_param_int('mercenary_level');
146
    if ($mercenary_level < 0 || $mercenary_level > get_unit_param($mercenary_id, P_MAX_STACK)) {
147
      throw new Exception('mrc_msg_error_wrong_level', ERR_ERROR);
148
    }
149
150
    $mercenary_period = sys_get_param_int('mercenary_period');
151
    if ($mercenary_level && !array_key_exists($mercenary_period, $this->sn_powerup_buy_discounts)) {
152
      throw new Exception('mrc_msg_error_wrong_period', ERR_ERROR);
153
    }
154
155
    sn_db_transaction_start();
156
157
    $mercenary_level_old = mrc_get_level($user, [], $mercenary_id, true, true);
158
    if ($this->config->empire_mercenary_temporary && $mercenary_level_old && $mercenary_level) {
159
      throw new Exception('mrc_msg_error_already_hired', ERR_ERROR); // Can't hire already hired temp mercenary - dismiss first
160
    } elseif ($this->config->empire_mercenary_temporary && !$mercenary_level_old && !$mercenary_level) {
161
      throw new Exception('', ERR_NONE); // Can't dismiss (!$mercenary_level) not hired (!$mercenary_level_old) temp mercenary. But no error
162
    }
163
164
    if ($mercenary_level) {
165
      $darkmater_cost = eco_get_total_cost($mercenary_id, $mercenary_level);
166
      if (!$this->config->empire_mercenary_temporary && $mercenary_level_old) {
167
        $darkmater_cost_old = eco_get_total_cost($mercenary_id, $mercenary_level_old);
168
        $darkmater_cost[BUILD_CREATE][RES_DARK_MATTER] -= $darkmater_cost_old[BUILD_CREATE][RES_DARK_MATTER];
169
      }
170
      $darkmater_cost = ceil($darkmater_cost[BUILD_CREATE][RES_DARK_MATTER] * $mercenary_period * $this->sn_powerup_buy_discounts[$mercenary_period] / $this->config->empire_mercenary_base_period);
171
    } else {
172
      $darkmater_cost = 0;
173
    }
174
    $darkmater_cost *= $this->cost_alliance_multiplier;
175
176
    if (mrc_get_level($user, [], RES_DARK_MATTER) < $darkmater_cost) {
177
      throw new Exception('mrc_msg_error_no_resource', ERR_ERROR);
178
    }
179
180
    $this->mercenaryDismiss($user, $mercenary_id, $darkmater_cost, $mercenary_level);
181
182
    if ($darkmater_cost && $mercenary_level) {
183
      DBStaticUnit::db_unit_set_insert(
184
        "unit_player_id = {$user['id']},
185
        unit_location_type = " . LOC_USER . ",
186
        unit_location_id = {$user['id']},
187
        unit_type = {$this->mode},
188
        unit_snid = {$mercenary_id},
189
        unit_level = {$mercenary_level},
190
        unit_time_start = " . (!$this->isUnitsPermanent ? 'FROM_UNIXTIME(' . SN_TIME_NOW . ')' : 'null') . ",
191
        unit_time_finish = " . (!$this->isUnitsPermanent ? 'FROM_UNIXTIME(' . (SN_TIME_NOW + $mercenary_period) . ')' : 'null')
192
      );
193
194
      rpg_points_change($user['id'], $this->mode == UNIT_PLANS ? RPG_PLANS : RPG_MERCENARY, -($darkmater_cost),
195
        sprintf($this->lang[$this->mode == UNIT_PLANS ? 'mrc_plan_bought_log' : 'mrc_mercenary_hired_log'], $this->lang['tech'][$mercenary_id], $mercenary_id, $darkmater_cost, round($mercenary_period / PERIOD_DAY)));
196
    }
197
    sn_db_transaction_commit();
198
    sys_redirect($_SERVER['REQUEST_URI']);
199
  }
200
201
  protected function mrc_officer_accessible(&$user, $mercenary_id) {
202
    $mercenary_info = get_unit_param($mercenary_id);
203
204
    if ($this->config->empire_mercenary_temporary || $mercenary_info[P_UNIT_TYPE] == UNIT_PLANS) {
205
      return true;
206
    }
207
208
//    if (isset($mercenary_info[P_REQUIRE])) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
209
//      foreach ($mercenary_info[P_REQUIRE] as $unit_id => $unit_level) {
210
//        if (mrc_get_level($user, [], $unit_id) < $unit_level) {
211
//          return false;
212
//        }
213
//      }
214
//    }
215
//
216
//    return true;
217
    return eco_can_build_unit($user, [], $mercenary_id) == BUILD_ALLOWED;
218
  }
219
220
  /**
221
   * @param \template $template
222
   */
223
  protected function fillDiscountTable($template) {
224
    foreach ($this->sn_powerup_buy_discounts as $hire_period => $hire_discount) {
225
      $template->assign_block_vars('period', array(
226
        'LENGTH'   => $hire_period,
227
        'TEXT'     => $this->lang['mrc_period_list'][$hire_period],
228
        'DISCOUNT' => $hire_period / $this->config->empire_mercenary_base_period * $hire_discount,
229
        'SELECTED' => $hire_period == $this->config->empire_mercenary_base_period,
230
      ));
231
    }
232
  }
233
234
  /**
235
   * @param $user
236
   *
237
   * @return array
238
   */
239
  protected function modelMercenaryHire($user) {
240
    $operation_result = [];
241
    if ($mercenary_id = sys_get_param_int('mercenary_id')) {
242
      try {
243
        $this->mrc_mercenary_hire($user, $mercenary_id);
244
      } catch (Exception $e) {
245
        sn_db_transaction_rollback();
246
        $operation_result = array(
247
          'STATUS'  => in_array($e->getCode(), array(ERR_NONE, ERR_WARNING, ERR_ERROR)) ? $e->getCode() : ERR_ERROR,
248
          'MESSAGE' => $this->lang[$e->getMessage()],
249
        );
250
      }
251
    }
252
253
    return $operation_result;
254
  }
255
256
  /**
257
   * @param array $user
258
   * @param int   $mercenary_id
259
   * @param float $darkmater_cost
260
   * @param int   $mercenary_level
261
   */
262
  protected function mercenaryDismiss($user, $mercenary_id, $darkmater_cost, $mercenary_level) {
263
    if ((!$darkmater_cost || !$mercenary_level) && $this->isUnitsPermanent) {
264
      return;
265
    }
266
267
    $unit_row = DBStaticUnit::db_unit_by_location($user['id'], LOC_USER, $user['id'], $mercenary_id);
268
    if (is_array($unit_row) && ($dismiss_left_days = floor((strtotime($unit_row['unit_time_finish']) - SN_TIME_NOW) / PERIOD_DAY))) {
269
      $dismiss_full_cost = eco_get_total_cost($mercenary_id, $unit_row['unit_level']);
270
      $dismiss_full_cost = $dismiss_full_cost[BUILD_CREATE][RES_DARK_MATTER];
271
272
      $dismiss_full_days = round((strtotime($unit_row['unit_time_finish']) - strtotime($unit_row['unit_time_start'])) / PERIOD_DAY);
273
      rpg_points_change($user['id'], RPG_MERCENARY_DISMISSED, 0,
274
        sprintf($this->lang['mrc_mercenary_dismissed_log'], $this->lang['tech'][$mercenary_id], $mercenary_id, $dismiss_full_cost, $dismiss_full_days,
275
          $unit_row['unit_time_start'], $unit_row['unit_time_finish'], $dismiss_left_days, floor($dismiss_full_cost * $dismiss_left_days / $dismiss_full_days)
276
        ));
277
    }
278
    DBStaticUnit::db_unit_list_delete($user['id'], LOC_USER, $user['id'], $mercenary_id);
279
  }
280
281
  /**
282
   * @param           $user
283
   * @param           $mercenary
284
   * @param template  $template
285
   */
286
  protected function renderMercenaryReq(&$user, $mercenary, $template) {
287
    if (empty($mercenary[P_REQUIRE]) || !is_array($mercenary[P_REQUIRE])) {
288
      return;
289
    }
290
291
    foreach ($mercenary[P_REQUIRE] as $requireUnitId => $requireLevel) {
292
      $template->assign_block_vars('officer.require', $q = [
293
        'ID'             => $requireUnitId,
294
        'LEVEL_GOT'      => mrc_get_level($user, [], $requireUnitId),
295
        'LEVEL_REQUIRED' => $requireLevel,
296
        'NAME'           => \HelperString::htmlSafe($this->lang['tech'][$requireUnitId])
297
      ]);
298
    }
299
  }
300
301
  /**
302
   * @param float    $user_dark_matter
303
   * @param int      $mercenary_id
304
   * @param float    $currentCost
305
   * @param template $template
306
   * @param int      $mercenary_level
307
   * @param          $mercenary_max_level
308
   */
309
  protected function renderMercenaryLevelsAvail($user_dark_matter, $mercenary_id, $currentCost, $template, $mercenary_level, $mercenary_max_level) {
310
    $upgrade_cost = 1;
311
    for (
312
      $i = $this->config->empire_mercenary_temporary ? 1 : $mercenary_level + 1;
313
      $mercenary_max_level ? ($i <= $mercenary_max_level) : $upgrade_cost <= $user_dark_matter;
314
      $i++
315
    ) {
316
      $newCost = eco_get_total_cost($mercenary_id, $i);
317
      $upgrade_cost = $newCost[BUILD_CREATE][RES_DARK_MATTER] * $this->cost_alliance_multiplier - $currentCost;
318
      $template->assign_block_vars('officer.level', array(
319
        'VALUE' => $i,
320
        'PRICE' => $upgrade_cost,
321
      ));
322
    }
323
  }
324
325
}
326