Skip to content
Snippets Groups Projects
Philosopher.java 5.63 KiB
package example.philosophes;

import mas.core.Agent;
import mas.core.Schedulable;

import java.util.*;

public class Philosopher extends Agent {

    private Fork leftFork;

    private Fork rightFork;

    private Philosopher rightPhilosopher;

    private Philosopher leftPhilosopher;

    /**
     * The amount of time (in cycle) the philosopher haven't ate (while in state
     * hungry)
     */
    private double hungerDuration;
    /**
     * The amount of eaten pastas
     */
    private double eatenPastas;

    /**
     * The id of the philosopher
     */
    private int id;

    private Schedulable scheduler;

    /**
     * States philosophers can be in
     */
    public enum State {
        /**
         * The philosopher is thinking. It essentially means that they are not hungry
         * and not eating
         */
        THINK,
        /**
         * The philosopher is hungry. He wants to be in the state eating.
         */
        HUNGRY,
        /**
         * The philosopher has obtained the two forks and eat.
         */
        EATING
    }

    private State state = State.THINK;

    private double criticallity;

    public Philosopher(int _id, Fork _leftFork, Fork _rightFork, Philosopher _rightPhilosopher, Philosopher _leftPhilosopher) {
        id = _id;
        leftFork = _leftFork;
        rightFork = _rightFork;
        rightPhilosopher = _rightPhilosopher;
        leftPhilosopher = _leftPhilosopher;
    }

    @Override
    public void perceive() {
        System.out.println("Philosopher num " + id + " perceive");
        criticallity = computeCriticallity();
    }

    @Override
    public void decide() {
        System.out.println("Philosopher num " + id + " decide");

        State nextState = state;
        switch (state) {

            case EATING ->{
                eatenPastas++;
                if (new Random().nextInt(101) > 50) {
                    leftFork.release(this);
                    rightFork.release(this);
                    nextState = State.THINK;
                }
            }

            case HUNGRY -> {
                hungerDuration++;
                if (getMostCriticalNeighbor() == this) {
                    leftFork.tryTake(this);
                    rightFork.tryTake(this);
                    if (leftFork.owned(this) && rightFork.owned(this))
                        nextState = State.EATING;

                } else {
                    leftFork.release(this);
                    rightFork.release(this);
                }
            }
                case THINK->{
                    if (new Random().nextInt(101) > 50) {
                        hungerDuration = 0;
                        nextState = State.HUNGRY;
                    }
            }

            default -> {}
        }

        state = nextState;
        //System.out.println("Philospher n°" + id + " / State " + state);
        /*System.out.println(
                "\tPhilosopher num " + id + " : " + state + " / " + criticallity + " / " + eatenPastas
                 + "\n\t\t Right Fk : " + rightFork.getTakenBy().getId() + " / Left Fk : " + leftFork.getTakenBy().getId()
        );*/
    }

    @Override
    public void act() {
        System.out.println("Philosopher num " + id + " act");
        scheduler.addCyclable(new Waste(id));
    }

    @Override
    public boolean terminate() {
        return false;
    }


    private Philosopher getMostCriticalNeighbor() {
        List<Philosopher> criticalest = new ArrayList<>();
        double maxCriticality = getHungerDuration();

        criticalest.add(this);

        for(Map.Entry<Philosopher,Double> e : getNeighborsCriticallity()){
            if(e.getValue() > maxCriticality){
                criticalest.clear();
                maxCriticality = e.getValue();
                criticalest.add(e.getKey());
            } else if(e.getValue() == maxCriticality){
                criticalest.add(e.getKey());
            }
        }
        return criticalest.get(new Random().nextInt(criticalest.size()));
    }

    private double computeCriticallity(){

        if (state == State.HUNGRY){
            return hungerDuration;
        }
        return -1;
    }

    public Set<Map.Entry<Philosopher,Double>>  getNeighborsCriticallity(){
        Map<Philosopher, Double> criticalities = new HashMap<>();

        Philosopher leftPhilosopher = getLeftPhilosopher();
        Philosopher rightPhilosopher = getRightPhilosopher();

        criticalities.put(leftPhilosopher,leftPhilosopher.getCriticallity());
        criticalities.put(rightPhilosopher, rightPhilosopher.getCriticallity());

        return criticalities.entrySet();
    }

    public int getId() {
        return id;
    }

    public double getEatenPastas() {
        return eatenPastas;
    }

    public double getHungerDuration() {
        return hungerDuration;
    }

    public Fork getLeftFork() {
        return leftFork;
    }

    public Fork getRightFork() {
        return rightFork;
    }

    public Philosopher getLeftPhilosopher() {
        return leftPhilosopher;
    }

    public Philosopher getRightPhilosopher() {
        return rightPhilosopher;
    }

    public double getCriticallity() {
        return criticallity;
    }

    public void setLeftPhilosopher(Philosopher leftPhilosopher) {
        this.leftPhilosopher = leftPhilosopher;
    }

    public void setRightPhilosopher(Philosopher rightPhilosopher) {
        this.rightPhilosopher = rightPhilosopher;
    }

    public void setScheduler(Schedulable scheduler) {
        this.scheduler = scheduler;
    }

    public Schedulable getScheduler() {
        return scheduler;
    }

    @Override
    public String toString() {
        return "Philosopher " + id;
    }
}