145 lines
5.3 KiB
PHP
145 lines
5.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Point UNIQUE de détermination du statut d'un objet céleste.
|
|
* Basé sur les règles configurées dans l'administration.
|
|
*/
|
|
function calculateCelestialStatus($planet, $db, $statuses_map) {
|
|
$profile_id = $planet['status_profile_id'] ?? null;
|
|
|
|
// Si pas de profil sur la planète, on prend celui du type d'objet
|
|
if (!$profile_id && isset($planet['type'])) {
|
|
$stmt = $db->prepare("SELECT status_profile_id FROM celestial_object_types WHERE slug = ?");
|
|
$stmt->execute([$planet['type']]);
|
|
$profile_id = $stmt->fetchColumn();
|
|
}
|
|
|
|
// Si toujours pas de profil, on retourne le statut actuel (fallback alpha)
|
|
if (!$profile_id) {
|
|
return $planet['status'];
|
|
}
|
|
|
|
// Récupération des règles du profil par priorité
|
|
$stmt = $db->prepare("SELECT r.*, s.slug as status_slug
|
|
FROM celestial_object_status_rules r
|
|
JOIN celestial_object_statuses s ON r.status_id = s.id
|
|
WHERE r.profile_id = ? AND r.is_active = 1
|
|
ORDER BY r.priority DESC, r.id ASC");
|
|
$stmt->execute([$profile_id]);
|
|
$rules = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Préparation des données de l'objet pour l'évaluation
|
|
$orbital_controls = $planet['orbital_controls'] ?? [];
|
|
$terrestrial_controls = $planet['terrestrial_controls'] ?? [];
|
|
|
|
// On exclut la faction "Aucune" (ID 1) et les valeurs nulles des comptes
|
|
$orbital_factions = array_filter($orbital_controls, fn($v, $k) => $v > 0 && $k != 1, ARRAY_FILTER_USE_BOTH);
|
|
$terrestrial_factions = array_filter($terrestrial_controls, fn($v, $k) => $v > 0 && $k != 1, ARRAY_FILTER_USE_BOTH);
|
|
|
|
$orb_count = count($orbital_factions);
|
|
$terr_count = count($terrestrial_factions);
|
|
|
|
$orb_dom = null;
|
|
if ($orb_count > 0) {
|
|
arsort($orbital_factions);
|
|
$orb_dom = array_key_first($orbital_factions);
|
|
}
|
|
|
|
$terr_dom = null;
|
|
if ($terr_count > 0) {
|
|
arsort($terrestrial_factions);
|
|
$terr_dom = array_key_first($terrestrial_factions);
|
|
}
|
|
|
|
$is_empty = ($orb_count === 0 && $terr_count === 0);
|
|
|
|
// Évaluation des règles
|
|
foreach ($rules as $rule) {
|
|
// Condition Case Vide (doit matcher avant de tester le reste)
|
|
if ($rule['is_empty_case'] && !$is_empty) continue;
|
|
|
|
$match_orbite = true;
|
|
$match_sol = true;
|
|
|
|
$has_orb_cond = !empty($rule['orbital_count_op']) || !empty($rule['orbital_dominance']);
|
|
$has_sol_cond = !empty($rule['terrestrial_count_op']) || !empty($rule['terrestrial_dominance']);
|
|
|
|
// Evaluation Orbite
|
|
if ($rule['orbital_count_op']) {
|
|
if (!evaluateOperator($orb_count, $rule['orbital_count_op'], $rule['orbital_count_val'])) {
|
|
$match_orbite = false;
|
|
}
|
|
}
|
|
if ($match_orbite && !empty($rule['orbital_dominance'])) {
|
|
$allowed = explode(',', $rule['orbital_dominance']);
|
|
$isIn = false;
|
|
if (!$orb_dom) {
|
|
if (in_array('none', $allowed)) $isIn = true;
|
|
} else {
|
|
if (in_array((string)$orb_dom, $allowed)) $isIn = true;
|
|
}
|
|
if (!$isIn) $match_orbite = false;
|
|
}
|
|
|
|
// Evaluation Sol
|
|
if ($rule['terrestrial_count_op']) {
|
|
if (!evaluateOperator($terr_count, $rule['terrestrial_count_op'], $rule['terrestrial_count_val'])) {
|
|
$match_sol = false;
|
|
}
|
|
}
|
|
if ($match_sol && !empty($rule['terrestrial_dominance'])) {
|
|
$allowed = explode(',', $rule['terrestrial_dominance']);
|
|
$isIn = false;
|
|
if (!$terr_dom) {
|
|
if (in_array('none', $allowed)) $isIn = true;
|
|
} else {
|
|
if (in_array((string)$terr_dom, $allowed)) $isIn = true;
|
|
}
|
|
if (!$isIn) $match_sol = false;
|
|
}
|
|
|
|
// Application de la combinaison
|
|
$combine = $rule['combine_mode'] ?? 'OR';
|
|
$final_match = false;
|
|
|
|
if (!$has_orb_cond && !$has_sol_cond) {
|
|
// Pas de conditions spécifiques (ex: règle par défaut ou juste is_empty_case)
|
|
$final_match = true;
|
|
} elseif ($has_orb_cond && !$has_sol_cond) {
|
|
$final_match = $match_orbite;
|
|
} elseif (!$has_orb_cond && $has_sol_cond) {
|
|
$final_match = $match_sol;
|
|
} else {
|
|
// Les deux côtés ont des conditions
|
|
if ($combine === 'AND') {
|
|
$final_match = $match_orbite && $match_sol;
|
|
} else {
|
|
$final_match = $match_orbite || $match_sol;
|
|
}
|
|
}
|
|
|
|
// Condition Croisée (Dominance différente requise)
|
|
if ($final_match && ($rule['dominance_diff_required'] ?? 0)) {
|
|
if ($orb_dom == $terr_dom) $final_match = false;
|
|
}
|
|
|
|
if ($final_match) {
|
|
return $rule['status_slug'];
|
|
}
|
|
}
|
|
|
|
// Fallback final si profil présent mais aucune règle ne matche
|
|
return 'sta_inhabited';
|
|
}
|
|
|
|
function evaluateOperator($val, $op, $target) {
|
|
switch ($op) {
|
|
case '=': return $val == $target;
|
|
case '>': return $val > $target;
|
|
case '<': return $val < $target;
|
|
case '>=': return $val >= $target;
|
|
case '<=': return $val <= $target;
|
|
case '!=': return $val != $target;
|
|
}
|
|
return true;
|
|
} |