prepare("SELECT u.role, u.display_name, u.username, l.name as level_raw, u.selected_title_id, u.selected_badge_id, t.name as title_name, b.name as badge_name, b.image_url as badge_image FROM users u LEFT JOIN levels l ON u.level_id = l.id LEFT JOIN titles t ON u.selected_title_id = t.id LEFT JOIN badges b ON u.selected_badge_id = b.id WHERE u.id = ?"); $stmt->execute([$_SESSION['user_id']]); $u_data = $stmt->fetch(); if ($u_data) { $user_role = $u_data['role'] ?? 'user'; $_SESSION['display_name'] = $u_data['display_name'] ?: $u_data['username']; $level_num = (int)filter_var($u_data['level_raw'], FILTER_SANITIZE_NUMBER_INT); $_SESSION['level'] = $level_num; // Save title and badge to session for modal $_SESSION['selected_title_name'] = $u_data['title_name']; $_SESSION['selected_badge_name'] = $u_data['badge_name']; $_SESSION['selected_badge_image'] = $u_data['badge_image']; $grade_type = ($user_role === 'admin') ? 'admin' : 'utilisateur'; $g_stmt = $db->prepare("SELECT name, image_url FROM grades WHERE user_type = ? AND (min_level <= ? OR min_level IS NULL) AND (max_level >= ? OR max_level IS NULL) LIMIT 1"); $g_stmt->execute([$grade_type, $level_num, $level_num]); $grade_data = $g_stmt->fetch(); if ($grade_data) { $_SESSION['grade_name'] = $grade_data['name']; $_SESSION['grade_image'] = $grade_data['image_url']; } else { $_SESSION['grade_name'] = "Recrue"; $_SESSION['grade_image'] = "assets/images/placeholder_grade.png"; } } } $view = isset($_GET['view']) ? $_GET['view'] : 'sector'; $galaxy_id = isset($_GET['galaxy_id']) ? (int)$_GET['galaxy_id'] : 1; $sector_id = isset($_GET['sector_id']) ? (int)$_GET['sector_id'] : 1; // Fetch Dynamic Types, Statuses and Factions $object_types_db = $db->query("SELECT * FROM celestial_object_types")->fetchAll(PDO::FETCH_ASSOC); $statuses_db = $db->query("SELECT * FROM celestial_object_statuses")->fetchAll(PDO::FETCH_ASSOC); $factions_db = $db->query("SELECT * FROM factions")->fetchAll(PDO::FETCH_ASSOC); $object_types_map = []; foreach($object_types_db as $ot) { // Get modifiers for this type $stmt = $db->prepare("SELECT m.* FROM modifiers m JOIN celestial_object_type_modifiers cotm ON m.id = cotm.modifier_id WHERE cotm.celestial_object_type_id = ?"); $stmt->execute([$ot['id']]); $ot['modifiers'] = $stmt->fetchAll(PDO::FETCH_ASSOC); $object_types_map[$ot['slug']] = $ot; } $statuses_map = []; foreach($statuses_db as $s) { $s['is_blinking'] = (strpos($s['color'], ';blink') !== false); $statuses_map[$s['slug']] = $s; } $factions_map = []; foreach($factions_db as $f) $factions_map[$f['id']] = $f; // Grid size: 6x6 = 36 slots per sector $grid_size = 36; // Dynamic Resources $resources = []; if (isset($_SESSION['user_id'])) { $stmt = $db->prepare(" SELECT gr.*, COALESCE(ur.amount, 0) as amount FROM game_resources gr LEFT JOIN user_resources ur ON gr.id = ur.resource_id AND ur.user_id = ? WHERE gr.show_in_header = 1 ORDER BY CASE WHEN gr.name = 'Crédits' THEN 1 WHEN gr.name = 'Materials' THEN 2 WHEN gr.name = 'Energie' THEN 3 WHEN gr.name = 'Données' THEN 4 ELSE 5 END ASC, gr.name ASC "); $stmt->execute([$_SESSION['user_id']]); $header_resources = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach($header_resources as $hr) { $resources[$hr["name"]] = [ "val" => (string)$hr["amount"], "prod" => "", "icon" => $hr["icon"] ?: "fa-gem", "image" => $hr["image_url"] ]; } } else { $header_resources = $db->query("SELECT * FROM game_resources WHERE show_in_header = 1 ORDER BY CASE WHEN name = 'Crédits' THEN 1 WHEN name = 'Materials' THEN 2 WHEN name = 'Energie' THEN 3 WHEN name = 'Données' THEN 4 ELSE 5 END ASC, name ASC")->fetchAll(PDO::FETCH_ASSOC); foreach($header_resources as $hr) { $resources[$hr["name"]] = ["val" => "0", "prod" => "", "icon" => $hr["icon"] ?: "fa-gem", "image" => $hr["image_url"]]; } } if ($view === 'sector') { $stmt = $db->prepare("SELECT * FROM planets WHERE galaxy_id = ? AND sector_id = ? AND slot BETWEEN 1 AND ?"); $stmt->execute([$galaxy_id, $sector_id, $grid_size]); $objects_raw = $stmt->fetchAll(); $grid = array_fill(1, $grid_size, null); $planet_ids = []; foreach ($objects_raw as $obj) { $grid[$obj['slot']] = $obj; $planet_ids[] = $obj['id']; $grid[$obj['slot']]['cities'] = []; $grid[$obj['slot']]['orbital_controls'] = []; $grid[$obj['slot']]['terrestrial_controls'] = []; } if (!empty($planet_ids)) { $placeholders = implode(',', array_fill(0, count($planet_ids), '?')); // Fetch Orbital Controls $stmt = $db->prepare("SELECT * FROM planet_faction_control WHERE planet_id IN ($placeholders)"); $stmt->execute($planet_ids); $orb_controls_raw = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($orb_controls_raw as $ocr) { foreach ($grid as &$slot_data) { if ($slot_data && $slot_data['id'] == $ocr['planet_id']) { $slot_data['orbital_controls'][$ocr['faction_id']] = $ocr['control_level']; } } } // Fetch Cities unset($slot_data); $stmt = $db->prepare("SELECT c.*, st.name as type_name FROM cities c LEFT JOIN settlement_types st ON c.settlement_type_id = st.id WHERE c.planet_id IN ($placeholders)"); $stmt->execute($planet_ids); $all_cities = $stmt->fetchAll(PDO::FETCH_ASSOC); $city_ids = array_column($all_cities, 'id'); $city_controls = []; if (!empty($city_ids)) { $c_placeholders = implode(',', array_fill(0, count($city_ids), '?')); $c_stmt = $db->prepare("SELECT * FROM city_faction_control WHERE city_id IN ($c_placeholders)"); $c_stmt->execute($city_ids); $controls_raw = $c_stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($controls_raw as $cr) { $city_controls[$cr['city_id']][$cr['faction_id']] = $cr['control_level']; } } $planet_terrestrial_agg = []; foreach ($all_cities as $city) { $pid = $city['planet_id']; $city['controls'] = $city_controls[$city['id']] ?? []; foreach ($city['controls'] as $fid => $lvl) { $planet_terrestrial_agg[$pid][$fid] = ($planet_terrestrial_agg[$pid][$fid] ?? 0) + $lvl; } foreach ($grid as &$slot_data) { if ($slot_data && $slot_data['id'] == $pid) { $slot_data['cities'][] = $city; } } } // Calculate average terrestrial control per faction foreach ($grid as &$slot_data) { if ($slot_data && !empty($slot_data['cities'])) { $num_cities = count($slot_data['cities']); $pid = $slot_data['id']; if (isset($planet_terrestrial_agg[$pid])) { foreach ($planet_terrestrial_agg[$pid] as $fid => $total_lvl) { $slot_data['terrestrial_controls'][$fid] = round($total_lvl / $num_cities); } } } } // --- POINT UNIQUE: CALCULATE DYNAMIC STATUS --- foreach ($grid as &$slot_data) { if ($slot_data) { $slot_data['status'] = calculateCelestialStatus($slot_data, $db, $statuses_map); } } } unset($slot_data); $stmt = $db->prepare("SELECT name FROM sectors WHERE id = ?"); $stmt->execute([$sector_id]); $sector_info = $stmt->fetch(); $sector_display_name = $sector_info['name'] ?? "Secteur $sector_id"; $page_title = "$sector_display_name [G$galaxy_id]"; } else { // Galaxy View: Also need dynamic status $stmt = $db->prepare("SELECT * FROM planets WHERE galaxy_id = ? ORDER BY sector_id, slot ASC"); $stmt->execute([$galaxy_id]); $all_planets = $stmt->fetchAll(PDO::FETCH_ASSOC); $planet_ids = array_column($all_planets, 'id'); $orb_controls = []; $terr_controls = []; $city_counts = []; if (!empty($planet_ids)) { $placeholders = implode(',', array_fill(0, count($planet_ids), '?')); // Orbital $o_stmt = $db->prepare("SELECT * FROM planet_faction_control WHERE planet_id IN ($placeholders)"); $o_stmt->execute($planet_ids); while($r = $o_stmt->fetch()) $orb_controls[$r['planet_id']][$r['faction_id']] = $r['control_level']; // Terrestrial (Aggregated per planet) $t_stmt = $db->prepare("SELECT c.planet_id, cfc.faction_id, SUM(cfc.control_level) as total_lvl FROM city_faction_control cfc JOIN cities c ON cfc.city_id = c.id WHERE c.planet_id IN ($placeholders) GROUP BY c.planet_id, cfc.faction_id"); $t_stmt->execute($planet_ids); while($r = $t_stmt->fetch()) { $terr_controls[$r['planet_id']][$r['faction_id']] = $r['total_lvl']; } // City counts to know if it's empty $c_stmt = $db->prepare("SELECT planet_id, COUNT(*) as cnt FROM cities WHERE planet_id IN ($placeholders) GROUP BY planet_id"); $c_stmt->execute($planet_ids); while($r = $c_stmt->fetch()) $city_counts[$r['planet_id']] = $r['cnt']; } $sector_data = []; $active_sectors = []; foreach ($all_planets as $p) { $p['orbital_controls'] = $orb_controls[$p['id']] ?? []; $p['cities'] = isset($city_counts[$p['id']]) ? array_fill(0, $city_counts[$p['id']], []) : []; $p['terrestrial_controls'] = []; if (!empty($p['cities'])) { $num_cities = count($p['cities']); if (isset($terr_controls[$p['id']])) { foreach ($terr_controls[$p['id']] as $fid => $total_lvl) { $p['terrestrial_controls'][$fid] = round($total_lvl / $num_cities); } } } $dynamic_status = calculateCelestialStatus($p, $db, $statuses_map); $sector_data[$p['sector_id']][$p['slot']] = ['status' => $dynamic_status, 'type' => $p['type']]; if (!in_array($p['sector_id'], $active_sectors)) { $active_sectors[] = (int)$p['sector_id']; } } $page_title = "Galaxie $galaxy_id"; } function getStatusColor($status, $statuses_map) { $c = $statuses_map[$status]['color'] ?? 'rgba(255,255,255,0.05)'; return str_replace(';blink', '', $c); } ?>