Importer::createTeams()   A
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 2
b 0
f 0
nc 7
nop 2
dl 0
loc 15
ccs 10
cts 10
cp 1
crap 5
rs 9.6111
1
<?php
2
3
4
namespace TournamentGenerator\Import;
5
6
use Exception;
7
use JsonException;
8
use TournamentGenerator\Base;
9
use TournamentGenerator\Category;
10
use TournamentGenerator\Group;
11
use TournamentGenerator\Interfaces\WithGames;
12
use TournamentGenerator\Interfaces\WithSkipSetters;
13
use TournamentGenerator\Round;
14
use TournamentGenerator\Team;
15
use TournamentGenerator\TeamFilter;
16
use TournamentGenerator\Tournament;
17
18
/**
19
 * Basic importer
20
 *
21
 * Importer uses exported data and creates a new tournament objects from it.
22
 *
23
 * @package TournamentGenerator\Import
24
 * @author  Tomáš Vojík <[email protected]>
25
 * @since   0.5
26
 */
27
class Importer
28
{
29
	/** @var array List of $categoryId => $parent */
30
	protected static array $categories = [];
31
	/** @var array List of $roundId => $parent */
32
	protected static array $rounds = [];
33
	/** @var array List of $groupId => $parent */
34
	protected static array $groups = [];
35
	/** @var array List of $teamId => $parent */
36
	protected static array $teams = [];
37
	/** @var array List of $gameId => $parent */
38
	protected static array $games = [];
39
40
	/** @var Base|null $root Root object - returned from import */
41
	protected static ?Base $root = null;
42
43
	/**
44
	 * Processes a JSON input and creates necessary objects from it
45
	 *
46
	 * @param string $data
47
	 *
48
	 * @return Base
49
	 * @throws JsonException
50
	 * @throws InvalidImportDataException
51
	 * @see Importer::import()
52
	 *
53
	 */
54 35
	public static function importJson(string $data) : ?Base {
55 35
		return self::import(json_decode($data, true, 512, JSON_THROW_ON_ERROR));
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::import(json_decode...t\JSON_THROW_ON_ERROR)) targeting TournamentGenerator\Import\Importer::import() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
56
	}
57
58
	/**
59
	 * Processes an input array of data and creates necessary objects from it
60
	 *
61
	 * @param array $data
62
	 *
63
	 * @return Base Imported root object or null if nothing was created
64
	 *
65
	 * @throws InvalidImportDataException
66
	 * @throws Exception
67
	 */
68 37
	public static function import(array $data) : ?Base {
69
		// Validate data
70 37
		ImportValidator::validate($data);
71
72
		// Groups for parent logging
73
		// This allows setting a parent to other objects. The latest parent in hierarchy.
74 37
		self::$categories = [];
75 37
		self::$rounds = [];
76 37
		self::$groups = [];
77 37
		self::$teams = [];
78 37
		self::$games = [];
79
80
		// Reset root
81 37
		self::$root = null;
82
83
		// Helper array - $id => $object reference
84 37
		$allGroups = [];
85 37
		$allTeams = [];
86
87
		// Try setting up the tournament object
88 37
		self::createTournament((array) ($data['tournament'] ?? []));
89
90
		// Try setting up all category objects
91 37
		self::createCategories($data['categories'] ?? []);
92
93
		// Try setting up all round objects
94 37
		self::createRounds($data['rounds'] ?? []);
95
96
		// Try setting up all group objects
97 37
		self::createGroups($data['groups'] ?? [], $allGroups);
98
99
		// Try setting up all progression objects
100 37
		self::createProgressions($data['progressions'] ?? [], $allGroups);
101
102
		// Try setting up all team objects
103 37
		self::createTeams($data['teams'] ?? [], $allTeams);
104
105
		// Try setting up all game objects
106 37
		self::createGames($data['games'] ?? [], $allTeams);
107
108 37
		return self::$root;
109
	}
110
111
	/**
112
	 * Creates a tournament object
113
	 *
114
	 * @param array $setting
115
	 */
