Skip to content
Snippets Groups Projects
Commit aa89aa83 authored by Yanis O's avatar Yanis O
Browse files

Merge branch 'melissa'

parents ff834972 f996b97f
Branches
No related tags found
No related merge requests found
Pipeline #41507 passed
Showing
with 1092 additions and 61 deletions
Patients :
- Interactions et mouvement : Se déplacent et interagissent socialement, augmentant ainsi les chances de transmission du virus. Certains peuvent être asymptomatiques.
- Réaction en cas de maladie : S'ils se rendent compte qu'ils sont malades, ils cherchent un docteur pour se faire soigner. Sinon, ils continuent leur vie normalement, pouvant transmettre le virus sans le savoir.
Virus :
- Mouvement et infection : Entité unique sur le plateau qui se déplace aléatoirement, infectant les patients lorsqu'il passe à proximité.
- Le virus infecte les patients lorsqu'il passe à proximité.
- Évolue tous les 30 tours pour donner un nouveau variant, lorsqu'un nouveau variant est détecté, les médecins mettent plus de temps à le soigner au début
Docteurs :
- Traitement des patients : Traitent les patients malades qui se trouvent dans des cases adjacentes à leur position.
- Statique : Ne se déplacent pas entre les tours, ce qui nécessite que les patients viennent à eux pour être soignés.
...@@ -18,10 +18,10 @@ public class SimulatorApplication extends javafx.application.Application { ...@@ -18,10 +18,10 @@ public class SimulatorApplication extends javafx.application.Application {
private static final int BOX_WIDTH = 15; private static final int BOX_WIDTH = 15;
private static final int BOX_HEIGHT = 15; private static final int BOX_HEIGHT = 15;
public static final int INITIAL_FIRE_COUNT = 8; public static final int INITIAL_FIRE_COUNT = 8;
public static final int INITIAL_FIREFIGHTER_COUNT = 6; public static final int INITIAL_FIREFIGHTER_COUNT = 12;
public static final int INITIAL_MOTORIZED_FIREFIGHTER_COUNT = 8; public static final int INITIAL_MOTORIZED_FIREFIGHTER_COUNT = 8;
public static final int INITIAL_CLOUD_COUNT = 20; public static final int INITIAL_CLOUD_COUNT = 8;
public static final int INITIAL_MOUNTAIN_COUNT= 20; public static final int INITIAL_MOUNTAIN_COUNT= 6;
public static final int TURNS_FOR_SPAWNING_AIRTANKER = 10; public static final int TURNS_FOR_SPAWNING_AIRTANKER = 10;
private Stage primaryStage; private Stage primaryStage;
......
...@@ -20,7 +20,10 @@ import javafx.scene.control.ToggleGroup; ...@@ -20,7 +20,10 @@ import javafx.scene.control.ToggleGroup;
import javafx.util.Duration; import javafx.util.Duration;
import javafx.util.Pair; import javafx.util.Pair;
import model.Board; import model.Board;
import model.EmptySquare;
import model.Entity;
import model.EntityFactory; import model.EntityFactory;
import model.Model;
import model.Square; import model.Square;
import model.firefighterscenario.Cloud; import model.firefighterscenario.Cloud;
import model.firefighterscenario.Fire; import model.firefighterscenario.Fire;
...@@ -50,6 +53,7 @@ public class Controller { ...@@ -50,6 +53,7 @@ public class Controller {
private Grid<ViewElement> grid; private Grid<ViewElement> grid;
private Timeline timeline; private Timeline timeline;
private Board<Square> board; private Board<Square> board;
private Model model;
@FXML @FXML
private void initialize() { private void initialize() {
...@@ -63,12 +67,13 @@ public class Controller { ...@@ -63,12 +67,13 @@ public class Controller {
pauseToggleButton.setSelected(true); pauseToggleButton.setSelected(true);
} }
private void setModel(Board<Square> board) { private void setModel(Model model) {
this.board = requireNonNull(board, "board is null"); this.board = requireNonNull(model.getBoard(), "board is null");
this.model = model;
} }
private void updateBoard() { private void updateBoard() {
List<Position> updatedPositions = board.updateToNextGeneration(); List<Position> updatedPositions = model.updateToNextGeneration();
List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>(); List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
for (Position updatedPosition : updatedPositions) { for (Position updatedPosition : updatedPositions) {
Square squareState = board.getStates(updatedPosition); Square squareState = board.getStates(updatedPosition);
...@@ -91,6 +96,12 @@ public class Controller { ...@@ -91,6 +96,12 @@ public class Controller {
} }
private ViewElement getViewElement(Square square) { private ViewElement getViewElement(Square square) {
if (!square.getEntities().isEmpty()) {
for (Entity entity : square.getEntities()) {
if(entity instanceof EmptySquare)continue;
return entity.getViewElement();
}
}
return new ViewElement(square.getViewColor()); return new ViewElement(square.getViewColor());
} }
...@@ -121,6 +132,7 @@ public class Controller { ...@@ -121,6 +132,7 @@ public class Controller {
public void restartButtonAction() { public void restartButtonAction() {
this.pause(); this.pause();
board.reset(); board.reset();
System.gc();
pauseToggleButton.setSelected(true); pauseToggleButton.setSelected(true);
repaintGrid(); repaintGrid();
} }
...@@ -128,7 +140,7 @@ public class Controller { ...@@ -128,7 +140,7 @@ public class Controller {
public void initialize(int squareWidth, int squareHeight, int columnCount, public void initialize(int squareWidth, int squareHeight, int columnCount,
int rowCount, int initialFireCount, int initialFirefighterCount, int initialMotorizedFirefightersCount, int initialcloudCount, int initialmountaincount, int turnsForSpawningAirTanker) { int rowCount, int initialFireCount, int initialFirefighterCount, int initialMotorizedFirefightersCount, int initialcloudCount, int initialmountaincount, int turnsForSpawningAirTanker) {
grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight); grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight);
Board<Square> model = new FireFighterScenario(columnCount, rowCount);
Map<EntityFactory, Integer> entityCounts = new HashMap<EntityFactory, Integer>(); Map<EntityFactory, Integer> entityCounts = new HashMap<EntityFactory, Integer>();
entityCounts.put((pos, b) -> new Fire(pos), initialFireCount); entityCounts.put((pos, b) -> new Fire(pos), initialFireCount);
...@@ -138,7 +150,19 @@ public class Controller { ...@@ -138,7 +150,19 @@ public class Controller {
entityCounts.put((pos, b) -> new Mountain(pos), initialmountaincount); entityCounts.put((pos, b) -> new Mountain(pos), initialmountaincount);
entityCounts.put((pos, b) -> new Rockery(pos), 3); entityCounts.put((pos, b) -> new Rockery(pos), 3);
model.placeInitialEntities(entityCounts);
/*
entityCounts.put((pos, b) -> new Rock(pos), 10);
entityCounts.put((pos, b) -> new Cisor(pos), 10);
entityCounts.put((pos, b) -> new Paper(pos), 10);
*/
/*
entityCounts.put((pos, b) -> new Patient(pos), 70);
entityCounts.put((pos, b) -> new Virus(pos), 6);
entityCounts.put((pos, b) -> new Doctor(pos), 3);
*/
Model model = new FireFighterScenario(columnCount, rowCount, entityCounts);
this.setModel(model); this.setModel(model);
repaintGrid(); repaintGrid();
} }
......
...@@ -43,15 +43,6 @@ public interface Board<S> { ...@@ -43,15 +43,6 @@ public interface Board<S> {
*/ */
int columnCount(); int columnCount();
/**
* Update the board to its next generation or state. This method may modify the
* internal state of the board and return a list of positions that have changed
* during the update.
*
* @return A list of positions that have changed during the update.
*/
List<Position> updateToNextGeneration();
/** /**
* Reset the board to its initial state. * Reset the board to its initial state.
*/ */
...@@ -73,7 +64,7 @@ public interface Board<S> { ...@@ -73,7 +64,7 @@ public interface Board<S> {
public void clearCaseFrom(Entity entity, Position position); public void clearCaseFrom(Entity entity, Position position);
public Position getNearestEntity(Position fromPos, Class<?> entityType); public Position getNearestEntity(Position fromPos, Class<?> entityType, List<Entity> exclusionList);
public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType); public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType);
......
...@@ -4,7 +4,9 @@ import java.util.ArrayList; ...@@ -4,7 +4,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import model.firefighterscenario.Cloud;
import util.Position; import util.Position;
import view.ViewElement;
public class EmptySquare implements Entity { public class EmptySquare implements Entity {
...@@ -12,6 +14,15 @@ public class EmptySquare implements Entity { ...@@ -12,6 +14,15 @@ public class EmptySquare implements Entity {
private final Color viewColor = Color.WHITE; private final Color viewColor = Color.WHITE;
private int age; private int age;
private final int priotity = -1; private final int priotity = -1;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/img.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public EmptySquare(Position p) { public EmptySquare(Position p) {
this.position = p; this.position = p;
...@@ -61,4 +72,9 @@ public class EmptySquare implements Entity { ...@@ -61,4 +72,9 @@ public class EmptySquare implements Entity {
public int getPriority(){ public int getPriority(){
return this.priotity; return this.priotity;
} }
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
} }
package model; package model;
import java.util.List; import java.util.List;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import util.Position; import util.Position;
import view.ViewElement;
public interface Entity { public interface Entity {
...@@ -21,4 +21,5 @@ public interface Entity { ...@@ -21,4 +21,5 @@ public interface Entity {
public void incrementAge(); public void incrementAge();
public Color getViewColor(); public Color getViewColor();
public int getPriority(); public int getPriority();
public ViewElement getViewElement();
} }
package model;
class EntityNotFoundException extends Exception {
public EntityNotFoundException(String message) {
super(message);
}
}
\ No newline at end of file
package model;
import util.Matrix;
import util.Position;
public abstract class EntityScenario implements Scenario{
public void initScenario(Matrix<Square> matrix){
for(int x = 0; x < matrix.getRows(); x++){
for(int y = 0; y < matrix.getColumns(); y++){
Square s = new Square(new Position(x, y), new EmptySquare(new Position(x,y)));
matrix.set(x,y, s);
}
}
}
}
...@@ -12,6 +12,7 @@ import java.util.Set; ...@@ -12,6 +12,7 @@ import java.util.Set;
import util.Direction; import util.Direction;
import util.Position; import util.Position;
import util.PositionUtil;
public class EntitySpawner { public class EntitySpawner {
private final Board<Square> board; private final Board<Square> board;
...@@ -120,7 +121,7 @@ public class EntitySpawner { ...@@ -120,7 +121,7 @@ public class EntitySpawner {
int roadLength = 1; int roadLength = 1;
// Déterminer la direction interdite (opposée à la direction initiale) // Déterminer la direction interdite (opposée à la direction initiale)
Direction forbiddenDirection = getOppositeDirection(initialDirection); Direction forbiddenDirection = PositionUtil.getOppositeDirection(initialDirection);
// Initialiser la direction courante // Initialiser la direction courante
Direction currentDirection = initialDirection; Direction currentDirection = initialDirection;
...@@ -163,7 +164,7 @@ public class EntitySpawner { ...@@ -163,7 +164,7 @@ public class EntitySpawner {
// Mettre à jour la direction courante // Mettre à jour la direction courante
currentDirection = newDirection; currentDirection = newDirection;
forbiddenDirection = getOppositeDirection(currentDirection); forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
stepsInCurrentDirection = 0; stepsInCurrentDirection = 0;
continue; // Recommencer avec la nouvelle direction continue; // Recommencer avec la nouvelle direction
} else { } else {
...@@ -185,7 +186,7 @@ public class EntitySpawner { ...@@ -185,7 +186,7 @@ public class EntitySpawner {
// Mettre à jour la direction courante // Mettre à jour la direction courante
currentDirection = newDirection; currentDirection = newDirection;
forbiddenDirection = getOppositeDirection(currentDirection); forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
stepsInCurrentDirection = 0; stepsInCurrentDirection = 0;
} }
} }
...@@ -249,15 +250,7 @@ public class EntitySpawner { ...@@ -249,15 +250,7 @@ public class EntitySpawner {
} }
} }
private static Direction getOppositeDirection(Direction direction) {
switch (direction) {
case NORTH: return Direction.SOUTH;
case SOUTH: return Direction.NORTH;
case EAST: return Direction.WEST;
case WEST: return Direction.EAST;
default: throw new IllegalArgumentException("Direction non supportée : " + direction);
}
}
......
package model;
import java.util.List;
import util.Position;
public interface Model {
public List<Position> updateToNextGeneration();
public Board<Square> getBoard();
}
package model.firefighterscenario; package model;
import java.util.List; import java.util.List;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import model.Board; import model.firefighterscenario.Cloud;
import model.Entity;
import model.Square;
import util.Position; import util.Position;
import view.ViewElement;
public class Road implements Entity{ public class Road implements Entity{
private int age; private int age;
private final int PRIORITY = 0; private final int PRIORITY = 0;
private final Color VIEW_COLOR = Color.BLACK; private final Color VIEW_COLOR = Color.BLACK;
private Position position; private Position position;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/route.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public Road(Position position){ public Road(Position position){
this.position = position; this.position = position;
...@@ -57,4 +65,9 @@ public class Road implements Entity{ ...@@ -57,4 +65,9 @@ public class Road implements Entity{
return this.PRIORITY; return this.PRIORITY;
} }
@Override
public ViewElement getViewElement(){
return new ViewElement(cloudImage);
}
} }
package model; package model;
import java.util.List;
import java.util.Map;
import app.SimulatorApplication;
import util.Matrix; import util.Matrix;
import util.Position;
import util.PositionUtil;
public class Scenario implements Board<Square>{
private Matrix<Square> matrix;
protected int step;
protected int turnsToSpawnAirTanker;
protected Map<EntityFactory, Integer> initialMap;
public Scenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) {
this.matrix = new Matrix<Square>(columns, rows);
initScenario(matrix);
this.turnsToSpawnAirTanker = SimulatorApplication.TURNS_FOR_SPAWNING_AIRTANKER;
this.step = 0;
this.initialMap = initialMap;
placeInitialEntities(initialMap);
}
public void initScenario(Matrix<Square> matrix){
for(int x = 0; x < matrix.getRows(); x++){
for(int y = 0; y < matrix.getColumns(); y++){
Square s = new Square(new Position(x, y), new EmptySquare(new Position(x,y)));
matrix.set(x,y, s);
}
}
}
protected Matrix<Square> getMatrix(){
return this.matrix;
}
public void placeInitialEntities(Map<EntityFactory, Integer> initialMap) {
EntitySpawner spawner = new EntitySpawner(this);
spawner.spawnEntities(initialMap);
}
public Square getStates(Position position) {
if (position.x() > matrix.size() || position.y() > matrix.size()) {
throw new IllegalArgumentException(
"The position x:" + position.x() + " y:" + position.y() + " is out of the board.");
}
return matrix.get(position.x(), position.y());
}
public void setSquare(Square square) {
Position position = square.getPosition();
if (!(getStates(position).isEmpty())) {
return;
}
if (doesPositionExist(position)) {
matrix.set(position.x(), position.y(), square);
}
}
public interface Scenario { public void setSquare(Square square, boolean replaceStates) {
public void initScenario(Matrix<Square> matrix); Position position = square.getPosition();
if (!(getStates(position).isEmpty()) && !replaceStates) {
return;
}
matrix.set(position.x(), position.y(), square);
}
public void addEntityAtSquare(Entity entity, Position position) {
if (doesPositionExist(position)) {
matrix.get(position.x(), position.y()).addEntity(entity);
}
}
public int rowCount() {
return matrix.getRows();
}
public int columnCount() {
return matrix.getColumns();
}
@Override
public void clearCaseFrom(Entity entity, Position position) {
if(!matrix.get(position.x(), position.y()).getEntities().removeIf(element -> element.equals(entity))){
for(Entity e : getStates(position).getEntities()){
System.out.println(e);
}
}
}
public Position getNearestEntity(Position fromPos, Class<?> entityType, List<Entity> exclusionList) {
int rows = matrix.getRows();
int cols = matrix.getColumns();
if(exclusionList == null){
exclusionList = List.of();
}
// Définir la distance maximale possible
int maxDistance = rows + cols;
// Parcourir les distances croissantes à partir de 1
for (int distance = 1; distance < maxDistance; distance++) {
List<Position> positionsAtDistance = PositionUtil.getPositionsAtManhattanDistance(fromPos, distance, rows, cols);
for (Position currentPos : positionsAtDistance) {
if(isPositionEmpty(currentPos))continue;
Square currentSquare = matrix.get(currentPos.x(), currentPos.y());
for (Entity currentEntity : currentSquare.getEntities()) {
if (entityType.isInstance(currentEntity) && exclusionList != null && !exclusionList.contains(currentEntity)) {
// Vérifie si l'entité actuelle n'est pas dans la liste des exclusions
// Dès qu'une entité éligible est trouvée à cette distance, elle est la plus proche possible
return currentPos;
}
}
}
}
return null; // Retourne null si aucune entité éligible n'est trouvée
}
public void reset() {
step = 0;
matrix.clear();
initScenario(matrix);
placeInitialEntities(initialMap);
}
public int stepNumber() {
return this.step;
}
@Override
public boolean doesPositionExist(Position position) {
return matrix.validateIndex(position);
}
@Override
public int getStepNumber() {
return step;
}
@Override
public boolean doesSquareContainEntity(Position squarePos, Class<?> entityType) {
return getStates(squarePos).getEntities().stream().anyMatch(entityType::isInstance);
}
@Override
public boolean isPositionEmpty(Position position) {
return getStates(position).isEmpty();
}
@Override
public boolean isPositionFree(Position position, int priority) {
List<Entity> entities = matrix.get(position.x(), position.y()).getEntities();
for (Entity e : entities) {
if (e.getPriority() == priority) {
return false;
}
}
return true;
}
} }
package model.doctorviruspatient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javafx.scene.paint.Color;
import model.Board;
import model.Entity;
import model.Square;
import model.firefighterscenario.Cloud;
import util.Position;
import util.PositionUtil;
import view.ViewElement;
public class Doctor implements Entity {
private final int priority = 1;
private Position position;
private int age;
private final Color viewColor = Color.RED;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/docteur.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
// Statique car les médecins partagent les connaissances et les recherches
private static List<Integer> knownVirusVariant = new ArrayList<Integer>();
private static Map<Integer, Double> currentResearch = new HashMap<>(); // Map<variantId, % de recherche>
public Doctor(Position p) {
this.position = p;
}
public Doctor(Position p, int age) {
this.position = p;
this.age = age;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
// Mettre à jour les recherches en cours
updateCurrentResearch();
// Interagir avec les positions adjacentes
interactWithAdjacentPositions(PositionUtil.generateAllAdjacentPositions(position, board), board);
return List.of();
}
/**
* Met à jour toutes les recherches en cours en augmentant leur avancement de x%.
* Si une recherche atteint ou dépasse 100%, elle est terminée.
*/
private void updateCurrentResearch() {
List<Integer> completedResearch = new ArrayList<>();
for (Map.Entry<Integer, Double> entry : currentResearch.entrySet()) {
int variantId = entry.getKey();
double progress = entry.getValue() + 2.0;
if (progress >= 100.0) {
progress = 100.0;
completedResearch.add(variantId);
}
currentResearch.put(variantId, progress);
}
// Traiter les recherches complétées
for (int variantId : completedResearch) {
currentResearch.remove(variantId);
knownVirusVariant.add(variantId);
System.out.println("Recherche terminée pour le variant ID: " + variantId);
}
}
private List<Position> interactWithAdjacentPositions(List<Position> adjacentPositions, Board<Square> board) {
List<Position> result = new ArrayList<>();
for (Position p : adjacentPositions) {
if (board.doesSquareContainEntity(p, Patient.class)) {
handleEncounterWithPatient(p, board);
}
}
return result;
}
private void handleEncounterWithPatient(Position p, Board<Square> board) {
if (board.doesSquareContainEntity(p, Patient.class)) {
Patient patient = (Patient) board.getStates(p).getEntities().stream()
.filter(e -> e instanceof Patient)
.findFirst()
.orElse(null);
if (patient != null && patient.isInfected()) {
Virus virus = patient.getVirus();
if (virus != null) {
int variantId = virus.getVariantId();
if (knownVirusVariant.contains(variantId)) {
patient.cure();
} else {
// Si la variante n'est pas connue et pas en cours de recherche, l'ajouter à la recherche
if (!currentResearch.containsKey(variantId)) {
currentResearch.put(variantId, 0.0);
System.out.println("Nouvelle variante détectée! Variant ID: " + variantId + ". Recherche commencée.");
}
}
}
}
}
}
@Override
public Position getPosition() {
return this.position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public void incrementAge() {
this.age += 1;
}
@Override
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getPriority() {
return this.priority;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Doctor) {
Doctor other = (Doctor) obj;
return this.position.equals(other.getPosition());
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(position);
}
@Override
public ViewElement getViewElement() {
return new ViewElement (cloudImage);
}
}
package model.doctorviruspatient;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import model.Board;
import model.Entity;
import model.EntityFactory;
import model.Model;
import model.Scenario;
import model.Square;
import util.Position;
public class DoctorVirusPatientScenario extends Scenario implements Model{
public DoctorVirusPatientScenario(int columns, int rows, Map<EntityFactory, Integer> initialMap) {
super(columns, rows, initialMap);
}
public List<Position> updateToNextGeneration() {
ArrayList<Position> changedPositions = new ArrayList<>();
Iterator<Square> iterator = getMatrix().iterator();
while (iterator.hasNext()) {
Square s = iterator.next();
if (s.isEmpty())
continue;
if (s.getMaxAge() == 0) {
s.incrementAllAges();
continue;
}
if(s.getMaxAge()>stepNumber()+1){
continue;
}
List<Entity> entities = new ArrayList<>(s.getEntities());
for (Entity e : entities) {
e.incrementAge();
changedPositions.addAll(e.nextTurn(this));
}
}
// Increment the step counter
this.step = this.step + 1;
return changedPositions;
}
@Override
public Board<Square> getBoard() {
return this;
}
}
package model.doctorviruspatient;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import javafx.scene.paint.Color;
import model.Board;
import model.Entity;
import model.Square;
import model.firefighterscenario.Cloud;
import util.PathGenerator;
import util.Position;
import util.PositionUtil;
import view.ViewElement;
public class Patient implements Entity {
private final int priority = 1;
private Position position;
private int age;
private final Color viewColor = Color.BLUE;
private Virus carriedVirus;
private List<Entity> visitedPatients;
private static int patientsCount = 0;
private int patientID;
private Position ennemy;
private boolean isAsymptomatic;
private boolean wandering;
private static javafx.scene.image.Image healthyImage;
private static javafx.scene.image.Image infectedImage;
static {
try {
healthyImage = new javafx.scene.image.Image(Patient.class.getResource("/view/icons/virus/humain.png").toExternalForm());
infectedImage = new javafx.scene.image.Image(Patient.class.getResource("/view/icons/virus/patient.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
// Attributs pour le chemin
private List<Position> path;
private int pathIndex;
private static final int MAX_STEPS_IN_DIRECTION = 5;
private static final int MINIMUM_ROAD_LENGTH = 10;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/humain.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public Patient(Position p) {
this.wandering = true;
patientID = patientsCount;
patientsCount += 1;
this.visitedPatients = new ArrayList<>();
this.position = p;
Random r = new Random();
int randomNumber = r.nextInt(10);
this.isAsymptomatic = randomNumber == 1;
// Initialiser le chemin
this.path = new ArrayList<>();
this.pathIndex = 0;
}
public Patient(Position p, int age) {
this.wandering = true;
patientID = patientsCount;
patientsCount += 1;
this.visitedPatients = new ArrayList<>();
this.position = p;
this.age = age;
Random r = new Random();
int randomNumber = r.nextInt(10);
this.isAsymptomatic = randomNumber == 1;
// Initialiser le chemin
this.path = new ArrayList<>();
this.pathIndex = 0;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
if (isInfected() && !isAsymptomatic) {
return moveToDoctor(board);
}
updateWanderingStatus(board);
if (wandering) {
return performWandering(board);
}
resetVisitedPatientsIfNecessary();
Position target = determineTarget(board);
if (target == null) {
visitedPatients.clear();
return List.of();
}
Position nextPos = determineNextPosition(target, board);
if (nextPos != null && board.doesPositionExist(nextPos)) {
List<Position> adjacentPositions = PositionUtil.generateAllAdjacentPositions(nextPos, board);
List<Position> result = interactWithAdjacentPositions(adjacentPositions, board);
result.addAll(moveToPosition(nextPos, board));
result.addAll(adjacentPositions);
result.add(position);
return result;
}
return List.of();
}
private void updateWanderingStatus(Board<Square> board) {
if (board.getStepNumber() % 8 == 0) {
wandering = false;
// Réinitialiser le chemin lorsque le patient arrête d'errer
this.path.clear();
this.pathIndex = 0;
}
}
private List<Position> moveToDoctor(Board<Square> board) {
for (Position p : PositionUtil.generateAllAdjacentPositions(position, board)) {
if (!board.doesPositionExist(p)) continue;
if (board.doesSquareContainEntity(p, Doctor.class)) return List.of();
}
Position nearestDoctor = board.getNearestEntity(position, Doctor.class, null);
Position nextPos = PositionUtil.getNextPositionTowards(position, nearestDoctor, board);
if (nextPos == null) return List.of();
List<Position> changedPositions = new ArrayList<>();
changedPositions.addAll(moveToPosition(nextPos, board));
return changedPositions;
}
private List<Position> performWandering(Board<Square> board) {
if (path == null || path.isEmpty() || pathIndex >= path.size()) {
generateNewPath(board);
if (path.isEmpty()) {
return List.of();
}
}
Position nextPosition = path.get(pathIndex);
if (board.doesPositionExist(nextPosition) && board.isPositionFree(nextPosition, priority)) {
List<Position> changedPositions = moveSelfOnBoard(nextPosition, board);
pathIndex++;
return changedPositions;
} else {
// Si la position n'est pas libre ou n'existe pas, générer un nouveau chemin
generateNewPath(board);
return List.of();
}
}
private void generateNewPath(Board<Square> board) {
PathGenerator pathGenerator = new PathGenerator(board, position, MAX_STEPS_IN_DIRECTION, MINIMUM_ROAD_LENGTH);
this.path = pathGenerator.generate();
// Supprimer la position actuelle du chemin si elle est présente
if (!path.isEmpty() && path.get(0).equals(position)) {
path.remove(0);
}
this.pathIndex = 0;
}
private void resetVisitedPatientsIfNecessary() {
if (visitedPatients.size() - 1 >= patientsCount) {
visitedPatients.clear();
}
}
private Position determineTarget(Board<Square> board) {
return board.getNearestEntity(position, Patient.class, getVisitedPatients());
}
private Position determineNextPosition(Position target, Board<Square> board) {
int enemyDistance = PositionUtil.getManhattanDistance(target, position);
if (ennemy != null && enemyDistance < 2) {
return PositionUtil.getNextPositionAwayFrom(position, target, board);
} else if (target != null) {
return PositionUtil.getNextPositionTowards(position, target, board);
}
return null;
}
private List<Position> moveToPosition(Position nextPos, Board<Square> board) {
List<Position> changedPosition = new ArrayList<>();
if (!board.isPositionFree(nextPos, priority)) {
nextPos = findAlternativePosition(nextPos, board);
}
if (nextPos != null) {
changedPosition.addAll(moveSelfOnBoard(nextPos, board));
}
return changedPosition;
}
private Position findAlternativePosition(Position currentPos, Board<Square> board) {
List<Position> adjacentPositions = PositionUtil.generateAdjacentPositions(position, board);
for (Position p : adjacentPositions) {
if (ennemy != null) {
Position awayPos = PositionUtil.getNextPositionAwayFrom(p, ennemy, board);
if (p.equals(awayPos)) {
continue;
}
}
if (board.isPositionFree(p, priority)) {
return p;
}
}
return null;
}
private List<Position> moveSelfOnBoard(Position newPosition, Board<Square> board) {
if(!board.isPositionFree(newPosition, priority))return List.of();
Position oldPosition = new Position(this.position.x(), this.position.y());
board.clearCaseFrom(this, oldPosition);
board.addEntityAtSquare(this, newPosition);
this.position = newPosition;
return List.of(oldPosition, this.position);
}
private List<Position> interactWithAdjacentPositions(List<Position> adjacentPositions, Board<Square> board) {
List<Position> result = new ArrayList<>();
for (Position p : adjacentPositions) {
if (board.doesSquareContainEntity(p, Patient.class)) {
handleEncounterWithPatient(p, board);
if (isInfected()) {
result.addAll(adjacentPositions);
}
}
}
return result;
}
private void handleEncounterWithPatient(Position p, Board<Square> board) {
this.wandering = true;
// Réinitialiser le chemin lorsqu'un patient est rencontré
this.path.clear();
this.pathIndex = 0;
Patient patient = (Patient) board.getStates(p).getEntities().stream()
.filter(entity -> entity instanceof Patient)
.findFirst()
.orElse(null);
if (isInfected()) {
patient.infect(carriedVirus);
}
if (patient != null) {
this.ennemy = patient.getPosition();
visitedPatients.add(patient);
}
}
@Override
public Position getPosition() {
return this.position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public void incrementAge() {
this.age += 1;
}
@Override
public Color getViewColor() {
return isInfected() ? Color.CYAN : this.viewColor;
}
@Override
public int getPriority() {
return this.priority;
}
public boolean isInfected() {
return this.carriedVirus != null;
}
public void infect(Virus virus) {
if (this.carriedVirus != null) return;
this.carriedVirus = virus;
}
public Virus getVirus() {
return this.carriedVirus;
}
public List<Entity> getVisitedPatients() {
return this.visitedPatients;
}
public boolean hasVisited(Patient patient) {
return this.getVisitedPatients().contains(patient);
}
public int getPatientId() {
return this.patientID;
}
public void cure() {
if (this.carriedVirus.tryToKill()) {
this.carriedVirus = null;
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Patient) {
Patient other = (Patient) obj;
return this.patientID == other.getPatientId();
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(patientID);
}
@Override
public ViewElement getViewElement() {
return isInfected() ? new ViewElement(infectedImage) : new ViewElement(healthyImage);
}
}
package model.doctorviruspatient;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.scene.paint.Color;
import model.Board;
import model.Entity;
import model.Square;
import model.firefighterscenario.Cloud;
import util.PathGenerator;
import util.Position;
import util.PositionUtil;
import view.ViewElement;
public class Virus implements Entity {
private final int priority = 2;
private Position position;
private int age;
private final Color viewColor = Color.LIMEGREEN;
private List<Position> path;
private int pathIndex;
private static final int MAX_STEPS_IN_DIRECTION = 5;
private static final int MINIMUM_ROAD_LENGTH = 10;
private int health;
private int variantId;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/virus/virus.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public Virus(Position p) {
this.variantId = 0;
this.health = 50;
this.position = p;
this.path = new ArrayList<>();
this.age = 0;
this.pathIndex = 0;
}
public Virus(Position p, int age) {
this.health = 8;
this.position = p;
this.age = age;
this.path = new ArrayList<>();
this.pathIndex = 0;
}
@Override
public List<Position> nextTurn(Board<Square> board) {
if(board.getStepNumber() % 100 == 0){
evolve();
}
// Génère un nouveau chemin si nécessaire
if (path == null || path.isEmpty() || pathIndex >= path.size()) {
generateNewPath(board);
if (path.isEmpty()) {
return List.of();
}
}
List<Position> adjacentPosition = PositionUtil.generateAllAdjacentPositions(position, board);
for(Position p : adjacentPosition){
if(board.doesSquareContainEntity(p, Patient.class)){
Patient patient = (Patient) board.getStates(p).getEntities().stream().filter(e -> e instanceof Patient).findFirst().get();
patient.infect(this);
}
}
// Se déplace vers la prochaine position du chemin
Position nextPosition = path.get(pathIndex);
if (board.doesPositionExist(nextPosition)) {
// Vérifier si la position est libre
if (board.isPositionFree(nextPosition, priority)) {
Position oldPosition = position;
position = nextPosition;
board.clearCaseFrom(this, oldPosition);
board.addEntityAtSquare(this, position);
pathIndex = pathIndex + 1;
return List.of(oldPosition, position);
} else {
// Si la position n'est pas libre, génère un nouveau chemin
generateNewPath(board);
return List.of();
}
} else {
// Si la prochaine position n'existe pas, génère un nouveau chemin
generateNewPath(board);
return List.of();
}
}
private void generateNewPath(Board<Square> board) {
PathGenerator pathGenerator = new PathGenerator(board, position, MAX_STEPS_IN_DIRECTION, MINIMUM_ROAD_LENGTH);
this.path = pathGenerator.generate();
// Supprime la position actuelle du chemin si elle est présente au début
if (!path.isEmpty() && path.get(0).equals(position)) {
path.remove(0);
}
this.pathIndex = 0; // Réinitialise l'index du chemin
}
// Les autres méthodes restent inchangées
private void evolve(){
this.variantId++;
Random r = new Random();
this.health = r.nextInt(100);
}
public int getVariantId(){
return this.variantId;
}
@Override
public Position getPosition() {
return this.position;
}
@Override
public void setPosition(Position p) {
this.position = p;
}
@Override
public int getAge() {
return this.age;
}
@Override
public void setAge(int age) {
this.age = age;
}
@Override
public void incrementAge() {
this.age += 1;
}
@Override
public Color getViewColor() {
return this.viewColor;
}
@Override
public int getPriority() {
return this.priority;
}
public boolean tryToKill(){
if(health <= 0){
return true;
}
health--;
return false;
}
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
}
...@@ -11,6 +11,7 @@ import model.Square; ...@@ -11,6 +11,7 @@ import model.Square;
import util.Direction; import util.Direction;
import util.Position; import util.Position;
import util.PositionUtil; import util.PositionUtil;
import view.ViewElement;
public class AirTanker implements Entity{ public class AirTanker implements Entity{
private final Color viewColor = Color.GOLD; private final Color viewColor = Color.GOLD;
...@@ -18,6 +19,15 @@ public class AirTanker implements Entity{ ...@@ -18,6 +19,15 @@ public class AirTanker implements Entity{
private int age; private int age;
private Position position; private Position position;
private int priority = 3; private int priority = 3;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/avion.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public AirTanker(Position position, Board<Square> b, int age) { public AirTanker(Position position, Board<Square> b, int age) {
this.age = age; this.age = age;
...@@ -163,5 +173,8 @@ public class AirTanker implements Entity{ ...@@ -163,5 +173,8 @@ public class AirTanker implements Entity{
return Objects.hash(position, age); return Objects.hash(position, age);
} }
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
} }
...@@ -10,6 +10,7 @@ import model.Entity; ...@@ -10,6 +10,7 @@ import model.Entity;
import model.Square; import model.Square;
import util.Position; import util.Position;
import util.PositionUtil; import util.PositionUtil;
import view.ViewElement;
public class Cloud implements Entity{ public class Cloud implements Entity{
private int age; private int age;
...@@ -17,8 +18,15 @@ public class Cloud implements Entity{ ...@@ -17,8 +18,15 @@ public class Cloud implements Entity{
private final Color viewColor = Color.GRAY; private final Color viewColor = Color.GRAY;
private final int priority = 2; private final int priority = 2;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/nuage.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public Cloud(Position position, Board<Square> b){ public Cloud(Position position, Board<Square> b){
this.age = 0; this.age = 0;
this.position = position; this.position = position;
...@@ -108,5 +116,11 @@ public class Cloud implements Entity{ ...@@ -108,5 +116,11 @@ public class Cloud implements Entity{
return this.priority; return this.priority;
} }
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
} }
...@@ -8,9 +8,11 @@ import java.util.Optional; ...@@ -8,9 +8,11 @@ import java.util.Optional;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import model.Board; import model.Board;
import model.Entity; import model.Entity;
import model.Road;
import model.Square; import model.Square;
import util.Position; import util.Position;
import util.PositionUtil; import util.PositionUtil;
import view.ViewElement;
public class Fire implements Entity { public class Fire implements Entity {
...@@ -18,6 +20,15 @@ public class Fire implements Entity { ...@@ -18,6 +20,15 @@ public class Fire implements Entity {
private final Color viewColor = Color.RED; private final Color viewColor = Color.RED;
private int age; private int age;
private final int priority = 1; private final int priority = 1;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/flamme.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public Fire(Position position) { public Fire(Position position) {
this.position = position; this.position = position;
...@@ -132,4 +143,9 @@ public class Fire implements Entity { ...@@ -132,4 +143,9 @@ public class Fire implements Entity {
return Objects.hash(position, age); return Objects.hash(position, age);
} }
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
} }
...@@ -10,6 +10,7 @@ import model.Entity; ...@@ -10,6 +10,7 @@ import model.Entity;
import model.Square; import model.Square;
import util.Position; import util.Position;
import util.PositionUtil; import util.PositionUtil;
import view.ViewElement;
...@@ -19,6 +20,15 @@ public class FireFighter implements Entity { ...@@ -19,6 +20,15 @@ public class FireFighter implements Entity {
private final Color viewColor = Color.BLUE; private final Color viewColor = Color.BLUE;
private final int priority = 1; private final int priority = 1;
protected List<Position> lastThreePosition; protected List<Position> lastThreePosition;
private static javafx.scene.image.Image cloudImage;
static {
try {
cloudImage = new javafx.scene.image.Image(Cloud.class.getResource("/view/icons/fire/sapeur-pompier.png").toExternalForm());
} catch (Exception e) {
e.printStackTrace();
}
}
public FireFighter(Position position, Board<Square> b) { public FireFighter(Position position, Board<Square> b) {
this.position = position; this.position = position;
...@@ -107,7 +117,12 @@ public class FireFighter implements Entity { ...@@ -107,7 +117,12 @@ public class FireFighter implements Entity {
List<Position> positions = new ArrayList<>(); List<Position> positions = new ArrayList<>();
// Find the nearest fire // Find the nearest fire
Position nearestFirePos = b.getNearestEntity(position, Fire.class); Position nearestFirePos;
try {
nearestFirePos = b.getNearestEntity(position, Fire.class, null);
} catch (Exception e) {
return List.of();
}
if (nearestFirePos != null) { if (nearestFirePos != null) {
// Get the next position towards the fire // Get the next position towards the fire
Position nextPos = getNextPositionTowards(position, nearestFirePos, b); Position nextPos = getNextPositionTowards(position, nearestFirePos, b);
...@@ -220,4 +235,8 @@ public class FireFighter implements Entity { ...@@ -220,4 +235,8 @@ public class FireFighter implements Entity {
} }
public int getPriority(){ return this.priority;} public int getPriority(){ return this.priority;}
@Override
public ViewElement getViewElement() {
return new ViewElement(cloudImage);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment