'Full Frame', 'APS-C' => 'APS-C', 'Micro Four Thirds' => 'Micro Four Thirds', '1 Inch' => '1 Inch', 'Lainnya' => 'Lainnya', ]; } public static function deriveFromSpecs(array $specs): array { $hargaSewa = max((int) ($specs['harga_sewa'] ?? 0), 0); $iso = max((int) ($specs['iso'] ?? 0), 0); $afPoint = max((int) ($specs['af_point'] ?? 0), 0); $sensor = self::normalizeSensor((string) ($specs['sensor'] ?? '')); $sensorScore = self::sensorScore($sensor); return [ // Cost criterion for TOPSIS uses rental price directly. 'price' => $hargaSewa, 'sensor' => $sensor, 'sensor_score' => $sensorScore, // Auxiliary scores are derived consistently to avoid free-form admin scoring. 'low_light' => self::lowLightScore($iso, $sensorScore), 'portabilitas' => self::portabilityScore($sensor), 'af_speed' => self::afSpeedScore($afPoint), ]; } public static function normalizeSensor(string $sensor): string { $normalized = strtolower(trim($sensor)); return match ($normalized) { 'full frame', 'full-frame' => 'Full Frame', 'aps-c', 'apsc' => 'APS-C', 'micro four thirds', 'micro 4/3', 'mft' => 'Micro Four Thirds', '1 inch', '1-inch', '1"' => '1 Inch', default => 'Lainnya', }; } public static function sensorScore(string $sensor): int { return match (self::normalizeSensor($sensor)) { 'Full Frame' => 10, 'APS-C' => 8, 'Micro Four Thirds' => 6, '1 Inch' => 4, default => 3, }; } public static function lowLightScore(int $iso, int $sensorScore): float { $isoContribution = min($iso / 12800, 1) * 7; $sensorContribution = ($sensorScore / 10) * 3; return round(min($isoContribution + $sensorContribution, 10), 1); } public static function portabilityScore(string $sensor): float { return match (self::normalizeSensor($sensor)) { '1 Inch' => 9.0, 'Micro Four Thirds' => 8.0, 'APS-C' => 7.0, 'Full Frame' => 5.0, default => 6.0, }; } public static function afSpeedScore(int $afPoint): float { return match (true) { $afPoint >= 500 => 10.0, $afPoint >= 300 => 9.0, $afPoint >= 150 => 8.0, $afPoint >= 75 => 7.0, $afPoint >= 25 => 5.0, $afPoint >= 9 => 3.0, default => 2.0, }; } }