116 37
	protected static function createTournament(array $setting) : void {
117 37
		if (!empty($setting)) {
118
			// Check tournament type (can be a preset)
119 14
			if (empty($setting['type']) || $setting['type'] === 'general') {
120 11
				$tournament = new Tournament();
121
			}
122
			else {
123 3
				$tournament = new $setting['type'];
124
			}
125 14
			self::$root = $tournament; // If set - Tournament is always root
126
127 14
			self::setTournament($tournament, $setting);
128 14
			self::logAllIds($setting, $tournament);
129
		}
130 37
	}
131
132
	/**
133
	 * Setup a tournament with all its settings
134
	 *
135
	 * @param Tournament $tournament
136
	 * @param array      $setting
137
	 */
138 14
	protected static function setTournament(Tournament $tournament, array $setting) : void {
139 14
		foreach ($setting as $key => $value) {
140 14
			switch ($key) {
141 14
				case 'name':
142 14
					$tournament->setName($value);
143 14
					break;
144 14
				case 'skip':
145 10
					$tournament->setSkip($value);
146 10
					break;
147 14
				case 'timing':
148 10
					self::setTiming($tournament, (array) $value);
149 10
					break;
150
			}
151
		}
152 14
	}
153
154
	/**
155
	 * Set timing setting to a tournament object
156
	 *
157
	 * @param Tournament $object
158
	 * @param array      $setting
159
	 */
160 10
	protected static function setTiming(Tournament $object, array $setting) : void {
161 10
		foreach ($setting as $key2 => $value2) {
162 10
			switch ($key2) {
163 10
				case 'play':
164 10
					$object->setPlay($value2);
165 10
					break;
166 9
				case 'gameWait':
167 9
					$object->setGameWait($value2);
168 9
					break;
169 9
				case 'categoryWait':
170 9
					$object->setCategoryWait($value2);
171 9
					break;
172 9
				case 'roundWait':
173 9
					$object->setRoundWait($value2);
174 9
					break;
175
			}
176
		}
177 10
	}
178
179
	/**
180
	 * Log all set ids and objects into helper arrays
181
	 *
182
	 * Adds an $id => $object pair for each id and group. Sets an game autoincrement value to the lowest possible game id if the object is root.
183
	 *
184
	 * @param array $setting Object's settings
185
	 * @param Base  $object  Object that is logged
186
	 *
187
	 * @see Importer::addIds()
188
	 */
189 34
	protected static function logAllIds(array $setting, Base $object) : void {
190 34
		self::addIds(self::$categories, $object, $setting['categories'] ?? []);
191 34
		self::addIds(self::$rounds, $object, $setting['rounds'] ?? []);
192 34
		self::addIds(self::$groups, $object, $setting['groups'] ?? []);
193 34
		self::addIds(self::$teams, $object, $setting['teams'] ?? [], true);
194 34
		self::addIds(self::$games, $object, $setting['games'] ?? []);
195
		/** @noinspection NotOptimalIfConditionsInspection */
196 34
		if (self::$root === $object && !empty($setting['games']) && $object instanceof WithGames) {
197 9
			$object->getGameContainer()->setAutoIncrement(min($setting['games']));
198
		}
199 34
	}
200
201
	/**
202
	 * Log an object as parent to other object
203
	 *
204
	 * Adds an $id => $object pairs for each id into $group.
205
	 *
206
	 * @param array $group  Group to log the object into
207
	 * @param Base  $object Object to log
208
	 * @param array $ids    List of child object ids
209
	 */
210 34
	protected static function addIds(array &$group, Base $object, array $ids, bool $multiple = false) : void {
211 34
		foreach ($ids as $id) {
212 16
			if ($multiple) {
213 11
				if (!isset($group[$id])) {
214 11
					$group[$id] = [];
215
				}
216 11
				$group[$id][] = $object;
217 11
				continue;
218
			}
219 16
			$group[$id] = $object;
220
		}
221 34
	}
222
223
	/**
224
	 * Create category objects
225
	 *
226
	 * @param array $categories
227
	 */
