
/* malus globaux:
   attributs protégés : -0.25 par cas
   attributs public : -0.25 par cas
   méthode utilitaires publiques au lieu de protégée ou privée : -25 par cas
   (max -1)
   méthode inutilement redéfinie : -0.25 par cas
   masquage d'attribut: -.5 par cas
   Héritage aberrant : -1.5 par cas (par exemple Food héritant de Aquarium )
   Bonus globaux:
    Bons commentaires des méthodes : entre +1 et +2
    Bon usage du override : +1
   
*/
////////////////////////////////////////////////////////////////////
/* Classe Aquarium: living environment for the fishes
parlty provided (inheritance level and attributes + preventing copy)
Total: 16 points (without bonuses)
 */
/********************** QUESTION 1 *************************/
// partly provided
class Aquarium implements Updatable
		       // Question 2:
		       , AquariumFishEgView
		// Question 3:
			  , AquariumFishView
{
    // QUESTION 1
    // additionnal attributes
    private Vec3d dimensions; // 0.5
    private double ph; // 0.5
    private double fill_level; // 0.5
    private double temperature; // 0.5
    
    //TO BE ADDED IN QUESTION 1:
    // bonus of 0.75 if the constants are present
    final static double INITIAL_TEMPERATURE(22.0);
    final static double INITIAL_WATER_LEVEL(0.85);
    final static double INITIAL_PH(7.);

    //default initialisation to :
    /*
       double fill_level=INITIAL_WATER_LEVEL,
       double ph=INITIAL_PH,
       double temperature=INITIAL_TEMPERATURE);
    */
    // 3 (dont 1.5  pour la surcharge)
    public Aquarium(const Vec3d dimensions) {}
    public Aquarium( Vec3d dimensions, double fill_level, double ph,
                     double temperature) {}

    // provided (not graded)
    @Override
    public void update(double dt) {}

    // resets the level fill, ph and temperature
    // 1
    // -0.5 if non necessary parameters are present
    public void resetParameters() {}

    // 1.5 :solution with no parameter accepted
    public double fill(double percentage) {}

    
    // 0.5 point
    public double getPH() {}
    // 0.5 point
    public double getTemperature() {}
    //0.5 point
    public double getFillLevel() {}


    // transfers fishes to another aquarium
    // 2
    // QUESTION 1
    public void transferFishTo(Aquarium new_aquarium) {}
  
    
    // QUESTION 3:
    public void addFishEgg(int number of eggs);
    // QUESTION 4:
    boolean isColliding(Fish, Food);
}

/********************** QUESTION 2   *************************/
/* Class Food
   empty shell  + implementation link + abstract: 0.5 + 0.5 + 0.5= 1.5
 */

// QUESTION 2:
//1.75
interface AquariumFishEggView {
    void addFish(Fish);
    void removeFood(Food);
}

abstrat class Food implements Updatable {
    // 0.5
    private double energy; // énergie du nutriment
     private Vec3d position; // énergie du nutriment
    //1 points
     //- 0.25 par paramètre inutile
    public Food ( Vec3d position, double energie) {}

    // way of being consumed (loosing energy)
    // 1.5 points
    abstract void consume();

    // déplacement aléatoire
    // calls move
    // 1
    @Override
    void update(double dt) {}


    // returns true id energy < 0
    // 0.5 bonus
    boolean isDead() {}

 

   
    // Question 4 only
    // 0.75 
    abstract void acceptInteractionFrom(MaleFish);
    // 0.75
    
    abstract void acceptInteractionFrom(FemaleFish);

    // random move
    // 1 for modularisation
    protected void move(double dt);

    

}



/* Class FishEgg
   empty shell  + inheritance links : 0.5 + 0.5 = 1
  
 */
class FishEgg extends Food {
     // 0.25
    private boolean fertilised = false;

    //0.25
    private double incubationCounter=0;
    // 0.5
    public final static double INCUBATION_TIME = 10;
    // 1
    AquariumFishEggView home;
    
    // initialise l'énergie depuis le json
    // 1.5 (dont 1 pour AquariumFishEggView)
    // -0.25 si paramètres inutiles
    public FishEgg  (Vec3d position, double energy, AquariumFishEggView home ) { }

