-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPartRuleConfiguratorService.php
More file actions
104 lines (83 loc) · 3.06 KB
/
Copy pathPartRuleConfiguratorService.php
File metadata and controls
104 lines (83 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?php
namespace BSO\Survival\Service;
use BSO\Survival\Database\Repository\PartRuleRepositoryInterface;
use InvalidArgumentException;
use RuntimeException;
class PartRuleConfiguratorService {
private const ALLOWED_TIEBREAKERS = [
'manual_referee',
'lower_raw_wins',
'higher_raw_wins',
];
private const ALLOWED_CURVES = [
'linear',
];
/** @var PartRuleRepositoryInterface */
private $rules;
public function __construct(PartRuleRepositoryInterface $rules) {
$this->rules = $rules;
}
/**
* @param array<string, mixed> $config
*/
public function configure(int $partId, string $scoringMode, array $config, string $tiebreakerMode = 'manual_referee'): bool {
if ($partId <= 0) {
throw new InvalidArgumentException('part id must be a positive integer.');
}
$mode = trim($scoringMode);
if (!ScoringMethodRegistry::exists($mode)) {
throw new InvalidArgumentException(sprintf('Unsupported scoring mode: %s', $mode));
}
$method = ScoringMethodRegistry::get($mode);
if ($method === null) {
throw new RuntimeException(sprintf('Scoring method %s is not available.', $mode));
}
$validatedTiebreaker = $this->sanitizeTiebreakerMode($tiebreakerMode);
$validatedConfig = $this->sanitizeConfigByMode($mode, $config);
$configJson = function_exists('wp_json_encode')
? wp_json_encode($validatedConfig)
: json_encode($validatedConfig);
if (!is_string($configJson)) {
throw new RuntimeException('Failed to encode scoring_config.');
}
return $this->rules->upsertForPart(
$partId,
$mode,
$method->getFieldUnit(),
$validatedTiebreaker,
$configJson
);
}
private function sanitizeTiebreakerMode(string $tiebreakerMode): string {
$value = trim($tiebreakerMode);
if (!in_array($value, self::ALLOWED_TIEBREAKERS, true)) {
return 'manual_referee';
}
return $value;
}
/**
* @param array<string, mixed> $config
* @return array<string, mixed>
*/
private function sanitizeConfigByMode(string $mode, array $config): array {
$curve = isset($config['normalization_curve'])
? trim((string) $config['normalization_curve'])
: 'linear';
if (!in_array($curve, self::ALLOWED_CURVES, true)) {
$curve = 'linear';
}
$safe = [
'normalization_curve' => $curve,
];
if ($mode === 'time') {
$safe['max_time'] = isset($config['max_time']) ? max(1, (int) $config['max_time']) : 1200;
}
if ($mode === 'points') {
$safe['max_points'] = isset($config['max_points']) ? max(1, (int) $config['max_points']) : 100;
}
if ($mode === 'distance') {
$safe['max_distance'] = isset($config['max_distance']) ? max(1, (int) $config['max_distance']) : 500;
}
return $safe;
}
}