228 37
	protected static function createCategories(array $categories) : void {
229 37
		foreach ($categories as $setting) {
230
			// Typecast settings
231 11
			$setting = (array) $setting;
232 11
			$category = new Category($setting['name'] ?? '', $setting['id'] ?? null);
233
234 11
			if (!isset(self::$root)) {
235 6
				self::$root = $category;
236
			}
237
238 11
			self::setSkip($category, $setting);
239
240
			// Set parent if exists
241 11
			if (isset(self::$categories[$setting['id'] ?? $category->getId()])) {
242 5
				self::$categories[$setting['id'] ?? $category->getId()]->addCategory($category);
243
			}
244
245 11
			self::logAllIds($setting, $category);
246
		}
247 37
	}
248
249
	/**
250
	 * Set skip setting to an object
251
	 *
252
	 * @param WithSkipSetters $category
253
	 * @param array           $setting
254
	 */
255 28
	protected static function setSkip(WithSkipSetters $category, array $setting) : void {
256 28
		if (isset($setting['skip'])) {
257 25
			$category->setSkip($setting['skip']);
258
		}
259 28
	}
260
261
	/**
262
	 * Create round objects
263
	 *
264
	 * @param array $rounds
265
	 */
266 37
	protected static function createRounds(array $rounds) : void {
267 37
		foreach ($rounds as $setting) {
268
			// Typecast settings
269 17
			$setting = (array) $setting;
270 17
			$round = new Round($setting['name'] ?? '', $setting['id'] ?? null);
271
272 17
			if (!isset(self::$root)) {
273 8
				self::$root = $round;
274
			}
275
276 17
			self::setSkip($round, $setting);
277
278
			// Set parent if exists
279 17
			if (isset(self::$rounds[$setting['id'] ?? $round->getId()])) {
280 9
				self::$rounds[$setting['id'] ?? $round->getId()]->addRound($round);
281
			}
282 17
			self::logAllIds($setting, $round);
283
		}
284 37
	}
285
286
	/**
287
	 * Create group objects
288
	 *
289
	 * @param array $groups
290
	 * @param array $allGroups
291
	 *
292
	 * @throws Exception
293
	 */
294 37
	protected static function createGroups(array $groups, array &$allGroups) : void {
295 37
		foreach ($groups as $setting) {
296
			// Typecast settings
297 17
			$setting = (array) $setting;
298 17
			$group = new Group($setting['name'] ?? '', $setting['id'] ?? null);
299 17
			$allGroups[$group->getId()] = $group;
300
301 17
			if (!isset(self::$root)) {
302 6
				self::$root = $group;
303
			}
304
305 17
			self::setSkip($group, $setting);
306 17
			self::setGroup($group, $setting);
307
308
			// Set parent if exists
309 17
			if (isset(self::$groups[$setting['id'] ?? $group->getId()])) {
310 11
				self::$groups[$setting['id'] ?? $group->getId()]->addGroup($group);
311
			}
312 17
			self::logAllIds($setting, $group);
313
		}
314 37
	}
315
316
	/**
317
	 * Setup a group with all its settings
318
	 *
319
	 * @param Group $group
320
	 * @param array $setting
321
	 *
322
	 * @throws Exception
323
	 */
324 17
	protected static function setGroup(Group $group, array $setting) : void {
325 17
		foreach ($setting as $key => $value) {
326 17
			switch ($key) {
327 17
				case 'type':
328 17
					$group->setType($value);
329 17
					break;
330 17
				case 'points':
331 17
					self::setPoints($group, (array) $value);
332 17
					break;
333 17
				case 'inGame':
334 17
					$group->setInGame($value);
335 17
					break;
336 17
				case 'maxSize':
337 17
					$group->setMaxSize($value);
338 17
					break;
339
			}
340
		}
341 17
	}
342
343
	/**
344
	 * Set points setting to an object
345
	 *
346
	 * @param Group $object
347
	 * @param array $setting
348
	 */
