| Code Coverage
| Lines | Functions and Methods | Classes and Traits
Total | 86.67% covered (warning) | 86.67% | 39 / 45 | 60.00% covered (warning) | 60.00% | 3 / 5 | CRAP | 0.00% covered (danger) | 0.00% | 0 / 1
EvaluationEngineService | 86.67% covered (warning) | 86.67% | 39 / 45 | 60.00% covered (warning) | 60.00% | 3 / 5 | 14.46 | 0.00% covered (danger) | 0.00% | 0 / 1
getActiveRuleSet | 64.29% covered (warning) | 64.29% | 9 / 14 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.18 |
evaluate | 100.00% covered (success) | 100.00% | 7 / 7 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
calculateFinalScore | 90.00% covered (success) | 90.00% | 9 / 10 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.01 |
calculateStatus | 100.00% covered (success) | 100.00% | 13 / 13 | 100.00% covered (success) | 100.00% | 1 / 1 | 7 |
isEligibleForAdvancement | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |

1 | <?php
2 |
3 | namespace App\Services;
4 |
5 | class EvaluationEngineService
6 | {
7 | /**
8 | * @return array<string, float|int|string|bool|null>
9 | */
10 | public function getActiveRuleSet(): array
11 | {
12 | $rule = db_connect()
13 | ->table('evaluation_rules')
14 | ->where('is_active', 1)
15 | ->orderBy('scope_type', 'ASC')
16 | ->orderBy('id', 'DESC')
17 | ->get()
18 | ->getRowArray();
19 |
20 | if ($rule !== null) {
21 | return $rule;
22 | }
23 |
24 | return [
25 | 'almost_ready_threshold' => 3.5,
26 | 'ready_threshold' => 4.0,
27 | 'minimum_critical_threshold' => 3.0,
28 | ];
29 | }
30 |
31 | /**
32 | * @param array<int, array<string, float|int|bool|null>> $criteriaScores
33 | * @param array<string, float|int|string|bool|null> $rules
34 | * @return array{final_score: float, final_status: string, promotion_signal: bool}
35 | */
36 | public function evaluate(array $criteriaScores, array $rules): array
37 | {
38 | $finalScore = $this->calculateFinalScore($criteriaScores);
39 | $status = $this->calculateStatus($finalScore, $criteriaScores, $rules);
40 |
41 | return [
42 | 'final_score' => $finalScore,
43 | 'final_status' => $status,
44 | 'promotion_signal' => $this->isEligibleForAdvancement($finalScore, $criteriaScores, $rules),
45 | ];
46 | }
47 |
48 | /**
49 | * @param array<int, array<string, float|int|bool|null>> $criteriaScores
50 | */
51 | public function calculateFinalScore(array $criteriaScores): float
52 | {
53 | $weightedScore = 0.0;
54 | $weightTotal = 0.0;
55 |
56 | foreach ($criteriaScores as $criterion) {
57 | $score = (float) ($criterion['score'] ?? 0);
58 | $weight = (float) ($criterion['weight'] ?? 1);
59 |
60 | $weightedScore += $score * $weight;
61 | $weightTotal += $weight;
62 | }
63 |
64 | if ($weightTotal === 0.0) {
65 | return 0.0;
66 | }
67 |
68 | return round($weightedScore / $weightTotal, 2);
69 | }
70 |
71 | /**
72 | * @param array<int, array<string, float|int|bool|null>> $criteriaScores
73 | * @param array<string, float|int|string|bool|null> $rules
74 | */
75 | public function calculateStatus(float $finalScore, array $criteriaScores, array $rules): string
76 | {
77 | $readyThreshold = (float) ($rules['ready_threshold'] ?? 4.0);
78 | $almostReadyThreshold = (float) ($rules['almost_ready_threshold'] ?? 3.5);
79 | $minimumCriticalThreshold = (float) ($rules['minimum_critical_threshold'] ?? 3.0);
80 |
81 | foreach ($criteriaScores as $criterion) {
82 | $isCritical = (bool) ($criterion['is_critical'] ?? false);
83 | $score = (float) ($criterion['score'] ?? 0);
84 |
85 | if ($isCritical && $score < $minimumCriticalThreshold) {
86 | return $finalScore >= $almostReadyThreshold ? 'ALMOST READY' : 'HOLD';
87 | }
88 | }
89 |
90 | if ($finalScore >= $readyThreshold) {
91 | return 'READY';
92 | }
93 |
94 | if ($finalScore >= $almostReadyThreshold) {
95 | return 'ALMOST READY';
96 | }
97 |
98 | return 'HOLD';
99 | }
100 |
101 | /**
102 | * @param array<int, array<string, float|int|bool|null>> $criteriaScores
103 | * @param array<string, float|int|string|bool|null> $rules
104 | */
105 | public function isEligibleForAdvancement(float $finalScore, array $criteriaScores, array $rules): bool
106 | {
107 | return $this->calculateStatus($finalScore, $criteriaScores, $rules) === 'READY';
108 | }
109 | }