|
@@ -0,0 +1,729 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Classe Tile
|
|
|
|
|
+ *
|
|
|
|
|
+ * Représente une tuile avec des propriétés arbitraires.
|
|
|
|
|
+ */
|
|
|
|
|
+if (!class_exists('Tile')) {
|
|
|
|
|
+ class Tile
|
|
|
|
|
+ {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var array Les propriétés de la tuile
|
|
|
|
|
+ */
|
|
|
|
|
+ private array $properties;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructeur d'une tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $properties Les propriétés initiales de la tuile
|
|
|
|
|
+ */
|
|
|
|
|
+ public function __construct(array $properties = [])
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->properties = $properties;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit une propriété
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $key La clé de la propriété
|
|
|
|
|
+ * @param mixed $value La valeur de la propriété
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setProperty(string $key, $value): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->properties[$key] = $value;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère une propriété
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $key La clé de la propriété
|
|
|
|
|
+ * @param mixed $default La valeur par défaut si la propriété n'existe pas
|
|
|
|
|
+ * @return mixed La valeur de la propriété
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getProperty(string $key, $default = null)
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->properties[$key] ?? $default;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Vérifie si une propriété existe
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $key La clé de la propriété
|
|
|
|
|
+ * @return bool True si la propriété existe
|
|
|
|
|
+ */
|
|
|
|
|
+ public function hasProperty(string $key): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return array_key_exists($key, $this->properties);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Supprime une propriété
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $key La clé de la propriété
|
|
|
|
|
+ */
|
|
|
|
|
+ public function removeProperty(string $key): void
|
|
|
|
|
+ {
|
|
|
|
|
+ unset($this->properties[$key]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère toutes les propriétés
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Toutes les propriétés
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getAllProperties(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->properties;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit toutes les propriétés
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $properties Les nouvelles propriétés
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setAllProperties(array $properties): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->properties = $properties;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Vérifie si la tuile est vide (aucune propriété)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return bool True si la tuile est vide
|
|
|
|
|
+ */
|
|
|
|
|
+ public function isEmpty(): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return empty($this->properties);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Convertit la tuile en tableau pour la sérialisation
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les données de la tuile
|
|
|
|
|
+ */
|
|
|
|
|
+ public function toArray(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->properties;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Crée une tuile depuis un tableau
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $data Les données de la tuile
|
|
|
|
|
+ * @return Tile La tuile créée
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function fromArray(array $data): Tile
|
|
|
|
|
+ {
|
|
|
|
|
+ return new self($data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Méthodes d'accès rapide pour les propriétés communes
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère le type de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return string|null Le type ou null
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getType(): ?string
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->getProperty('type');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit le type de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $type Le type
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setType(string $type): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->setProperty('type', $type);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère les ressources de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les ressources
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getResources(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->getProperty('resources', []);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit les ressources de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $resources Les ressources
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setResources(array $resources): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->setProperty('resources', $resources);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère la température de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return float|null La température ou null
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getTemperature(): ?float
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->getProperty('temperature');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit la température de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param float $temperature La température
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setTemperature(float $temperature): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->setProperty('temperature', $temperature);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère l'élévation de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return int|null L'élévation ou null
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getElevation(): ?int
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->getProperty('elevation');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit l'élévation de la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $elevation L'élévation
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setElevation(int $elevation): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->setProperty('elevation', $elevation);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Classe Map
|
|
|
|
|
+ *
|
|
|
|
|
+ * Représente une carte composée d'hexagones (damier hexagonal).
|
|
|
|
|
+ * Chaque hexagone est une parcelle pouvant contenir une tuile avec des propriétés arbitraires.
|
|
|
|
|
+ */
|
|
|
|
|
+if (!class_exists('Map')) {
|
|
|
|
|
+ class Map
|
|
|
|
|
+ {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var array Les hexagones de la carte indexés par coordonnées [q][r]
|
|
|
|
|
+ */
|
|
|
|
|
+ private array $hexagons = [];
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var string Le nom de la carte
|
|
|
|
|
+ */
|
|
|
|
|
+ private string $name;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var int La largeur de la carte (nombre d'hexagones en largeur)
|
|
|
|
|
+ */
|
|
|
|
|
+ private int $width;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var int La hauteur de la carte (nombre d'hexagones en hauteur)
|
|
|
|
|
+ */
|
|
|
|
|
+ private int $height;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var string La date de création de la carte
|
|
|
|
|
+ */
|
|
|
|
|
+ private string $createdAt;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var string La date de dernière modification
|
|
|
|
|
+ */
|
|
|
|
|
+ private string $updatedAt;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructeur de la carte
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $name Le nom de la carte
|
|
|
|
|
+ * @param int $width La largeur de la carte (en nombre d'hexagones)
|
|
|
|
|
+ * @param int $height La hauteur de la carte (en nombre d'hexagones)
|
|
|
|
|
+ */
|
|
|
|
|
+ public function __construct(string $name, int $width = 10, int $height = 10)
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->name = $name;
|
|
|
|
|
+ $this->width = $width;
|
|
|
|
|
+ $this->height = $height;
|
|
|
|
|
+ $this->createdAt = date('Y-m-d H:i:s');
|
|
|
|
|
+ $this->updatedAt = date('Y-m-d H:i:s');
|
|
|
|
|
+
|
|
|
|
|
+ // Initialiser la carte avec des hexagones vides
|
|
|
|
|
+ $this->initializeMap();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Initialise la carte avec des hexagones vides
|
|
|
|
|
+ */
|
|
|
|
|
+ private function initializeMap(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ for ($q = 0; $q < $this->width; $q++) {
|
|
|
|
|
+ for ($r = 0; $r < $this->height; $r++) {
|
|
|
|
|
+ $this->hexagons[$q][$r] = new Hexagon($q, $r, new Tile(['type' => 'empty']));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit la tuile d'un hexagone
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q Coordonnée Q de l'hexagone
|
|
|
|
|
+ * @param int $r Coordonnée R de l'hexagone
|
|
|
|
|
+ * @param Tile $tile La tuile à placer
|
|
|
|
|
+ * @return bool True si l'hexagone a été modifié, false sinon
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setTile(int $q, int $r, Tile $tile): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!$this->isValidCoordinate($q, $r)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $this->hexagons[$q][$r]->setTile($tile);
|
|
|
|
|
+ $this->updatedAt = date('Y-m-d H:i:s');
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère la tuile d'un hexagone
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q Coordonnée Q de l'hexagone
|
|
|
|
|
+ * @param int $r Coordonnée R de l'hexagone
|
|
|
|
|
+ * @return Tile|null La tuile ou null si les coordonnées sont invalides
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getTile(int $q, int $r): ?Tile
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!$this->isValidCoordinate($q, $r)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $this->hexagons[$q][$r]->getTile();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère un hexagone
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q Coordonnée Q de l'hexagone
|
|
|
|
|
+ * @param int $r Coordonnée R de l'hexagone
|
|
|
|
|
+ * @return Hexagon|null L'hexagone ou null si les coordonnées sont invalides
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getHexagon(int $q, int $r): ?Hexagon
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!$this->isValidCoordinate($q, $r)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $this->hexagons[$q][$r];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Vérifie si les coordonnées sont valides
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q Coordonnée Q
|
|
|
|
|
+ * @param int $r Coordonnée R
|
|
|
|
|
+ * @return bool True si les coordonnées sont valides
|
|
|
|
|
+ */
|
|
|
|
|
+ public function isValidCoordinate(int $q, int $r): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return isset($this->hexagons[$q][$r]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère tous les hexagones de la carte
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les hexagones indexés par [q][r]
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getAllHexagons(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->hexagons;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère les hexagones d'une ligne spécifique
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q La coordonnée Q de la ligne
|
|
|
|
|
+ * @return array|null Les hexagones de la ligne ou null si la ligne n'existe pas
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getHexagonsRow(int $q): ?array
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->hexagons[$q] ?? null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compte le nombre d'hexagones d'un certain type
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $tileType Le type de tuile à compter
|
|
|
|
|
+ * @return int Le nombre d'hexagones de ce type
|
|
|
|
|
+ */
|
|
|
|
|
+ public function countTiles(string $tileType): int
|
|
|
|
|
+ {
|
|
|
|
|
+ $count = 0;
|
|
|
|
|
+ foreach ($this->hexagons as $row) {
|
|
|
|
|
+ foreach ($row as $hexagon) {
|
|
|
|
|
+ $tile = $hexagon->getTile();
|
|
|
|
|
+ if ($tile && $tile->getType() === $tileType) {
|
|
|
|
|
+ $count++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return $count;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compte le nombre d'hexagones vides
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return int Le nombre d'hexagones vides
|
|
|
|
|
+ */
|
|
|
|
|
+ public function countEmptyTiles(): int
|
|
|
|
|
+ {
|
|
|
|
|
+ $count = 0;
|
|
|
|
|
+ foreach ($this->hexagons as $row) {
|
|
|
|
|
+ foreach ($row as $hexagon) {
|
|
|
|
|
+ if ($hexagon->isEmpty()) {
|
|
|
|
|
+ $count++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return $count;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère les statistiques de la carte
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les statistiques (nombre total d'hexagones, répartition par type)
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getStatistics(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $totalHexagons = $this->width * $this->height;
|
|
|
|
|
+ $tileTypeCounts = [];
|
|
|
|
|
+ $emptyCount = $this->countEmptyTiles();
|
|
|
|
|
+
|
|
|
|
|
+ // Compter les types de tuiles présents
|
|
|
|
|
+ foreach ($this->hexagons as $row) {
|
|
|
|
|
+ foreach ($row as $hexagon) {
|
|
|
|
|
+ $tile = $hexagon->getTile();
|
|
|
|
|
+ if ($tile && !$tile->isEmpty()) {
|
|
|
|
|
+ $type = $tile->getType();
|
|
|
|
|
+ if ($type !== null) {
|
|
|
|
|
+ $tileTypeCounts[$type] = ($tileTypeCounts[$type] ?? 0) + 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'total_hexagons' => $totalHexagons,
|
|
|
|
|
+ 'width' => $this->width,
|
|
|
|
|
+ 'height' => $this->height,
|
|
|
|
|
+ 'tile_type_counts' => $tileTypeCounts,
|
|
|
|
|
+ 'empty_count' => $emptyCount,
|
|
|
|
|
+ 'empty_percentage' => round(($emptyCount / $totalHexagons) * 100, 2),
|
|
|
|
|
+ 'filled_count' => $totalHexagons - $emptyCount,
|
|
|
|
|
+ 'filled_percentage' => round((($totalHexagons - $emptyCount) / $totalHexagons) * 100, 2)
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Convertit la carte en tableau pour la sérialisation JSON
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les données de la carte
|
|
|
|
|
+ */
|
|
|
|
|
+ public function toArray(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $hexagonsData = [];
|
|
|
|
|
+ foreach ($this->hexagons as $q => $row) {
|
|
|
|
|
+ foreach ($row as $r => $hexagon) {
|
|
|
|
|
+ $hexagonsData[] = $hexagon->toArray();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'name' => $this->name,
|
|
|
|
|
+ 'width' => $this->width,
|
|
|
|
|
+ 'height' => $this->height,
|
|
|
|
|
+ 'created_at' => $this->createdAt,
|
|
|
|
|
+ 'updated_at' => $this->updatedAt,
|
|
|
|
|
+ 'hexagons' => $hexagonsData
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Convertit la carte en JSON
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param bool $prettyPrint True pour un JSON formaté
|
|
|
|
|
+ * @return string Le JSON de la carte
|
|
|
|
|
+ */
|
|
|
|
|
+ public function toJson(bool $prettyPrint = false): string
|
|
|
|
|
+ {
|
|
|
|
|
+ return json_encode(
|
|
|
|
|
+ $this->toArray(),
|
|
|
|
|
+ $prettyPrint ? JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE : 0
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Sauvegarde la carte dans un fichier JSON
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $filePath Le chemin du fichier
|
|
|
|
|
+ * @return bool True si la sauvegarde a réussi
|
|
|
|
|
+ */
|
|
|
|
|
+ public function saveToFile(string $filePath): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ try {
|
|
|
|
|
+ $json = $this->toJson(true);
|
|
|
|
|
+ $result = file_put_contents($filePath, $json);
|
|
|
|
|
+ return $result !== false;
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ AppDebugger::log('Erreur lors de la sauvegarde de la carte: ' . $e->getMessage(), 'ERROR');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Charge une carte depuis un tableau
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $data Les données de la carte
|
|
|
|
|
+ * @return Map|null La carte chargée ou null en cas d'erreur
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function fromArray(array $data): ?Map
|
|
|
|
|
+ {
|
|
|
|
|
+ try {
|
|
|
|
|
+ $map = new self($data['name'], $data['width'], $data['height']);
|
|
|
|
|
+ $map->createdAt = $data['created_at'] ?? date('Y-m-d H:i:s');
|
|
|
|
|
+ $map->updatedAt = $data['updated_at'] ?? date('Y-m-d H:i:s');
|
|
|
|
|
+
|
|
|
|
|
+ // Charger les hexagones
|
|
|
|
|
+ foreach ($data['hexagons'] as $hexagonData) {
|
|
|
|
|
+ $q = $hexagonData['q'];
|
|
|
|
|
+ $r = $hexagonData['r'];
|
|
|
|
|
+ if ($map->isValidCoordinate($q, $r)) {
|
|
|
|
|
+ $map->hexagons[$q][$r] = Hexagon::fromArray($hexagonData);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $map;
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ AppDebugger::log('Erreur lors du chargement de la carte depuis un tableau: ' . $e->getMessage(), 'ERROR');
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Charge une carte depuis un fichier JSON
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $filePath Le chemin du fichier
|
|
|
|
|
+ * @return Map|null La carte chargée ou null en cas d'erreur
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function fromFile(string $filePath): ?Map
|
|
|
|
|
+ {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (!file_exists($filePath)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $json = file_get_contents($filePath);
|
|
|
|
|
+ $data = json_decode($json, true);
|
|
|
|
|
+
|
|
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
|
|
+ AppDebugger::log('Erreur JSON lors du chargement du fichier: ' . json_last_error_msg(), 'ERROR');
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return self::fromArray($data);
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ AppDebugger::log('Erreur lors du chargement de la carte depuis un fichier: ' . $e->getMessage(), 'ERROR');
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Getters
|
|
|
|
|
+ public function getName(): string { return $this->name; }
|
|
|
|
|
+ public function getWidth(): int { return $this->width; }
|
|
|
|
|
+ public function getHeight(): int { return $this->height; }
|
|
|
|
|
+ public function getCreatedAt(): string { return $this->createdAt; }
|
|
|
|
|
+ public function getUpdatedAt(): string { return $this->updatedAt; }
|
|
|
|
|
+
|
|
|
|
|
+ // Setters
|
|
|
|
|
+ public function setName(string $name): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->name = $name;
|
|
|
|
|
+ $this->updatedAt = date('Y-m-d H:i:s');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Classe Hexagon
|
|
|
|
|
+ *
|
|
|
|
|
+ * Représente un hexagone individuel dans la carte.
|
|
|
|
|
+ */
|
|
|
|
|
+if (!class_exists('Hexagon')) {
|
|
|
|
|
+ class Hexagon
|
|
|
|
|
+ {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var int Coordonnée Q (axe horizontal)
|
|
|
|
|
+ */
|
|
|
|
|
+ private int $q;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var int Coordonnée R (axe diagonal)
|
|
|
|
|
+ */
|
|
|
|
|
+ private int $r;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @var Tile|null La tuile de l'hexagone
|
|
|
|
|
+ */
|
|
|
|
|
+ private ?Tile $tile;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructeur d'un hexagone
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $q Coordonnée Q
|
|
|
|
|
+ * @param int $r Coordonnée R
|
|
|
|
|
+ * @param Tile|null $tile La tuile initiale (null pour vide)
|
|
|
|
|
+ */
|
|
|
|
|
+ public function __construct(int $q, int $r, ?Tile $tile = null)
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->q = $q;
|
|
|
|
|
+ $this->r = $r;
|
|
|
|
|
+ $this->tile = $tile;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param Tile|null $tile La nouvelle tuile (null pour vider)
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setTile(?Tile $tile): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->tile = $tile;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère la tuile
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return Tile|null La tuile ou null si vide
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getTile(): ?Tile
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->tile;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Vérifie si l'hexagone est vide
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return bool True si l'hexagone est vide
|
|
|
|
|
+ */
|
|
|
|
|
+ public function isEmpty(): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->tile === null || $this->tile->isEmpty() || $this->tile->getType() === 'empty';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère le type de tuile (méthode de compatibilité)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return string|null Le type de tuile ou null
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getTileType(): ?string
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->tile ? $this->tile->getType() : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Définit le type de tuile (méthode de compatibilité)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $tileType Le type de tuile
|
|
|
|
|
+ */
|
|
|
|
|
+ public function setTileType(string $tileType): void
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($this->tile === null) {
|
|
|
|
|
+ $this->tile = new Tile();
|
|
|
|
|
+ }
|
|
|
|
|
+ $this->tile->setType($tileType);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Calcule la coordonnée S (pour les coordonnées cubiques)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return int La coordonnée S
|
|
|
|
|
+ */
|
|
|
|
|
+ public function getS(): int
|
|
|
|
|
+ {
|
|
|
|
|
+ return -$this->q - $this->r;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Calcule la distance à un autre hexagone
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param Hexagon $other L'autre hexagone
|
|
|
|
|
+ * @return int La distance
|
|
|
|
|
+ */
|
|
|
|
|
+ public function distanceTo(Hexagon $other): int
|
|
|
|
|
+ {
|
|
|
|
|
+ return (abs($this->q - $other->q) + abs($this->r - $other->r) + abs($this->getS() - $other->getS())) / 2;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Récupère les hexagones voisins
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les directions vers les voisins [q, r]
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function getNeighbors(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return [
|
|
|
|
|
+ [1, 0], // Est
|
|
|
|
|
+ [1, -1], // Nord-Est
|
|
|
|
|
+ [0, -1], // Nord-Ouest
|
|
|
|
|
+ [-1, 0], // Ouest
|
|
|
|
|
+ [-1, 1], // Sud-Ouest
|
|
|
|
|
+ [0, 1] // Sud-Est
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Convertit l'hexagone en tableau pour la sérialisation
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return array Les données de l'hexagone
|
|
|
|
|
+ */
|
|
|
|
|
+ public function toArray(): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'q' => $this->q,
|
|
|
|
|
+ 'r' => $this->r,
|
|
|
|
|
+ 'tile' => $this->tile ? $this->tile->toArray() : null
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Crée un hexagone depuis un tableau
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $data Les données de l'hexagone
|
|
|
|
|
+ * @return Hexagon L'hexagone créé
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function fromArray(array $data): Hexagon
|
|
|
|
|
+ {
|
|
|
|
|
+ $tile = null;
|
|
|
|
|
+ if (isset($data['tile']) && $data['tile'] !== null) {
|
|
|
|
|
+ $tile = Tile::fromArray($data['tile']);
|
|
|
|
|
+ } elseif (isset($data['tile_type'])) {
|
|
|
|
|
+ // Compatibilité avec l'ancien format
|
|
|
|
|
+ $tile = new Tile(['type' => $data['tile_type']]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new self($data['q'], $data['r'], $tile);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Getters
|
|
|
|
|
+ public function getQ(): int { return $this->q; }
|
|
|
|
|
+ public function getR(): int { return $this->r; }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|