Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
# Island
## Description

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

за реадми лайк


This program is a model of an island with variable parameters, consisting of an array of locations (for example, 100x20 cells). The locations will be filled with plants and animals. Animals can:

- There are plants and/or other animals (if there is suitable food in their location),

- Move around (to neighboring locations),

- Reproduce (if there is a pair in their location),

- Starve to death or be eaten.

## Menu
![Снимок экрана 2023-12-13 в 22.41.16.png](https://sun9-75.userapi.com/impf/flMZlZqf4zfSCd7SJ1_XWsEHyqQmOkGPdNni2Q/Wn8UBRtEaWU.jpg?size=1280x610&quality=96&sign=6abd3609550508af513ed3c207f6b1eb&type=album)
You can very flexibly change the simulation settings in the provided menu

![Снимок экрана 2023-12-13 в 22.41.51.png](https://sun9-10.userapi.com/impf/4MxG-31Cp3Hy0Fvf-gsVYJ2YH-fogGtDgL4nSg/DBnGgaffTfc.jpg?size=1280x734&quality=96&sign=6e817330e3712257a28aa9753b3fb3eb&type=album)

Also you can watch the simulation in the console

![Снимок экрана 2023-12-13 в 22.42.32.png](https://sun9-61.userapi.com/impf/jKHTOeM3SLnVWsS_oQKfMWBzJ2JLzp42fa0HVA/K3o5_Qn_a94.jpg?size=570x844&quality=96&sign=b8d9b0ad383710e33a61ba243b08d232&type=album)
![Снимок экрана 2023-12-13 в 22.42.46.png](https://sun9-19.userapi.com/impf/Hz_evDk2xinAjGoaViAjm-LG39Efdz0ioA45cw/M8qe7KBb0js.jpg?size=570x844&quality=96&sign=f13bd777dcde69fed47b86f4edaacf17&type=album)
11 changes: 11 additions & 0 deletions src/efanov/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package efanov;


import efanov.simulation.SimulationStarter;

public class Application {
public static void main(String[] args) {
SimulationStarter simulationStarter = new SimulationStarter();
simulationStarter.start();
}
}
42 changes: 42 additions & 0 deletions src/efanov/constants/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package efanov.constants;

import efanov.simulation.SimulationSettings;

public class Constant {
public static final String RESOURCES_PROBABILITY_YAML = "/Users/effgang/dev/Island/src/efanov/resources/probability.yaml";
public static final String ANIMAL_SETTINGS_PROPERTIES = "/Users/effgang/dev/Island/src/efanov/resources/animal-settings.properties";
public static final int PLANT_COUNT_TO_ADD = 10;
public static final String END = "***Simulation is over***";
public static final String DELIMITER = "-".repeat(20);
public static final String SIMULATION_STARTING = "Simulation starting...";
public static final String CHANGE_DATA = """
Would you like to change another parameter ?
1 - Yes
2 - No""";
public static final String INVALID_ANSWER = "Invalid answer ";
public static final String WRITE_1_OR_2 = " please write 1 or 2";
public static final String IT_S_NOT_A_NUMBER = "It's not a number: ";
public static final String ENTER_THE_PARAMETER_VALUE_FOR = "Please re-enter the parameter value for ";
public static final String WRITE_THE_PARAMETER_VALUE = "Write the parameter value: ";
public static final String WRITE_NUMBER_OF_PARAMETER = "Write parameter number: ";
public static final String GREETING = "We are glad to welcome you in our simulation, choose the parameters that you want to change";
public static final String INVALID_NUMBER_PLEASE_TRY_AGAIN = "Invalid number, please try again";
public static final String MAP_WIDTH = "Map width";
public static final String MAP_HEIGHT = "Map height";
public static final String COUNT_ENTITIES_IN_ONE_LOCATION = "Count entities in one location";
public static final String LIFE_CYCLE_OF_SIMULATION = "Life cycle of simulation (tact)";
public static final SimulationSettings settings = new SimulationSettings();
public static final String START_MENU = """
1. Map width
2. Map height
3. Count entities in one location
4. Life cycle of simulation (tact)
5. Continue
""";
public static final String DATA = "Initial data:\n" +
"width -> " + settings.getWidth() + "\n" +
"height -> " + settings.getHeight() + "\n" +
"Count entities in one location -> " + settings.getEntityCountOnCage() + "\n" +
"Life cycle of simulation (tact) -> " + settings.getLifeCycleTact() + "\n";

}
103 changes: 103 additions & 0 deletions src/efanov/dialog/UserDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package efanov.dialog;

import efanov.constants.Constant;
import efanov.simulation.SimulationSettings;

import java.util.InputMismatchException;
import java.util.Scanner;

public class UserDialog {
public boolean exit = false;
public String paramType = null;

public void showMenuAndChangeParameters(SimulationSettings settings) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.println(Constant.DATA);
System.out.println(Constant.GREETING);
while (true) {
System.out.println(Constant.DELIMITER);
System.out.print(Constant.START_MENU);
System.out.println(Constant.DELIMITER);
System.out.print(Constant.WRITE_NUMBER_OF_PARAMETER);
int ans;
try {
ans = scanner.nextInt();
if (ans < 0 || ans > 5) {
System.out.println(Constant.INVALID_NUMBER_PLEASE_TRY_AGAIN);
continue;
}
} catch (InputMismatchException e) {
String badValue = scanner.nextLine();
System.out.println(Constant.IT_S_NOT_A_NUMBER + badValue);
continue;
}

if (ans != 5) {
System.out.print(Constant.WRITE_THE_PARAMETER_VALUE);
}
if (ans == 1) {
paramType = Constant.MAP_WIDTH;
}
if (ans == 2) {
paramType = Constant.MAP_HEIGHT;
}
if (ans == 3) {
paramType = Constant.COUNT_ENTITIES_IN_ONE_LOCATION;
}
if (ans == 4) {
paramType = Constant.LIFE_CYCLE_OF_SIMULATION;
}
if (ans == 5) {
break;
}
Comment on lines +22 to +52

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это можно вынести в отдельный сервис ввода данных, чтобы было более читаемо и был нормальный код. Плюс можно вынести в enum и сделать вот так
enum SomeEnum {
VALUE(1, Constant.WRITE_THE_PARAMETER_VALUE),
VALUE2(2, Constant.MAP_WIDTH) и так далее и сделать switch case на этот enum


int param;
while (true) {
try {
param = scanner.nextInt();
} catch (InputMismatchException e) {
String badValue = scanner.nextLine();
System.out.println(Constant.IT_S_NOT_A_NUMBER + badValue + "\n" + Constant.ENTER_THE_PARAMETER_VALUE_FOR + paramType);
continue;
}
break;
}


switch (ans) {
case 1 -> settings.setWidth(param);
case 2 -> settings.setHeight(param);
case 3 -> settings.setEntityCountOnCage(param);
case 4 -> settings.setLifeCycleTact(param);
default -> System.out.println(Constant.INVALID_NUMBER_PLEASE_TRY_AGAIN);
}

System.out.println(Constant.CHANGE_DATA);

while (true) {
try {
int solution = scanner.nextInt();
if (solution == 1) {
break;
} else if (solution == 2) {
exit = true;
break;
} else {
System.out.println(Constant.INVALID_NUMBER_PLEASE_TRY_AGAIN);
}

} catch (InputMismatchException e) {
String badValue = scanner.nextLine();
System.out.println(Constant.INVALID_ANSWER + badValue + Constant.WRITE_1_OR_2);
}

}
if (exit) {
break;
}
}
} finally {
System.out.println(Constant.SIMULATION_STARTING);
}
}
}
55 changes: 55 additions & 0 deletions src/efanov/entities/EntitiesFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package efanov.entities;

import efanov.entities.animals.Animal;
import efanov.entities.animals.herbivores.*;
import efanov.entities.animals.predators.*;
import efanov.entities.plants.Herb;
import efanov.properties.processing.Processor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class EntitiesFactory {
Processor processor = new Processor();

public Entity createEntity(EntityType entityType) {
return switch (entityType) {
case WOLF -> getAnimal(entityType, Wolf.class);
case BEAR -> getAnimal(entityType, Bear.class);
case BOA -> getAnimal(entityType, Boa.class);
case FOX -> getAnimal(entityType, Fox.class);
case EAGLE -> getAnimal(entityType, Eagle.class);
case HORSE -> getAnimal(entityType, Horse.class);
case GOAT -> getAnimal(entityType, Goat.class);
case SHEEP -> getAnimal(entityType, Sheep.class);
case MOUSE -> getAnimal(entityType, Mouse.class);
case RABBIT -> getAnimal(entityType, Rabbit.class);
case DEER -> getAnimal(entityType, Deer.class);
case WILDBOAR -> getAnimal(entityType, WildBoar.class);
case DUCK -> getAnimal(entityType, Duck.class);
case BUFFALO -> getAnimal(entityType, Buffalo.class);
case CATERPILLAR -> getAnimal(entityType, Caterpillar.class);
case PLANT -> new Herb(processor.getEmojiFromFile(entityType.name()),
processor.getWeightFromFile(entityType.name()),
processor.getMaxCountFromFile(entityType.name()));
};
}

private Animal getAnimal(EntityType entityType, Class<? extends Animal> clazz) {
Constructor<? extends Animal> constructor;
try {

constructor = clazz.getDeclaredConstructor(String.class, Double.class, Integer.class, Integer.class, Double.class);

return constructor.newInstance(processor.getEmojiFromFile(entityType.name()),
processor.getWeightFromFile(entityType.name()),
processor.getMaxCountFromFile(entityType.name()),
processor.getSpeedFromFile(entityType.name()),
processor.getSaturationFromFile(entityType.name()));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
throw new RuntimeException(e);
}

}
}
14 changes: 14 additions & 0 deletions src/efanov/entities/Entity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package efanov.entities;

import lombok.*;

@Getter
@Setter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode
public abstract class Entity {
private String emoji;
private double weight;
private int maxCountOnLocation;

}
26 changes: 26 additions & 0 deletions src/efanov/entities/EntityType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package efanov.entities;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum EntityType {
WOLF,
BOA,
FOX,
BEAR,
EAGLE,
HORSE,
DEER,
RABBIT,
MOUSE,
GOAT,
SHEEP,
WILDBOAR,
BUFFALO,
DUCK,
CATERPILLAR,
PLANT

}
15 changes: 15 additions & 0 deletions src/efanov/entities/animals/Action.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package efanov.entities.animals;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum Action {
EAT(30),
REPRODUCE(30),
MOVE(30),
SLEEP(10);

private final int actionChance;
}
45 changes: 45 additions & 0 deletions src/efanov/entities/animals/Animal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package efanov.entities.animals;

import efanov.entities.Entity;
import lombok.Getter;
import lombok.Setter;

import java.util.concurrent.ThreadLocalRandom;

@Getter
@Setter
public abstract class Animal extends Entity {
private static final int BOUND = 100;
protected int speed;
protected double saturation;
protected double health;

public Animal(String emoji, Double weight, Integer maxCountOnLocation, Integer speed, Double saturation) {
super(emoji, weight, maxCountOnLocation);
this.speed = speed;
this.saturation = saturation;
this.health = saturation;
}

public abstract Animal reproduce();

public void eat(Entity food) {
if (food.getWeight() + this.getHealth() >= this.getSaturation()) {
this.setHealth(this.getSaturation());
} else {
double saturationAfterEating = this.getHealth() + food.getWeight();
this.setHealth(saturationAfterEating);
}
}

public Direction chooseDirection() {
return Direction.values()[ThreadLocalRandom.current().nextInt(Direction.values().length)];
}

public Action chooseAction() {
var action = Action.values()[ThreadLocalRandom.current().nextInt(Action.values().length)];
var isActiveAction = ThreadLocalRandom.current().nextInt(BOUND) < action.getActionChance();
return isActiveAction ? action : Action.SLEEP;
}

}
13 changes: 13 additions & 0 deletions src/efanov/entities/animals/Direction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package efanov.entities.animals;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum Direction {
LEFT,
RIGHT,
UP,
DOWN
}
27 changes: 27 additions & 0 deletions src/efanov/entities/animals/EatingMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package efanov.entities.animals;

import efanov.constants.Constant;
import lombok.Getter;
import org.yaml.snakeyaml.Yaml;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;

@Getter
public class EatingMap {
InputStream inputStream;

{
try {
inputStream = new FileInputStream(Constant.RESOURCES_PROBABILITY_YAML);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}

Yaml yaml = new Yaml();
Map<String, Map<String, Integer>> eatingProbability = yaml.load(inputStream);

}
13 changes: 13 additions & 0 deletions src/efanov/entities/animals/herbivores/Buffalo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package efanov.entities.animals.herbivores;

public class Buffalo extends Herbivore {

public Buffalo(String emoji, Double weight, Integer maxCountOnLocation, Integer speed, Double saturation) {
super(emoji, weight, maxCountOnLocation, speed, saturation);
}

@Override
public Buffalo reproduce() {
return new Buffalo(getEmoji(), getWeight(), getMaxCountOnLocation(), speed, saturation);
}
}
Loading