Skip to content

Commit

Permalink
added SimulationThread
Browse files Browse the repository at this point in the history
  • Loading branch information
PiotrMakarewicz committed Dec 22, 2020
1 parent fdac506 commit 0d98639
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 75 deletions.
10 changes: 5 additions & 5 deletions parameters.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"width": 10,
"height": 10,
"width": 25,
"height": 25,
"jungleRatio": 0.05,
"moveEnergy": 1.0,
"initialEnergy": 50.0,
"moveEnergy": 0.00001,
"initialEnergy": 100.0,
"plantEnergy": 25.0,
"initialAnimals": 3
"initialAnimals": 10
}
49 changes: 10 additions & 39 deletions src/sample/Main.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package sample;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import simulation.Simulation;
import simulation.SimulationErrorException;
Expand All @@ -14,45 +20,10 @@ public class Main extends Application {

@Override
public void start(Stage stage) throws Exception{
Simulation s1 = ParametersLoader.load("parameters.json");
displaySimulation(s1,stage);
}

public void displaySimulation(Simulation simulation, Stage stage) throws InterruptedException, SimulationErrorException {
final Group root = new Group();
final double width = simulation.getWidth()*10;
final double height = simulation.getHeight()*10;
final Scene simulationScene = new Scene(root, width, height, Color.BLACK);

final StatsWatcher statsWatcher = new StatsWatcher(simulation);
final SimulationCanvas canvas = new SimulationCanvas(simulation);

root.getChildren().add(canvas);
stage.setScene(simulationScene);
stage.setResizable(false);

simulation.start();
canvas.drawBackground();
canvas.update();
stage.show();
Task<Integer> task = new Task<>() {
@Override protected Integer call() throws Exception {
int iterations;
for (iterations = 0; true; iterations++) {
if (isCancelled()) {
break;
}
simulation.simulateOneDay();
System.out.println("CANVAS UPDATE start");
canvas.update();
statsWatcher.printStats();
Thread.sleep(100);
}
return iterations;
}
};
Thread th = new Thread(task);
th.start();
SimulationThread t1 = new SimulationThread(ParametersLoader.load("parameters.json"));
SimulationThread t2 = new SimulationThread(ParametersLoader.load("parameters.json"));
t1.start();
t2.start();
}

public static void main(String[] args) {
Expand Down
66 changes: 66 additions & 0 deletions src/sample/SimulationThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package sample;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import simulation.Simulation;
import simulation.StatsWatcher;

public class SimulationThread extends Thread{
private final Stage stage = new Stage();
private final Simulation simulation;
public void run() {
Platform.runLater(this::displaySimulation);
}
public SimulationThread(Simulation simulation){
this.simulation = simulation;
}
public void displaySimulation() {
final Group root = new Group();
final double width = simulation.getWidth()*10+400;
final double height = Math.max(simulation.getHeight()*10,400);
final Scene simulationScene = new Scene(root, width, height, Color.BLACK);

final StatsWatcher statsWatcher = new StatsWatcher(simulation);
final SimulationCanvas canvas = new SimulationCanvas(simulation);
canvas.setLayoutX(400);
final Label statsLabel = new Label();
statsLabel.setTextFill(Color.web("#FFFFFF"));
statsLabel.setPadding(new Insets(5.0));

root.getChildren().add(statsLabel);
root.getChildren().add(canvas);
stage.setScene(simulationScene);
stage.setResizable(false);

simulation.start();
canvas.drawBackground();
canvas.update();
stage.show();
Task<Integer> task = new Task<>() {
@Override protected Integer call() throws Exception {
int iterations;
for (iterations = 0; true; iterations++) {
if (isCancelled()) {
break;
}
simulation.simulateOneDay();
System.out.println("CANVAS UPDATE start");

Platform.runLater(canvas::update);
Platform.runLater(()->{statsLabel.setText(statsWatcher.getSummary());});

Thread.sleep(100);
}
return iterations;
}
};
Thread th = new Thread(task);
th.start();
}
}
8 changes: 4 additions & 4 deletions src/simulation/Animal.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class Animal{
this.genome = new Genome();
this.location = location;
this.direction = Direction.values()[(new Random(System.nanoTime()).nextInt(8))];
System.out.println("Spawning "+this.toString()+" at "+location.toString());
//System.out.println("Spawning "+this.toString()+" at "+location.toString());
};

Animal(Animal parent1, Animal parent2, int birthDay, Location location){
Expand All @@ -30,19 +30,19 @@ public class Animal{
this.direction = Direction.values()[(new Random(System.nanoTime()).nextInt(8))];
parent1.children.add(this);
parent2.children.add(this);
System.out.println("Born "+this.toString()+", child of "+parent1.toString()+" and "+parent2.toString()+", at "+location);
//System.out.println("Born "+this.toString()+", child of "+parent1.toString()+" and "+parent2.toString()+", at "+location);
}

public void die(int deathDay) throws AnimalStateException {
System.out.println(this.toString()+" dies at "+this.location);
//System.out.println(this.toString()+" dies at "+this.location);
if (!this.isAlive())
throw new AnimalStateException("Trying to kill a dead animal: " + this.toString());
this.energy = 0;
this.deathDay = deathDay;
}
public void shift() {
direction = direction.shiftedBy(genome.pickRandomGene());
System.out.println(this.toString() + " shifts to " + this.direction);
//System.out.println(this.toString() + " shifts to " + this.direction);
}

public int getBirthDay() {
Expand Down
6 changes: 5 additions & 1 deletion src/simulation/AnimalBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class AnimalBoard {
private List<Animal> deadAnimals = new ArrayList<>();

public List<Animal> getAllAlive(){
List<Animal> allAnimals = new ArrayList<Animal>();
List<Animal> allAnimals = new ArrayList<>();
for (List<Animal> locationAnimals : locationAnimalMap.values()){
allAnimals = Stream.concat(allAnimals.stream(),locationAnimals.stream()).collect(Collectors.toList());
}
Expand Down Expand Up @@ -84,4 +84,8 @@ public void update(){
}
}
}

public List<Animal> getAllDead() {
return deadAnimals;
}
}
16 changes: 8 additions & 8 deletions src/simulation/Simulation.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ private void addPlants(){
Location location = Location.getRandom(width,height);
if(jungle.contains(location) && !plantedInJungle){
plantBoard.plant(location);
System.out.println("Added in-jungle plant at "+location.toString());
//System.out.println("Added in-jungle plant at "+location.toString());
plantedInJungle = true;
}
else if(!jungle.contains(location) && !plantedOutsideJungle){
plantBoard.plant(location);
System.out.println("Added outside-jungle plant at "+location.toString());
//System.out.println("Added outside-jungle plant at "+location.toString());
plantedOutsideJungle = true;
}
}
Expand All @@ -65,7 +65,7 @@ private void moveAnimals() throws AnimalStateException {
animal.die(currentDay);
animalBoard.markAsDead(animal);
} else {
System.out.println("Moving "+animal.toString()+" from " + animal.getLocation() +" to "+toBoardLimits(animal.getLocation().stepTo(animal.getDirection())));
//System.out.println("Moving "+animal.toString()+" from " + animal.getLocation() +" to "+toBoardLimits(animal.getLocation().stepTo(animal.getDirection())));
animal.shift();
animal.setLocation(toBoardLimits(animal.getLocation().stepTo(animal.getDirection())));
}
Expand Down Expand Up @@ -94,7 +94,7 @@ public void eatPlants() throws UnplantingUnplantedLocationException{
}
plantBoard.unplant(location);
eatenPlants.add(location);
System.out.println("Plant eaten at " + location.toString() + " by " + animals.get(0).toString());
//System.out.println("Plant eaten at " + location.toString() + " by " + animals.get(0).toString());
}
}
}
Expand Down Expand Up @@ -152,13 +152,13 @@ public void simulateOneDay() throws SimulationErrorException{
currentDay++;
System.out.println("\nSTARTING DAY "+ currentDay + "\n=======================================");
try {
System.out.println("\nMoving animals\n=======================================");
//System.out.println("\nMoving animals\n=======================================");
moveAnimals();
System.out.println("\nEating plants\n=======================================");
//System.out.println("\nEating plants\n=======================================");
eatPlants();
System.out.println("\nReproducing animals\n=======================================");
//System.out.println("\nReproducing animals\n=======================================");
reproduceAnimals();
System.out.println("\nAdding plants\n=======================================");
//System.out.println("\nAdding plants\n=======================================");
addPlants();
} catch(AnimalStateException e){
throw new SimulationErrorException("AnimalStateException: "+ e.toString(),this);
Expand Down
45 changes: 27 additions & 18 deletions src/simulation/StatsWatcher.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package simulation;

import java.sql.SQLOutput;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.*;
import java.util.stream.Collectors;

public class StatsWatcher {
Expand All @@ -23,7 +19,7 @@ public double getAverageEnergy(){
double totalEnergy = animals.stream().map(Animal::getEnergy).reduce(0.0, Double::sum);
return totalEnergy/animals.size();
}
public Genome getDominatingGenome(){
public Optional<Genome> getDominatingGenome(){
Map<Genome,Integer> occurrences = new TreeMap<>();
for (Animal animal : simulation.animalBoard.getAllAlive()){
Genome genome = animal.getGenome();
Expand All @@ -32,7 +28,7 @@ public Genome getDominatingGenome(){
}
else occurrences.put(genome,occurrences.get(genome)+1);
}
return occurrences.keySet().stream().max(Comparator.comparingInt(occurrences::get)).get();
return occurrences.keySet().stream().max(Comparator.comparingInt(occurrences::get));
}
public double getAverageChildrenNumber(){
return simulation.animalBoard.getAllAlive().stream()
Expand All @@ -42,19 +38,32 @@ public double getAverageChildrenNumber(){
/simulation.animalBoard.getAllAlive().size();
}
public List<Animal> getAnimalsWithDominatingGenome(){
return simulation.animalBoard.getAllAlive().stream()
.filter(a -> a.getGenome().equals(getDominatingGenome()))
if(getDominatingGenome().isPresent())
return simulation.animalBoard.getAllAlive().stream()
.filter(a -> a.getGenome().equals(getDominatingGenome().get()))
.collect(Collectors.toList());
else return new ArrayList<>();
}

public double getAverageLifeExpectancy(){
if (simulation.animalBoard.getAllDead().isEmpty())
return 0;
else return ((Integer)simulation.animalBoard.getAllDead()
.stream().mapToInt(a -> a.getDeathDay() - a.getBirthDay())
.sum()).doubleValue() / simulation.animalBoard.getAllDead().size();
}
public double toTwoDecimalPlaces(double v){
return ((Long)Math.round(v*100)).doubleValue()/100;
}

public void printStats(){
System.out.println("\nSimulation "+ simulation.name+" statistics:");
System.out.println("=======================================");
System.out.println("Alive animals: " +getAliveAnimalsNum());
System.out.println("Plants: "+getPlantsNum());
System.out.println("Average energy: "+getAverageEnergy());
System.out.println("Dominating genome: "+getDominatingGenome());
System.out.println("Average children number:"+getAverageChildrenNumber());
System.out.println("Animals with dominating genome: "+getAnimalsWithDominatingGenome());
public String getSummary(){
return "Current day: " + simulation.getCurrentDay() +
"\nAlive animals: " + getAliveAnimalsNum() +
"\nPlants: " + getPlantsNum() +
"\nAverage energy: " + toTwoDecimalPlaces(getAverageEnergy()) +
"\nAverage children number: " + toTwoDecimalPlaces(getAverageChildrenNumber()) +
"\nAverage life expectancy for dead animals: " + toTwoDecimalPlaces(getAverageLifeExpectancy()) +
"\nDominating genome: " + (getDominatingGenome().isPresent() ? getDominatingGenome().get(): "none")+
"\nAnimals with dominating genome: " + getAnimalsWithDominatingGenome().size();
}
}

0 comments on commit 0d98639

Please sign in to comment.