    // specific way of being eaten
    // 1.25
    @Override
    public void consume() {}

    // call Food::move()
    // increase incubation timer if fertilized
    // give birth to a new fish at time out 
    //(calls home.addFish(toFish()) + home.removeFood(this)
    //
    //2 ( 1 for the comments)
    @Override
    public void update(double dt) {}

    // 1
    public boolean isFertilized() {}
    // pour informer l'aquarium
    
   

    // sets fertilized to true
    // needed by the interaction methods
    // sets incubation counter to zero
    // 1 (0.5 for the comment)
    public void fertilise();


    // QUESTION 4:
    // fertilized or eaten
    // calls consume
    // 1.5 (0.5 for the comment)
    @Override
    void acceptInteractionFrom(MaleFish) { }

    // eaten
    // calls consume
    // 1.5
    @Override
    void acceptInteractionFrom(FemaleFish) {
    }


    // create a new fish
    // 1 (bonus for modularisation)
    private void bloom() {}
};

/* Class Flake
   empty shell  + inheritance links : 0.5 + 0.5 = 1

  Malus -0.5 pour redLfinition inutile de update
 
 */
class Flake extends Food {
    //1
    // - 0.25 par paramètre inutile 
    public Flake (Vec3d position) {}

    // façon spécifique d'être mangé
    // 1.25
    @Override
    public void consume() {}

    // QUESTION 4
    // calls consume
    //1
    @Override
    void acceptInteractionFrom(MaleFish) {}

    
    @Override
    void acceptInteractionFrom(FemaleFish) {}



};
/********************** QUESTION 3 *************************/

/*Note:
 *
 */
/* Classe Fish
   empty shell + implementation + abstract: 0.25 + 0.25 + 0.25
   
 */
// 3
interface AquariumFishView {
    Vec3d getTemperature();
    Vec3d getPH();
    void  addFishEgg(int numberOfEggs);
}

abstract class Fish implements Updatable {

    //0.25
    private Vec3d position;
    //0.25
    private double energy;
    // 1
     private AquariumFishView home;	
    // 1.5
    public Fish( Vec3d position, double energy, AquariumFishView);

    // Calls move
    //
    // 1.25
    @Override
    public void update(double dt) { }

    // 
    // 1 (0.5 for abstract)
    abstract void interactWith(Food food);

    // 1
    // for the female lo lay the eggs
    protected FishAquariumView getHome() { }
    
// 0.5 : modularisation
    private void move(double dt);
  

};

/* Class FemaleFish
  empty shell + inheritance: 0.25 + 0.25
 */
class FemaleFish extends Fish {
   
    // 1.5
    public FemaleFish(Vec3d position, double energy, AquariumFishView home) { }

    // calls Fish::update for moving
    // + calls layEggs
    // 1.5
    public void update(double dt) { }

    // 0.5 (prototype)
    public void interactWith(Food food) {
    }

    //lay eggs in aquarium
    // calls  home.addFishEgg
    // 0.5 (bonus, modularization)
    private void layEggs();
}

/* Class MaleFish
  empty shell + inheritance: 0.25 + 0.25 :0.5
Malus -0.5 pour redéfinition de update
 */
class MaleFish extends Fish {
    // 1.5
    public MaleFish( Vec3d position, double energy,AquariumFishView home);

    //0.5 (prototype)
    @Override
    public void interactWith(Food food) {
        food->acceptInteractionFrom(this);
    }
};

/********************** QUESTION 4 *************************/
Total: 8-5
//1.5
void MaleFish::interactWith(Food food) {
    food.acceptInteractionFrom(this);
}
// 1.5
void FemaleFish::interactWith(Food food) {
    food.acceptInteractionFrom(this);
}

// 1.5
void FishEgg::acceptInteractionFrom(MaleFish  fish) {
    fertilize();
}
// 1.5
void FishEgg::acceptInteractionFrom(FemaleFish fish) {
    consume();
}
// 1.5
void Flake::acceptInteractInteractionFrom(FemaleFish fish) {
    consume();
}
// 1.5
void Flake::acceptInteractInteractionFrom(MaleFish fish) {
    consume();
}


