<?php
//Gestion des dépendances, on importe les classes nécessaires à la classe en cours
include_once("game/Class/class.exceptionHB.php");
include_once("game/Class/class.donnee.php");

/***************************************************************************
 *                            class.file.php
 *                           ----------------
 *   begin                : Samedi 11 octobre 2008
 *   update               : Vendredi 1e mai 2009
 *   email                : nemunaire@gmail.com
 *
 *
 ***************************************************************************/
class File
{
    private $file = array();
    private $type;
    private $time;


    public function __construct($type)
    {
        $this->type = $type;
        $this->time = time();
    }

    public function reajusteVacances($timeVac)
    {
        if (isset($this->file[0])) {
            $this->time += time() - $timeVac;
        }

        return serialize($this);
    }

    public function refreshTime()
    {
        if (count($this->file) < 1) {
            $this->time = time();
        }
    }

    public function DEBUG_setTime($time)
    {
        $this->time = $time;
    }

    public function printFile(SURFACE $planete)
    {
        if (count($this->file) == 0) {
            return false;
        } else {
            $out = array();
            if ($this->type == "batiments") {
                $batiments = $planete->batiments;
                foreach ($this->file as $key => $element) {
                    if ($element[1]) { //Cas d'une démolition
                        $temps = Donnee::tempsBatiments($element[0], $batiments[$element[0]]--, $planete) * 0.6;
                        if (count($out) == 0) {
                            $temps -= time() - $this->time;
                        }
                        $out[$key] = array($element[0], $element[1], ceil($temps));
                    } else { //Cas d'une construction
                        $temps = Donnee::tempsBatiments($element[0], ++$batiments[$element[0]], $planete);
                        if (count($out) == 0) {
                            $temps -= time() - $this->time;
                        }
                        $out[$key] = array($element[0], $element[1], ceil($temps));
                    }
                }
            } elseif ($this->type == "alli_batiments") {
                $batiments = $planete->batiments;
                foreach ($this->file as $key => $element) {
                    if ($element[1]) { //Cas d'une démolition
                        $temps = Donnee::tempsAlli_Batiments($element[0], $batiments[$element[0]]--, $planete) * 0.6;
                        if (count($out) == 0) {
                            $temps -= time() - $this->time;
                        }
                        $out[$key] = array($element[0], $element[1], ceil($temps));
                    } else { //Cas d'une construction
                        $temps = Donnee::tempsAlli_Batiments($element[0], ++$batiments[$element[0]], $planete);
                        if (count($out) == 0) {
                            $temps -= time() - $this->time;
                        }
                        $out[$key] = array($element[0], $element[1], ceil($temps));
                    }
                }
            } elseif ($this->type == "technologies") {
                foreach ($this->file as $key => $element) {
                    $temps = Donnee::tempsTechnologie($element[0], $element[1], $planete);
                    if (count($out) == 0) {
                        $temps -= time() - $this->time;
                    }
                    $out[$key] = array($element[0], $element[1], ceil($temps));
                }
            } elseif ($this->type == "casernes") {
                foreach ($this->file as $key => $element) {
                    if ($element[2]) {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsCaserne($element[0], $planete) * 0.6;
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins));
                    } else {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsCaserne($element[0], $planete);
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins));
                    }
                }
            } elseif ($this->type == "terrestres") {
                foreach ($this->file as $key => $element) {
                    $type = Donnee::typeTerrestre($element[0]);
                    if ($element[2]) {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsTerrestre($element[0], $planete) * 0.6;
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins), $type);
                    } else {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsTerrestre($element[0], $planete);
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins), $type);
                    }
                }
            } elseif ($this->type == "vaisseaux") {
                foreach ($this->file as $key => $element) {
                    if ($element[2]) {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsVaisseaux($element[0], $planete) * 0.6;
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins));
                    } else {
                        if (count($out) == 0) {
                            $temps_moins = time() - $this->time;
                        } else {
                            $temps_moins = 0;
                        }

                        $temps = Donnee::tempsVaisseaux($element[0], $planete);
                        $out[$key] = array($element[0], $element[1], $element[2], ceil($temps * $element[1] - $temps_moins), ceil($temps - $temps_moins));
                    }
                }
            }

            return $out;
        }
    }

    public function batiment_objectInFile($objet)
    {
        if (in_array(array($objet, true), $this->file)) {
            return array_search(array($objet, true), $this->file);
        } elseif (in_array(array($objet, false), $this->file)) {
            return array_search(array($objet, false), $this->file);
        } else {
            return false;
        }
    }

    public function technologie_objectInFile($branche, $idTechnologie)
    {
        if (in_array(array($branche, $idTechnologie), $this->file)) {
            return array_search(array($branche, $idTechnologie), $this->file);
        } else {
            return false;
        }
    }

    public function hasObject()
    {
        if (empty($this->file[0])) {
            return false;
        } else {
            return true;
        }
    }

    public function objectInFile($objet)
    {
        if ($this->file) {
            foreach ($this->file as $key => $element) {
                if ($element[0] == $objet) {
                    return $key;
                }
            }
        }
        return false;
    }

    public function batiment_addObjet($objet, surface $planete)
    {
        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(1, 1);
        }

        //Validation des conditions de construction
        if (is_a($planete, "Asteroide")) {
            if (!Donnee::neededAlli_Batiments($objet, $planete)) {
                throw new ExceptionHB(1, 2);
            }
        } else {
            if (!Donnee::neededBatiments($objet, $planete)) {
                throw new ExceptionHB(1, 2);
            }
        }


        //On vérifie qu'il reste suffisamment de place sur la planète
        if (!is_a($planete, "Asteroide") && $planete->casesRest < count($this->file)) {
            foreach ($this->file as $argh) {
                throw new ExceptionHB(1, 0);
            }
        }


        //On vérifie que la batiment ne soit pas en cours de démolition
        if (in_array(array($objet, true), $this->file)) {
            throw new ExceptionHB(1, 3);
        }

        //Calcul du prochain niveau du batiment
        if (in_array(array($objet, false), $this->file)) { //Si le batiment est déjà en file d'attente, on recherche le prochain niveau à construire
            $nbOccurence = 1;
            foreach ($this->file as $obj) {
                if ($obj[0] == $objet) {
                    $nbOccurence++;
                }
            }
            $nextLvl = $planete->batiments[$objet] + $nbOccurence;
        } else {
            $nextLvl = $planete->batiments[$objet] + 1;
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        //On vérifie qu'il y ait assez de ressources sur la planète
        if ((!is_a($planete, "Asteroide") && $planete->checkAndRetireRessources(Donnee::metalBatiments($objet, $nextLvl, $planete), Donnee::cristalBatiments($objet, $nextLvl, $planete), Donnee::hydrogeneBatiments($objet, $nextLvl, $planete), 0)) || (is_a($planete, "Asteroide") && $planete->checkAndRetireRessources(0, 0, 0, Donnee::creditsAlli_Batiments($objet, $nextLvl, $planete)))) {
            $this->file[] = array($objet, false);
            $planete->addModif("file_bat");
            return true;
        } else {
            throw new ExceptionHB(1, 4);
        }
    }

    public function batiment_addDemolition($objet, surface $planete)
    {
        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(1, 1);
        }

        //On vérifie que le niveau actuel soit non nul
        if ($planete->batiments[$objet] <= 0) {
            throw new ExceptionHB(1, 6);
        }

        //On vérifie que la batiment ne soit pas en cours de construction ou démolition
        if (in_array(array($objet, false), $this->file) || in_array(array($objet, true), $this->file)) {
            throw new ExceptionHB(1, 7);
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        $this->file[] = array($objet, true);

        $planete->addModif("file_bat");

        return true;
    }

    public function batiment_delObjet($id, surface $planete)
    {
        //Vérification de l'existance de l'objet en file d'attente
        if (empty($this->file[$id])) {
            throw new ExceptionHB(1, 5);
        }

        //On récupère le type de batiment
        $objet = $this->file[$id][0];

        //On gère les démolition
        if ($this->file[$id][1]) {
            $lvlAnnule = $planete->batiments[$objet];
        } else {
            //On recherche d'autres instances du batiment
            $occurence = 0;
            foreach ($this->file as $key => $obj) {
                if ($obj[0] == $objet) {
                    $occurence++;
                    if ($key > $id) {
                        $id = $key;
                    }
                }
            }
            $lvlAnnule = $planete->batiments[$objet] + $occurence;
        }

        //On met à jour le temps si on vient d'annuler le premier batiment en lice
        if ($id == 0) {
            $this->time = time();
        }

        $planete->addModif("file_bat");

        if (is_a($planete, "Asteroide") && !$this->file[$id][1]) {
            $planete->addRessources(0, 0, 0, Donnee::creditsAlli_Batiments($objet, $lvlAnnule, $planete));
        }
        //On redonne 60% des ressources au joueur si c'est la première construction dans la file d'attente
        elseif ($id == 0 && !$this->file[$id][1]) {
            $planete->addRessources(Donnee::metalBatiments($objet, $lvlAnnule, $planete)*0.6, Donnee::cristalBatiments($objet, $lvlAnnule, $planete)*0.6, Donnee::hydrogeneBatiments(abs($objet), $lvlAnnule, $planete)*0.6);
        } elseif (!$this->file[$id][1]) {
            $planete->addRessources(Donnee::metalBatiments($objet, $lvlAnnule, $planete), Donnee::cristalBatiments($objet, $lvlAnnule, $planete), Donnee::hydrogeneBatiments($objet, $lvlAnnule, $planete));
        }

        //Effacement de la file
        unset($this->file[$id]);

        return true;
    }

    public function batiment_ready(SURFACE $planete)
    {
        //On vérifie qu'il existe un bâtiment en construction
        if (count($this->file) < 1) {
            return false;
        }

        //On parcourt la liste à la recherche des batiments terminés dans l'ordre
        foreach ($this->file as $key => $element) {
            //Calcul du temps écoulé depuis la dernière construction
            $tempsEcoule = time() - $this->time;

            //On séparer les démolitions des constructions
            if ($element[1]) { //Cas de la démolition
                //Récupération de l'ID du batiment et son niveau actuel
                $lvl = $planete->batiments[$element[0]];

                //Récupération de 60% du temps nécessaire
                if (is_a($planete, "Asteroide")) {
                    $temps = Donnee::tempsAlli_Batiments($element[0], $lvl, $planete) * 0.6;
                } else {
                    $temps = Donnee::tempsBatiments($element[0], $lvl, $planete) * 0.6;
                }

                //Si le temps écoulé est suffisant
                if ($tempsEcoule >= $temps) {
                    //On redonne 70% des ressources du batiment au joueur
                    if (is_a($planete, "Asteroide")) {
                        $planete->addRessources(Donnee::metalAlli_Batiments($element[0], $lvl, $planete)*0.7, Donnee::cristalAlli_Batiments($element[0], $lvl, $planete)*0.7, Donnee::hydrogeneAlli_Batiments($element[0], $lvl, $planete)*0.7, Donnee::creditsAlli_Batiments($element[0], $lvl, $planete)*0.7);
                    } else {
                        $planete->addRessources(Donnee::metalBatiments($element[0], $lvl, $planete)*0.7, Donnee::cristalBatiments($element[0], $lvl, $planete)*0.7, Donnee::hydrogeneBatiments($element[0], $lvl, $planete)*0.7);
                    }

                    //On retire un niveau au batiment
                    $planete->batiments[$element[0]]--;

                    //On efface l'entrée de la file et on met à jour le temps de la file
                    unset($this->file[$key]);
                    $this->time += $temps;

                    //On demande la mise à jour des champs modifiés
                    $planete->addModif("batiments");
                    $planete->addModif("file_bat");
                }
                //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
                else {
                    return false;
                }
            } else { //Cas de la construction
                //Récupération du niveau du batiment
                $lvl = $planete->batiments[$element[0]] + 1;

                //Récupération du temps nécessaire
                if (is_a($planete, "Asteroide")) {
                    $temps = Donnee::tempsAlli_Batiments($element[0], $lvl, $planete);
                } else {
                    $temps = Donnee::tempsBatiments($element[0], $lvl, $planete);
                }

                //Si le temps écoulé est suffisant
                if ($tempsEcoule >= $temps) {
                    //On ajoute un niveau au batiment
                    $planete->batiments[$element[0]]++;

                    //On efface l'entrée de la file et on met à jour le temps de la file
                    unset($this->file[$key]);
                    $this->time += $temps;

                    //On demande la mise à jour des champs modifiés
                    $planete->addModif("batiments");
                    $planete->addModif("file_bat");
                }
                //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
                else {
                    return false;
                }
            }
        }
    }

    public function technologie_addObjet($branche, $idTechnologie, Planete $planete)
    {
        //On vérifie que cette technologie ne soit pas déjà en file d'attente
        if (in_array(array($branche, $idTechnologie), $this->file)) {
            throw new ExceptionHB(2, 0);
        }

        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(2, 1);
        }

        //Validation des conditions de recherche
        if (!Donnee::neededTechnologie($branche, $idTechnologie, $planete)) {
            throw new ExceptionHB(2, 2);
        }

        //On vérifie que l'on n'ait pas déjà cette technologie
        $bit = pow(2, $idTechnologie);
        if (($planete->technologies[$branche]& $bit) == $bit) {
            throw new ExceptionHB(2, 3);
        }
        unset($bit);

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        //On vérifie qu'il y ait assez de ressources sur la planète
        if ($planete->checkAndRetireRessources(0, 0, 0, Donnee::creditsTechnologie($branche, $idTechnologie, $planete))) {
            $this->file[] = array($branche, $idTechnologie);
            $planete->addModif("file_tech");
            return true;
        } else {
            throw new ExceptionHB(2, 4);
        }
    }

    public function technologie_delObjet($id, Planete $planete)
    {
        //Vérification de l'existance de l'objet en file d'attente
        if (empty($this->file[$id])) {
            throw new ExceptionHB(2, 5);
        }

        //On récupère les informations de la technologie
        $branche = $this->file[$id][0];
        $idTechnologie = $this->file[$id][1];

        //On met à jour le temps si on vient d'annuler la première technologie en lice
        if ($id == 0) {
            $this->time = time();
        }

        $planete->addModif("file_tech");

        $planete->addCredits(Donnee::creditsTechnologie($branche, $idTechnologie, $planete));

        //Effacement de la file
        unset($this->file[$id]);

        return true;
    }

    public function technologie_ready(Planete $planete)
    {
        //On vérifie qu'il existe une technologie dans la file
        if (count($this->file) < 1) {
            return false;
        }

        //On parcourt la liste à la recherche des technologies terminées dans l'ordre
        foreach ($this->file as $key => $element) {
            //Calcul du temps écoulé depuis la dernière construction
            $tempsEcoule = time() - $this->time;

            //Récupération du temps nécessaire
            $temps = Donnee::tempsTechnologie($element[0], $element[1], $planete);

            //Si le temps écoulé est suffisant
            if ($tempsEcoule >= $temps) {
                //On ajoute le bit correspondant à la technologie
                $planete->technologies[$element[0]] = $planete->technologies[$element[0]] | pow(2, $element[1]); //ATTENTION : Possibilité de faille : le bit généré n'est pas extrait des données, mais est calculer. Il peut donc être différent et être cause de problèmes !

                //On efface l'entrée de la file et on met à jour le temps de la file
                unset($this->file[$key]);
                $this->time += $temps;

                //On demande la mise à jour des champs modifiés
                $planete->addModifUser("technologies");
                $planete->addModif("file_tech");
            }
            //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
            else {
                return false;
            }
        }
    }


    public function caserne_addObjet($objet, $nombre, Planete $planete)
    {
        //Vérification du nombre passé en entrée
        if (!is_numeric($nombre) || $nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //Validation des conditions de construction
        if (!Donnee::neededCaserne($objet, $planete)) {
            throw new ExceptionHB(3, 2);
        }

        //On vérifie que l'unité ne soit pas en cours de démolition et récupération du dernier en construction
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if ($element[2]) {
                    throw new ExceptionHB(3, 3);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file) && !isset($sauvLastKey)) {
            throw new ExceptionHB(3, 1);
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        //On tronque au maximum d'unités constructible sur la planète
        if (($metal = Donnee::metalCaserne($objet, $planete)) > 0) {
            $metal = $planete->metal/$metal;
        } else {
            $metal = $nombre;
        }
        if (($cristal = Donnee::cristalCaserne($objet, $planete)) > 0) {
            $cristal = $planete->cristal/$cristal;
        } else {
            $cristal = $nombre;
        }
        if (($hydrogene = Donnee::hydrogeneCaserne($objet, $planete)) > 0) {
            $hydrogene = $planete->hydrogene/$hydrogene;
        } else {
            $hydrogene = $nombre;
        }

        $nombre = floor(min($nombre, $metal, $cristal, $hydrogene));

        //On vérifie qu'il y ait assez de ressources sur la planète
        if ($planete->checkAndRetireRessources(Donnee::metalCaserne($objet, $planete, $nombre), Donnee::cristalCaserne($objet, $planete, $nombre), Donnee::hydrogeneCaserne($objet, $planete, $nombre), 0)) {
            //Si il existe déjà l'objet en file d'attente, on l'ajoute
            if (isset($sauvLastKey)) {
                $this->file[$sauvLastKey][1] += $nombre;
            } else {
                $this->file[] = array($objet, $nombre, false);
            }

            $planete->addModif("file_cas");
            return true;
        } else {
            throw new ExceptionHB(3, 4);
        }
    }

    public function caserne_addDemolition($objet, $nombre, Planete $planete)
    {
        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(3, 1);
        }

        //Vérification du nombre passé en entrée
        if ($nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //On vérifie que le nombre d'unité actuel soit non nul
        if ($planete->casernes[$objet] < $nombre) {
            throw new ExceptionHB(3, 6);
        }

        //On vérifie que l'unité ne soit pas en cours de construction ou démolition
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if (!$element[2]) {
                    throw new ExceptionHB(3, 7);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        if (isset($sauvLastKey)) {
            $this->file[$sauvLastKey][1] += $nombre;
        } else {
            $this->file[] = array($objet, $nombre, true);
        }

        $planete->addModif("file_cas");

        return true;
    }

    public function caserne_delObjet($id, $nombre, Planete $planete)
    {
        //Vérification de l'existance de l'objet en file d'attente
        if (empty($this->file[$id])) {
            throw new ExceptionHB(3, 5);
        }

        //Si $nombre est supérieur au nombre présent dans la file, on le réduit
        if ($this->file[$id][1] < $nombre) {
            $nombre = $this->file[$id][1];
        }

        //On récupère les informations disponibles
        $objet = $this->file[$id][0];
        $nombreMax = $this->file[$id][1];

        //On met à jour le temps si on vient d'annuler le premier groupe d'unités en lice
        if ($id == 0 && $nombreMax == $nombre) {
            $this->time = time();
        }

        $planete->addModif("file_cas");

        if (!$this->file[$id][2]) {
            $planete->addRessources(Donnee::metalCaserne($objet, $planete, $nombre), Donnee::cristalCaserne($objet, $planete, $nombre), Donnee::hydrogeneCaserne($objet, $planete, $nombre));
        }

        //Effacement de la file
        if ($nombre >= $nombreMax) {
            unset($this->file[$id]);
        } else {
            $this->file[$id][1] -= $nombre;
        }
        $planete->addModif("file_cas");

        return true;
    }

    public function caserne_ready(Planete $planete)
    {
        //On vérifie qu'il existe une unité en construction
        if (count($this->file) < 1) {
            return false;
        }

        //On parcourt la liste à la recherche des unités terminées dans l'ordre
        foreach ($this->file as $key => $element) {
            //Calcul du temps écoulé depuis la dernière construction
            $tempsEcoule = time() - $this->time;

            //On séparer les démolitions des constructions
            if ($element[2]) { //Cas de la démolition
                //On vérifie qu'il reste des unités du type sur la planète
                if ($planete->casernes[$element[0]] <= 0) {
                    unset($this->file[$key]);
                    $planete->addModif("file_cas");
                } else {
                    //Récupération de 60% du temps nécessaire
                    $temps = Donnee::tempsCaserne($element[0], $planete) * 0.6;

                    //Calcul du nombre d'unités maximum
                    $nbUnitee = min(floor($tempsEcoule/$temps), $element[1], $planete->casernes[$element[0]]);

                    //Si le temps écoulé est suffisant
                    if ($nbUnitee > 0) {
                        //On redonne 70% des ressources de l'unité au joueur
                        $planete->addRessources(Donnee::metalCaserne($element[0], $planete, $nbUnitee)*0.7, Donnee::cristalCaserne($element[0], $planete, $nbUnitee)*0.7, Donnee::hydrogeneCaserne($element[0], $planete, $nbUnitee)*0.7);

                        //On retire les unités
                        $planete->casernes[$element[0]] -= $nbUnitee;

                        //On efface l'entrée de la file et on met à jour le temps de la file
                        if ($nbUnitee >= $element[1]) {
                            unset($this->file[$key]);
                        } else {
                            $this->file[$key][1] -= $nbUnitee;
                        }
                        $this->time += $temps*$nbUnitee;

                        //On demande la mise à jour des champs modifiés
                        $planete->addModif("casernes");
                        $planete->addModif("file_cas");

                        if ($nbUnitee < $element[1]) {
                            return false;
                        }
                    }
                    //Si le temps écoulé n'est pas suffisant pour cette unité, on annule toutes les suivantes
                    else {
                        return false;
                    }
                }
            } else { //Cas de la construction
                //Récupération du temps nécessaire
                $temps = Donnee::tempsCaserne($element[0], $planete);

                //Calcul du nombre d'unités maximum
                $nbUnitee = min(floor($tempsEcoule/$temps), $element[1]);

                //Si le temps écoulé est suffisant
                if ($nbUnitee > 0) {
                    //On ajoute le nombre d'unités
                    $planete->casernes[$element[0]] += $nbUnitee;

                    //On efface l'entrée de la file et on met à jour le temps de la file
                    if ($nbUnitee >= $element[1]) {
                        unset($this->file[$key]);
                    } else {
                        $this->file[$key][1] -= $nbUnitee;
                    }
                    $this->time += $temps * $nbUnitee;

                    //On demande la mise à jour des champs modifiés
                    $planete->addModif("casernes");
                    $planete->addModif("file_cas");

                    if ($nbUnitee < $element[1]) {
                        return false;
                    }
                }
                //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
                else {
                    return false;
                }
            }
        }
    }


    public function terrestre_addObjet($objet, $nombre, Planete $planete)
    {
        //Vérification du nombre passé en entrée
        if (!is_numeric($nombre) || $nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //Validation des conditions de construction
        if (!Donnee::neededTerrestre($objet, $planete)) {
            throw new ExceptionHB(3, 2);
        }

        //On vérifie que l'unité ne soit pas en cours de démolition et récupération du dernier en construction
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if ($element[2]) {
                    throw new ExceptionHB(3, 3);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file) && !isset($sauvLastKey)) {
            throw new ExceptionHB(3, 1);
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        //On tronque au maximum d'unités constructible sur la planète
        if (($metal = Donnee::metalTerrestre($objet, $planete)) > 0) {
            $metal = $planete->metal/$metal;
        } else {
            $metal = $nombre;
        }
        if (($cristal = Donnee::cristalTerrestre($objet, $planete)) > 0) {
            $cristal = $planete->cristal/$cristal;
        } else {
            $cristal = $nombre;
        }
        if (($hydrogene = Donnee::hydrogeneTerrestre($objet, $planete)) > 0) {
            $hydrogene = $planete->hydrogene/$hydrogene;
        } else {
            $hydrogene = $nombre;
        }

        $nombre = floor(min($nombre, $metal, $cristal, $hydrogene));

        //On vérifie qu'il y ait assez de ressources sur la planète
        if ($planete->checkAndRetireRessources(Donnee::metalTerrestre($objet, $planete, $nombre), Donnee::cristalTerrestre($objet, $planete, $nombre), Donnee::hydrogeneTerrestre($objet, $planete, $nombre), 0)) {
            //Si il existe déjà l'objet en file d'attente, on l'ajoute
            if (isset($sauvLastKey)) {
                $this->file[$sauvLastKey][1] += $nombre;
            } else {
                $this->file[] = array($objet, $nombre, false);
            }

            $planete->addModif("file_ter");
            return true;
        } else {
            throw new ExceptionHB(3, 4);
        }
    }

    public function terrestre_addDemolition($objet, $nombre, Planete $planete)
    {
        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(3, 1);
        }

        //Vérification du nombre passé en entrée
        if ($nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //On vérifie que le nombre d'unité actuel soit non nul
        if ($planete->terrestres[$objet] < $nombre) {
            throw new ExceptionHB(3, 6);
        }

        //On vérifie que l'unité ne soit pas en cours de construction ou démolition
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if (!$element[2]) {
                    throw new ExceptionHB(3, 7);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        if (isset($sauvLastKey)) {
            $this->file[$sauvLastKey][1] += $nombre;
        } else {
            $this->file[] = array($objet, $nombre, true);
        }

        $planete->addModif("file_ter");

        return true;
    }

    public function terrestre_delObjet($id, $nombre, Planete $planete)
    {
        //Vérification de l'existance de l'objet en file d'attente
        if (empty($this->file[$id])) {
            throw new ExceptionHB(3, 5);
        }

        //Si $nombre est supérieur au nombre présent dans la file, on le réduit
        if ($this->file[$id][1] < $nombre) {
            $nombre = $this->file[$id][1];
        }

        //On récupère les informations disponibles
        $objet = $this->file[$id][0];
        $nombreMax = $this->file[$id][1];

        //On met à jour le temps si on vient d'annuler le premier groupe d'unités en lice
        if ($id == 0 && $nombreMax == $nombre) {
            $this->time = time();
        }

        $planete->addModif("file_ter");

        if (!$this->file[$id][2]) {
            $planete->addRessources(Donnee::metalTerrestre($objet, $planete, $nombre), Donnee::cristalTerrestre($objet, $planete, $nombre), Donnee::hydrogeneTerrestre($objet, $planete, $nombre));
        }

        //Effacement de la file
        if ($nombre >= $nombreMax) {
            unset($this->file[$id]);
        } else {
            $this->file[$id][1] -= $nombre;
        }
        $planete->addModif("file_ter");

        return true;
    }

    public function terrestre_ready(Planete $planete)
    {
        //On vérifie qu'il existe une unité en construction
        if (count($this->file) < 1) {
            return false;
        }

        //On parcourt la liste à la recherche des unités terminées dans l'ordre
        foreach ($this->file as $key => $element) {
            //Calcul du temps écoulé depuis la dernière construction
            $tempsEcoule = time() - $this->time;

            //On séparer les démolitions des constructions
            if ($element[2]) { //Cas de la démolition
                //On vérifie qu'il reste des unités du type sur la planète
                if ($planete->terrestres[$element[0]] <= 0) {
                    unset($this->file[$key]);
                    $planete->addModif("file_ter");
                } else {
                    //Récupération de 60% du temps nécessaire
                    $temps = Donnee::tempsTerrestre($element[0], $planete) * 0.6;

                    //Calcul du nombre d'unités maximum
                    $nbUnitee = min(floor($tempsEcoule/$temps), $element[1], $planete->terrestres[$element[0]]);

                    //Si le temps écoulé est suffisant
                    if ($nbUnitee > 0) {
                        //On redonne 70% des ressources de l'unité au joueur
                        $planete->addRessources(Donnee::metalTerrestre($element[0], $planete, $nbUnitee)*0.7, Donnee::cristalTerrestre($element[0], $planete, $nbUnitee)*0.7, Donnee::hydrogeneTerrestre($element[0], $planete, $nbUnitee)*0.7);

                        //On retire les unités
                        $planete->terrestres[$element[0]] -= $nbUnitee;

                        //On efface l'entrée de la file et on met à jour le temps de la file
                        if ($nbUnitee >= $element[1]) {
                            unset($this->file[$key]);
                        } else {
                            $this->file[$key][1] -= $nbUnitee;
                        }
                        $this->time += $temps*$nbUnitee;

                        //On demande la mise à jour des champs modifiés
                        $planete->addModif("terrestres");
                        $planete->addModif("file_ter");

                        if ($nbUnitee < $element[1]) {
                            return false;
                        }
                    }
                    //Si le temps écoulé n'est pas suffisant pour cette unité, on annule toutes les suivantes
                    else {
                        return false;
                    }
                }
            } else { //Cas de la construction
                //Récupération du temps nécessaire
                $temps = Donnee::tempsTerrestre($element[0], $planete);

                //Calcul du nombre d'unités maximum
                $nbUnitee = min(floor($tempsEcoule/$temps), $element[1]);

                //Si le temps écoulé est suffisant
                if ($nbUnitee > 0) {
                    //On ajoute le nombre d'unités
                    $planete->terrestres[$element[0]] += $nbUnitee;

                    //On efface l'entrée de la file et on met à jour le temps de la file
                    if ($nbUnitee >= $element[1]) {
                        unset($this->file[$key]);
                    } else {
                        $this->file[$key][1] -= $nbUnitee;
                    }
                    $this->time += $temps * $nbUnitee;

                    //On demande la mise à jour des champs modifiés
                    $planete->addModif("terrestres");
                    $planete->addModif("file_ter");

                    if ($nbUnitee < $element[1]) {
                        return false;
                    }
                }
                //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
                else {
                    return false;
                }
            }
        }
    }


    public function vaisseaux_addObjet($objet, $nombre, surface $planete)
    {
        //Vérification du nombre passé en entrée
        if (!is_numeric($nombre) || $nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //Validation des conditions de construction
        if (!Donnee::neededVaisseaux($objet, $planete)) {
            throw new ExceptionHB(3, 2);
        }

        //On vérifie que l'unité ne soit pas en cours de démolition et récupération du dernier en construction
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if ($element[2]) {
                    throw new ExceptionHB(3, 3);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file) && !isset($sauvLastKey)) {
            throw new ExceptionHB(3, 1);
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        //On tronque au maximum d'unités constructible sur la planète
        if (($metal = Donnee::metalVaisseaux($objet, $planete)) > 0) {
            $metal = $planete->metal/$metal;
        } else {
            $metal = $nombre;
        }
        if (($cristal = Donnee::cristalVaisseaux($objet, $planete)) > 0) {
            $cristal = $planete->cristal/$cristal;
        } else {
            $cristal = $nombre;
        }
        if (($hydrogene = Donnee::hydrogeneVaisseaux($objet, $planete)) > 0) {
            $hydrogene = $planete->hydrogene/$hydrogene;
        } else {
            $hydrogene = $nombre;
        }

        $nombre = floor(min($nombre, $metal, $cristal, $hydrogene));

        //On vérifie qu'il y ait assez de ressources sur la planète
        if ($planete->checkAndRetireRessources(Donnee::metalVaisseaux($objet, $planete, $nombre), Donnee::cristalVaisseaux($objet, $planete, $nombre), Donnee::hydrogeneVaisseaux($objet, $planete, $nombre), 0)) {
            //Si il existe déjà l'objet en file d'attente, on l'ajoute
            if (isset($sauvLastKey)) {
                $this->file[$sauvLastKey][1] += $nombre;
            } else {
                $this->file[] = array($objet, $nombre, false);
            }

            $planete->addModif("file_vais");
            return true;
        } else {
            throw new ExceptionHB(3, 4);
        }
    }

    public function vaisseaux_addDemolition($objet, $nombre, surface $planete)
    {
        //On vérifie que l'on ne dépasse pas la taille maximale de la file
        if (Donnee::tailleFile($planete) <= count($this->file)) {
            throw new ExceptionHB(3, 1);
        }

        //Vérification du nombre passé en entrée
        if ($nombre < 0 || $nombre > 99999) {
            throw new ExceptionHB(3, 8);
        }

        //On vérifie que le nombre d'unité actuel soit non nul
        if ($planete->vaisseaux[$objet] < $nombre) {
            throw new ExceptionHB(3, 6);
        }

        //On vérifie que l'unité ne soit pas en cours de construction ou démolition
        foreach ($this->file as $key => $element) {
            if ($element[0] == $objet) {
                if (!$element[2]) {
                    throw new ExceptionHB(3, 7);
                } else {
                    $sauvLastKey = $key;
                }
            }
        }

        //On rafraîchit le temps de la file si aucun objet n'est en file d'attente
        $this->refreshTime();

        if (isset($sauvLastKey)) {
            $this->file[$sauvLastKey][1] += $nombre;
        } else {
            $this->file[] = array($objet, $nombre, true);
        }

        $planete->addModif("file_vais");

        return true;
    }

    public function vaisseaux_delObjet($id, $nombre, surface $planete)
    {
        //Vérification de l'existance de l'objet en file d'attente
        if (empty($this->file[$id])) {
            throw new ExceptionHB(3, 5);
        }

        //Si $nombre est supérieur au nombre présent dans la file, on le réduit
        if ($this->file[$id][1] < $nombre) {
            $nombre = $this->file[$id][1];
        }

        //On récupère les informations disponibles
        $objet = $this->file[$id][0];
        $nombreMax = $this->file[$id][1];

        //On met à jour le temps si on vient d'annuler le premier groupe d'unités en lice
        if ($id == 0 && $nombreMax == $nombre) {
            $this->time = time();
        }

        $planete->addModif("file_vais");

        if (!$this->file[$id][2]) {
            $planete->addRessources(Donnee::metalVaisseaux($objet, $planete, $nombre), Donnee::cristalVaisseaux($objet, $planete, $nombre), Donnee::hydrogeneVaisseaux($objet, $planete, $nombre), 0);
        }

        //Effacement de la file
        if ($nombre >= $nombreMax) {
            unset($this->file[$id]);
        } else {
            $this->file[$id][1] -= $nombre;
        }
        $planete->addModif("file_vais");

        return true;
    }

    public function vaisseaux_ready(SURFACE $planete)
    {
        //On vérifie qu'il existe une unité en construction
        if (count($this->file) < 1) {
            return false;
        }

        //On parcourt la liste à la recherche des unités terminées dans l'ordre
        foreach ($this->file as $key => $element) {
            //Calcul du temps écoulé depuis la dernière construction
            $tempsEcoule = time() - $this->time;

            //On séparer les démolitions des constructions
            if ($element[2]) { //Cas de la démolition
                //On vérifie qu'il reste des unités du type sur la planète
                if ($planete->vaisseaux[$element[0]] <= 0) {
                    unset($this->file[$key]);
                    $planete->addModif("file_vais");
                } else {
                    //Récupération de 60% du temps nécessaire
                    $temps = Donnee::tempsVaisseaux($element[0], $planete) * 0.6;

                    //Calcul du nombre d'unités maximum
                    $nbUnitee = min(floor($tempsEcoule/$temps), $element[1], $planete->vaisseaux[$element[0]]);

                    //Si le temps écoulé est suffisant
                    if ($nbUnitee > 0) {
                        //On redonne 70% des ressources de l'unité au joueur
                        $planete->addRessources(Donnee::metalVaisseaux($element[0], $planete, $nbUnitee)*0.7, Donnee::cristalVaisseaux($element[0], $planete, $nbUnitee)*0.7, Donnee::hydrogeneVaisseaux($element[0], $planete, $nbUnitee)*0.7, 0);

                        //On retire les unités
                        $planete->vaisseaux[$element[0]] -= $nbUnitee;

                        //On efface l'entrée de la file et on met à jour le temps de la file
                        if ($nbUnitee >= $element[1]) {
                            unset($this->file[$key]);
                        } else {
                            $this->file[$key][1] -= $nbUnitee;
                        }
                        $this->time += $temps*$nbUnitee;

                        //On demande la mise à jour des champs modifiés
                        $planete->addModif("vaisseaux");
                        $planete->addModif("file_vais");

                        if ($nbUnitee < $element[1]) {
                            return false;
                        }
                    }
                    //Si le temps écoulé n'est pas suffisant pour cette unité, on annule toutes les suivantes
                    else {
                        return false;
                    }
                }
            } else { //Cas de la construction
                //Récupération du temps nécessaire
                $temps = Donnee::tempsVaisseaux($element[0], $planete);

                //Calcul du nombre d'unités maximum
                $nbUnitee = min(floor($tempsEcoule/$temps), $element[1]);

                //Si le temps écoulé est suffisant
                if ($nbUnitee > 0) {
                    //On ajoute le nombre d'unités
                    $planete->vaisseaux[$element[0]] += $nbUnitee;

                    //On efface l'entrée de la file et on met à jour le temps de la file
                    if ($nbUnitee >= $element[1]) {
                        unset($this->file[$key]);
                    } else {
                        $this->file[$key][1] -= $nbUnitee;
                    }
                    $this->time += $temps * $nbUnitee;

                    //On demande la mise à jour des champs modifiés
                    $planete->addModif("vaisseaux");
                    $planete->addModif("file_vais");

                    if ($nbUnitee < $element[1]) {
                        return false;
                    }
                }
                //Si le temps écoulé n'est pas suffisant pour ce batiment, on annule tous les suivants
                else {
                    return false;
                }
            }
        }
    }
}
