Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Pull Request — main (#1494)
by Dan
08:06 queued 03:15
created

ForcesDropProcessor   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 127
dl 0
loc 234
rs 2.64
c 1
b 0
f 0
wmc 72

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
F build() 0 221 71

How to fix   Complexity   

Complex Class

Complex classes like ForcesDropProcessor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ForcesDropProcessor, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Smr\Pages\Player;
4
5
use AbstractSmrPlayer;
6
use Globals;
7
use Smr\Page\PlayerPageProcessor;
8
use Smr\Request;
9
use SmrForce;
10
11
class ForcesDropProcessor extends PlayerPageProcessor {
12
13
	public function __construct(
14
		private readonly int $ownerAccountID,
15
		private readonly ?int $dropMines = null,
16
		private readonly ?int $takeMines = null,
17
		private readonly ?int $dropCDs = null,
18
		private readonly ?int $takeCDs = null,
19
		private readonly ?int $dropSDs = null,
20
		private readonly ?int $takeSDs = null,
21
		private readonly ?string $referrer = null
22
	) {}
23
24
	public function build(AbstractSmrPlayer $player): never {
25
		$ship = $player->getShip();
26
27
		if ($player->getNewbieTurns() > 0) {
28
			create_error('You can\'t take/drop forces under newbie protection!');
29
		}
30
31
		if ($player->isLandedOnPlanet()) {
32
			create_error('You must first launch to drop forces!');
33
		}
34
35
		if ($player->getSector()->hasLocation()) {
36
			create_error('You can\'t drop forces in a sector with a location!');
37
		}
38
39
		// take either from container or request, prefer container
40
		$drop_mines = $this->dropMines ?? Request::getInt('drop_mines', 0);
41
		$take_mines = $this->takeMines ?? Request::getInt('take_mines', 0);
42
		$drop_combat_drones = $this->dropCDs ?? Request::getInt('drop_combat_drones', 0);
43
		$take_combat_drones = $this->takeCDs ?? Request::getInt('take_combat_drones', 0);
44
		$drop_scout_drones = $this->dropSDs ?? Request::getInt('drop_scout_drones', 0);
45
		$take_scout_drones = $this->takeSDs ?? Request::getInt('take_scout_drones', 0);
46
47
		// so how many forces do we take/add per type?
48
		$change_mines = $drop_mines - $take_mines;
49
		$change_combat_drones = $drop_combat_drones - $take_combat_drones;
50
		$change_scout_drones = $drop_scout_drones - $take_scout_drones;
51
52
		$forces = SmrForce::getForce($player->getGameID(), $player->getSectorID(), $this->ownerAccountID);
53
54
		// check max on that stack
55
		$at_max = false;
56
		if ($forces->getMines() + $change_mines > SmrForce::MAX_MINES) {
57
			$change_mines = SmrForce::MAX_MINES - $forces->getMines();
58
			$at_max = $change_mines == 0;
59
		}
60
61
		if ($forces->getCDs() + $change_combat_drones > SmrForce::MAX_CDS) {
62
			$change_combat_drones = SmrForce::MAX_CDS - $forces->getCDs();
63
			$at_max = $change_combat_drones == 0;
64
		}
65
66
		if ($forces->getSDs() + $change_scout_drones > SmrForce::MAX_SDS) {
67
			$change_scout_drones = SmrForce::MAX_SDS - $forces->getSDs();
68
			$at_max = $change_scout_drones == 0;
69
		}
70
71
		// Check if the delta is 0 after applying the caps, in case by applying the caps we actually changed it to 0.
72
		if ($change_mines == 0 && $change_combat_drones == 0 && $change_scout_drones == 0) {
73
			if ($at_max) {
74
				// If no forces added only because the stack is full
75
				create_error('This stack can\'t hold any more of those forces!');
76
			} else {
77
				// If drop == take
78
				create_error('You want to add/remove 0 forces?');
79
			}
80
		}
81
82
		// NOTE: we do all error checking first, because any forces we remove from
83
		// the ship will vanish if we hit an error afterwards. This is because we
84
		// don't update the force stack expire time until the end of this script.
85
		// Force stacks without an updated expire time are automatically removed.
86
		//
87
		// We don't make the expire time update part of every force change internally
88
		// because those functions are used to remove forces via combat (which isn't
89
		// supposed to update the expire time).
90
91
		if ($change_combat_drones != 0) {
92
			// we can't take more forces than are in sector
93
			if ($forces->getCDs() + $change_combat_drones < 0) {
94
				create_error('You can\'t take more combat drones than are on this stack!');
95
			}
96
97
			if ($ship->getCDs() - $change_combat_drones > $ship->getMaxCDs()) {
98
				create_error('Your ships supports no more than ' . $ship->getMaxCDs() . ' combat drones!');
99
			}
100
101
			if ($ship->getCDs() - $change_combat_drones < 0) {
102
				create_error('You can\'t drop more combat drones than you carry!');
103
			}
104
		}
105
106
		if ($change_scout_drones != 0) {
107
			// we can't take more forces than are in sector
108
			if ($forces->getSDs() + $change_scout_drones < 0) {
109
				create_error('You can\'t take more scout drones than are on this stack!');
110
			}
111
112
			if ($ship->getSDs() - $change_scout_drones > $ship->getMaxSDs()) {
113
				create_error('Your ships supports no more than ' . $ship->getMaxSDs() . ' scout drones!');
114
			}
115
116
			if ($ship->getSDs() - $change_scout_drones < 0) {
117
				create_error('You can\'t drop more scout drones than you carry!');
118
			}
119
		}
120
121
		if ($change_mines != 0) {
122
			// we can't take more forces than are in sector
123
			if ($forces->getMines() + $change_mines < 0) {
124
				create_error('You can\'t take more mines than are on this stack!');
125
			}
126
127
			if ($ship->getMines() - $change_mines > $ship->getMaxMines()) {
128
				create_error('Your ships supports no more than ' . $ship->getMaxMines() . ' mines!');
129
			}
130
131
			if ($ship->getMines() - $change_mines < 0) {
132
				create_error('You can\'t drop more mines than you carry!');
133
			}
134
		}
135
136
		// All error checking is done, so now update the ship/force
137
138
		if ($change_combat_drones != 0) {
139
			if ($change_combat_drones > 0) {
140
				$ship->decreaseCDs($change_combat_drones);
141
				$forces->addCDs($change_combat_drones);
142
			} else {
143
				$ship->increaseCDs(-$change_combat_drones);
144
				$forces->takeCDs(-$change_combat_drones);
145
			}
146
		}
147
148
		if ($change_scout_drones != 0) {
149
			if ($change_scout_drones > 0) {
150
				$ship->decreaseSDs($change_scout_drones);
151
				$forces->addSDs($change_scout_drones);
152
			} else {
153
				$ship->increaseSDs(-$change_scout_drones);
154
				$forces->takeSDs(-$change_scout_drones);
155
			}
156
		}
157
158
		if ($change_mines != 0) {
159
			if ($change_mines > 0) {
160
				$ship->decreaseMines($change_mines);
161
				$forces->addMines($change_mines);
162
				if ($ship->isCloaked()) {
163
					$ship->decloak();
164
					$player->giveTurns(1);
165
				}
166
			} else {
167
				$ship->increaseMines(-$change_mines);
168
				$forces->takeMines(-$change_mines);
169
			}
170
		}
171
172
		// message to send out
173
		if ($forces->getOwnerID() != $player->getAccountID() && $forces->getOwner()->isForceDropMessages()) {
174
			$mines_message = '';
175
			if ($change_mines > 0) {
176
				$mines_message = 'added ' . pluralise($change_mines, 'mine');
177
			} elseif ($change_mines < 0) {
178
				$mines_message = 'removed ' . pluralise(abs($change_mines), 'mine');
179
			}
180
181
			if ($change_combat_drones > 0) {
182
				$combat_drones_message = ($change_mines <= 0 ? 'added ' : '') . pluralise($change_combat_drones, 'combat drone');
183
			} elseif ($change_combat_drones < 0) {
184
				$combat_drones_message = ($change_mines >= 0 ? 'removed ' : '') . pluralise(abs($change_combat_drones), 'combat drone');
185
			}
186
187
			if ($change_scout_drones > 0) {
188
				$scout_drones_message = '';
189
				if ((isset($combat_drones_message) && $change_combat_drones < 0) || (!isset($combat_drones_message) && $change_mines <= 0)) {
190
					$scout_drones_message = 'added ';
191
				}
192
				$scout_drones_message .= pluralise($change_scout_drones, 'scout drone');
193
			} elseif ($change_scout_drones < 0) {
194
				$scout_drones_message = '';
195
				if ((isset($combat_drones_message) && $change_combat_drones > 0) || (!isset($combat_drones_message) && $change_mines >= 0)) {
196
					$scout_drones_message = 'removed ';
197
				}
198
				$scout_drones_message .= pluralise(abs($change_scout_drones), 'scout drone');
199
			}
200
201
			// now compile it together
202
			$message = $player->getBBLink() . ' has ' . $mines_message;
203
204
			if (!empty($mines_message) && isset($combat_drones_message) && !isset($scout_drones_message)) {
205
				$message .= ' and ' . $combat_drones_message;
206
			} elseif (!empty($mines_message) && isset($combat_drones_message)) {
207
				$message .= ', ' . $combat_drones_message;
208
			} elseif (empty($mines_message) && isset($combat_drones_message)) {
209
				$message .= $combat_drones_message;
210
			}
211
212
			if (!empty($mines_message) && isset($combat_drones_message) && isset($scout_drones_message)) {
213
				$message .= ', and ' . $scout_drones_message;
214
			} elseif ((!empty($mines_message) || isset($combat_drones_message)) && isset($scout_drones_message)) {
215
				$message .= ' and ' . $scout_drones_message;
216
			} elseif (empty($mines_message) && !isset($combat_drones_message) && isset($scout_drones_message)) {
217
				$message .= $scout_drones_message;
218
			}
219
220
			if ($change_mines >= 0 && $change_combat_drones >= 0 && $change_scout_drones >= 0) {
221
				$message .= ' to';
222
			} elseif ($change_mines <= 0 && $change_combat_drones <= 0 && $change_scout_drones <= 0) {
223
				$message .= ' from';
224
			} else {
225
				$message .= ' from/to';
226
			}
227
228
			$message .= ' your stack in sector ' . Globals::getSectorBBLink($forces->getSectorID());
229
230
			$player->sendMessage($forces->getOwnerID(), MSG_SCOUT, $message, false);
231
		}
232
233
		$player->log(LOG_TYPE_FORCES, $change_combat_drones . ' combat drones, ' . $change_scout_drones . ' scout drones, ' . $change_mines . ' mines');
234
235
		$forces->updateExpire();
236
		$forces->update(); // Needs to be in db to show up on CS instantly when querying sector forces
237
238
		// If we dropped forces from the Local Map, stay on that page
239
		if ($this->referrer === LocalMap::class) {
240
			$container = new LocalMap();
241
		} else {
242
			$container = new CurrentSector();
243
		}
244
		$container->go();
245
	}
246
247
}
248