349 17
	protected static function setPoints(Group $object, array $setting) : void {
350 17
		foreach ($setting as $key2 => $value2) {
351 17
			switch ($key2) {
352 17
				case 'win':
353 17
					$object->setWinPoints($value2);
354 17
					break;
355 17
				case 'loss':
356 17
					$object->setLostPoints($value2);
357 17
					break;
358 17
				case 'draw':
359 17
					$object->setDrawPoints($value2);
360 17
					break;
361 17
				case 'second':
362 17
					$object->setSecondPoints($value2);
363 17
					break;
364 17
				case 'third':
365 17
					$object->setThirdPoints($value2);
366 17
					break;
367 17
				case 'progression':
368 17
					$object->setProgressPoints($value2);
369 17
					break;
370
			}
371
		}
372 17
	}
373
374
	/**
375
	 * Create all progressions
376
	 *
377
	 * @param array $progressions
378
	 * @param array $allGroups
379
	 */
380 37
	protected static function createProgressions(array $progressions, array $allGroups) : void {
381 37
		foreach ($progressions as $setting) {
382
			// Typecast settings
383 4
			$setting = (array) $setting;
384
385 4
			if (isset($setting['from'], $setting['to'], $allGroups[$setting['from']], $allGroups[$setting['to']])) {
386 4
				$progression = $allGroups[$setting['from']]->progression($allGroups[$setting['to']], $setting['offset'] ?? 0, $setting['length'] ?? null);
387
388
				// Setup filters
389 4
				foreach ($setting['filters'] ?? [] as $filterSetting) {
390
					// Typecast settings
391 2
					$filterSetting = (array) $filterSetting;
392
393 2
					self::$groups = array_map(static function($groupId) use ($allGroups) {
394 2
						return $allGroups[$groupId] ?? null;
395 2
					}, $filterSetting['groups'] ?? []);
396
397 2
					$filter = new TeamFilter($filterSetting['what'] ?? 'points', $filterSetting['how'] ?? '>', $filterSetting['val'] ?? 0, self::$groups);
398 2
					$progression->addFilter($filter);
399
				}
400
401 4
				if (isset($setting['progressed'])) {
402 4
					$progression->setProgressed($setting['progressed']);
403
				}
404
			}
405
		}
406 37
	}
407
408
	/**
409
	 * Create all team objects
410
	 *
411
	 * @param array $teams
412
	 * @param array $allTeams
413
	 */
414 37
	protected static function createTeams(array $teams, array &$allTeams) : void {
415 37
		foreach ($teams as $setting) {
416
			// Typecast settings
417 14
			$setting = (array) $setting;
418 14
			$team = new Team($setting['name'] ?? '', $setting['id'] ?? null);
419 14
			$allTeams[$team->getId()] = $team;
420
421 14
			if (!isset(self::$root)) {
422 3
				self::$root = $team;
423
			}
424
425
			// Set parent if exists
426 14
			if (isset(self::$teams[$setting['id'] ?? $team->getId()])) {
427 11
				foreach (self::$teams[$setting['id'] ?? $team->getId()] as $object) {
428 11
					$object->addTeam($team);
429
				}
430
			}
431
		}
432 37
	}
433
434
	/**
435
	 * Create all game objects
436
	 *
437
	 * @param       $games
438
	 * @param array $allTeams
439
	 */
440 37
	protected static function createGames($games, array $allTeams) : void {
441 37
		foreach ($games as $setting) {
442
			// Typecast settings
443 9
			$setting = (array) $setting;
444
445 9
			$gameTeams = array_map(static function($teamId) use ($allTeams) {
446 9
				return $allTeams[$teamId] ?? null;
447 9
			}, $setting['teams'] ?? []);
448
449
			// Check if parent group exists
450 9
			if (isset($setting['id'], self::$games[$setting['id']])) {
451
452 9
				$game = self::$games[$setting['id']]->game($gameTeams);
453
454
				// Set results
455 9
				if (isset($setting['scores'])) {
456 3
					$scores = array_map(static function($info) {
457 3
						return ((array) $info)['score'] ?? 0;
458 3
					}, $setting['scores']);
459 3
					$game->setResults($scores);
460
				}
461
462
			}
463
		}
464 37
	}
465
466
}