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;
}
}