Skip to content
Snippets Groups Projects
Commit d70fc3ee authored by AxelCarayon's avatar AxelCarayon
Browse files

refactoring to make code more generic

parent 5aef0044
No related branches found
No related tags found
No related merge requests found
Showing
with 390 additions and 44 deletions
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
*.rar *.rar
src/main/resources/output.csv src/main/resources/output.csv
src/main/resources/pythonOutput/*.csv
src/main/resources/pythonOutput/*.png
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid* hs_err_pid*
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly SEIRSState otherwise,
any Contribution intentionally submitted for inclusion in the Work any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions. this License, without any additional terms or conditions.
......
import csv import csv
import yaml
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
OUTPUT_FILE_LOCATION = 'src/main/resources/output.csv'
OUTPUT_FOLDER = 'src/main/resources/pythonOutput'
JAR_LOCATION = 'out/artifacts/SMA_SEIR_jar/SMA-SEIR.jar'
YAML_FILE = 'src/main/resources/parameters.yaml'
def readCSV(fileName): def readCSV(fileName):
with open(fileName, 'r') as csvfile: with open(fileName, 'r') as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
return list(reader) return list(reader)
def showDiagram(data): def getValues() :
with open(YAML_FILE, 'r') as file:
data = yaml.safe_load(file)
incubation = data['incubationRate']
infection = data['infectionRate']
recovery = data['recoveryRate']
looseImmunity = data['looseImmunityRate']
return f"incubationRate : {incubation} InfectionRate : {infection}\n RecoveryRate : {recovery} LooseImmunityRate : {looseImmunity}"
def makeDiagram(fileName):
data = readCSV(fileName)
suceptible = [] suceptible = []
exposed = [] exposed = []
recovred = [] recovred = []
...@@ -18,6 +34,7 @@ def showDiagram(data): ...@@ -18,6 +34,7 @@ def showDiagram(data):
recovred.append(int(row[2])) recovred.append(int(row[2]))
infected.append(int(row[3])) infected.append(int(row[3]))
plt.title(getValues())
plt.plot(suceptible, label='Suceptible', color='gray') plt.plot(suceptible, label='Suceptible', color='gray')
plt.plot(exposed, label='Exposed', color='yellow') plt.plot(exposed, label='Exposed', color='yellow')
plt.plot(infected, label='Infected', color='red') plt.plot(infected, label='Infected', color='red')
...@@ -25,14 +42,36 @@ def showDiagram(data): ...@@ -25,14 +42,36 @@ def showDiagram(data):
plt.xlabel('Cycles') plt.xlabel('Cycles')
plt.ylabel('Peoples') plt.ylabel('Peoples')
plt.legend() plt.legend()
plt.show() plt.savefig(f'{fileName.split(".")[0]}.png')
#plt.show()
plt.close()
def runJavaJar(fileName): def runJavaJar(fileName):
import subprocess import subprocess
subprocess.call(['java', '-jar', fileName]) subprocess.call(['java', '-jar', fileName])
def copyToOutputFolder(fileName):
import shutil
shutil.copy(OUTPUT_FILE_LOCATION, f"{OUTPUT_FOLDER}/{fileName}")
def createFile():
with open(OUTPUT_FILE_LOCATION, 'w') as file:
file.write('')
def editYaml(key,value):
with open(YAML_FILE, 'r') as file:
data = yaml.safe_load(file)
data[key] = value
runJavaJar('out/artifacts/SMA_SEIR_jar/SMA-SEIR.jar') with open(YAML_FILE, 'w') as file:
yaml.dump(data, file)
# data = readCSV("src/main/resources/output.csv") # if __name__ == "__main__":
# for i in range(10):
# editYaml("infectionRate", 0.05+(0.05*i))
# runJavaJar(JAR_LOCATION)
# copyToOutputFolder(f"output{i}.csv")
# makeDiagram(f"{OUTPUT_FOLDER}/output{i}.csv")
# showDiagram(data) runJavaJar(JAR_LOCATION)
\ No newline at end of file makeDiagram(OUTPUT_FILE_LOCATION)
\ No newline at end of file
import agents.RandomWalkingAgent;
import agents.SEIRSAgent;
import agents.states.InfectedSEIRSState;
import environment.SEIRSEnvironment;
import models.Parameters;
import scheduler.FairAsynchronousScheduler;
import scheduler.FairSynchronousScheduler;
import scheduler.Scheduler;
import sma.SEIRS_SMA;
import sma.SMA;
import utils.YamlReader;
import java.awt.*;
import java.util.Random;
public class RunExperiment {
public static void main(String[] args) {
SMA sma = new SEIRS_SMA();
Parameters parameters = YamlReader.getParams();
Random r = new Random(parameters.getSeed());
SEIRSAgent[] agents = new RandomWalkingAgent[parameters.getPopulation()];
Scheduler scheduler;
SEIRSEnvironment environment = new SEIRSEnvironment(parameters.getSize(),agents);
//Populate agents
for (int i = 0; i<parameters.getPopulation();i++) {
Point position = new Point(r.nextInt(parameters.getSize()),r.nextInt(parameters.getSize()));
RandomWalkingAgent agent = new RandomWalkingAgent(position,parameters.getSeed()+i,environment);
agents[i] = agent;
}
//Infect agents
for (int i=0 ; i< parameters.getNbOfPatientZero(); i++) {
SEIRSAgent agent = agents[(r.nextInt(parameters.getPopulation()))];
while (agent.getState() instanceof InfectedSEIRSState) {
agent = agents[(r.nextInt(parameters.getPopulation()))];
}
agent.changeState(new InfectedSEIRSState(agent));
}
//create scheduler
if (parameters.isSynchronousMode()) {
scheduler = new FairSynchronousScheduler(parameters.getSeed());
} else {
scheduler = new FairAsynchronousScheduler();
}
sma.init(environment,scheduler,agents);
sma.run();
}
}
package agents;
public interface Agent {
void wakeUp();
}
package agents;
import java.awt.*;
public interface Agent2D extends Agent {
Point getPosition();
}
package sma.agents; package agents;
import sma.agents.states.InfectedState; import agents.states.InfectedSEIRSState;
import sma.agents.states.State; import agents.states.SEIRSState;
import sma.agents.states.SuceptibleState; import agents.states.SuceptibleSEIRSState;
import sma.environment.Environment; import environment.SquareEnvironment2D;
import sma.environment.SquaredChunksEnvironment; import environment.SEIRSEnvironment;
import utils.YamlReader; import utils.YamlReader;
import java.awt.Point; import java.awt.Point;
import java.util.Random; import java.util.Random;
public class RandomWalkingAgent implements Agent { public class RandomWalkingAgent implements SEIRSAgent {
private Point position; private Point position;
private Random r; private final Random r;
private SquaredChunksEnvironment environment; private final SEIRSEnvironment environment;
private State state; private SEIRSState SEIRSState;
public RandomWalkingAgent(Point position, int seed, SquaredChunksEnvironment environment) { public RandomWalkingAgent(Point position, int seed, SEIRSEnvironment environment) {
this.position = position; this.position = position;
this.state = new SuceptibleState(this); this.SEIRSState = new SuceptibleSEIRSState(this);
this.environment = environment; this.environment = environment;
this.r = new Random(seed); this.r = new Random(seed);
} }
public void move() { private void move() {
state.onMovement(); SEIRSState.onMovement();
int move = r.nextInt(4); int move = r.nextInt(4);
Point newPosition = switch (move) { Point newPosition = switch (move) {
case Environment.LEFT -> new Point(position.x-environment.RADIUS,position.y); case SquareEnvironment2D.LEFT -> new Point(position.x- SEIRSEnvironment.RADIUS,position.y);
case Environment.RIGHT -> new Point(position.x+environment.RADIUS,position.y); case SquareEnvironment2D.RIGHT -> new Point(position.x+ SEIRSEnvironment.RADIUS,position.y);
case Environment.UP -> new Point(position.x,position.y-environment.RADIUS); case SquareEnvironment2D.UP -> new Point(position.x,position.y- SEIRSEnvironment.RADIUS);
case Environment.DOWN -> new Point(position.x,position.y+environment.RADIUS); case SquareEnvironment2D.DOWN -> new Point(position.x,position.y+ SEIRSEnvironment.RADIUS);
default -> throw new IllegalStateException("Unexpected value: " + move); default -> throw new IllegalStateException("Unexpected value: " + move);
}; };
if (newPosition.x <= environment.size-1 && newPosition.x >= 0 && newPosition.y <= environment.size-1 && newPosition.y >=0 ) { if (newPosition.x <= environment.getSize()-1 && newPosition.x >= 0 && newPosition.y <= environment.getSize()-1 && newPosition.y >=0 ) {
environment.notifyNewPosition(position,newPosition,this); environment.notifyNewPosition(position,newPosition ,this);
position = newPosition; position = newPosition;
} }
} }
@Override @Override
public void changeState(State state) { this.state = state; } public void wakeUp() {
move();
}
@Override
public void changeState(SEIRSState SEIRSState) { this.SEIRSState = SEIRSState; }
@Override @Override
public boolean isExposed() { public boolean isExposed() {
boolean isExposed = false; boolean isExposed = false;
for (Agent neighbor: environment.getNeighbors(position)) { for (SEIRSAgent neighbor: environment.getNeighbors(position)) {
if (neighbor.getState() instanceof InfectedState) { if ((neighbor).getState() instanceof InfectedSEIRSState) {
int roll = r.nextInt(100)+1; int roll = r.nextInt(10000)+1;
if (roll <= YamlReader.getParams().getInfectionRate()*100) { if (roll <= YamlReader.getParams().getInfectionRate()*10000) {
isExposed = true; isExposed = true;
} }
} }
...@@ -60,8 +66,8 @@ public class RandomWalkingAgent implements Agent { ...@@ -60,8 +66,8 @@ public class RandomWalkingAgent implements Agent {
@Override @Override
public boolean isInfected() { public boolean isInfected() {
boolean isSick = false; boolean isSick = false;
int roll = r.nextInt(100)+1; int roll = r.nextInt(10000)+1;
if (roll <= YamlReader.getParams().getIncubationRate()*100) { if (roll <= YamlReader.getParams().getIncubationRate()*10000) {
isSick = true; isSick = true;
} }
return isSick; return isSick;
...@@ -70,8 +76,8 @@ public class RandomWalkingAgent implements Agent { ...@@ -70,8 +76,8 @@ public class RandomWalkingAgent implements Agent {
@Override @Override
public boolean isRecovered() { public boolean isRecovered() {
boolean isHealed = false; boolean isHealed = false;
int roll = r.nextInt(100)+1; int roll = r.nextInt(10000)+1;
if (roll <= YamlReader.getParams().getRecoveryRate()*100) { if (roll <= YamlReader.getParams().getRecoveryRate()*10000) {
isHealed = true; isHealed = true;
} }
return isHealed; return isHealed;
...@@ -80,15 +86,15 @@ public class RandomWalkingAgent implements Agent { ...@@ -80,15 +86,15 @@ public class RandomWalkingAgent implements Agent {
@Override @Override
public boolean hasLostImmunity() { public boolean hasLostImmunity() {
boolean hasLostImmunity = false; boolean hasLostImmunity = false;
int roll = r.nextInt(100)+1; int roll = r.nextInt(10000)+1;
if (roll <= YamlReader.getParams().getLooseImmunityRate()*100) { if (roll <= YamlReader.getParams().getLooseImmunityRate()*10000) {
hasLostImmunity = true; hasLostImmunity = true;
} }
return hasLostImmunity; return hasLostImmunity;
} }
@Override @Override
public State getState() { return this.state; } public SEIRSState getState() { return this.SEIRSState; }
@Override @Override
public Point getPosition() { return position; } public Point getPosition() { return position; }
......
package sma.agents; package agents;
import sma.agents.states.State; import agents.states.SEIRSState;
import java.awt.*; public interface SEIRSAgent extends Agent2D {
public interface Agent { void changeState(SEIRSState SEIRSState);
SEIRSState getState();
void changeState(State state);
State getState();
boolean isExposed(); boolean isExposed();
boolean isInfected(); boolean isInfected();
boolean isRecovered(); boolean isRecovered();
boolean hasLostImmunity(); boolean hasLostImmunity();
void move();
Point getPosition();
} }
package sma.agents.states; package agents.states;
import sma.agents.Agent; public class ExposedSEIRSState extends SEIRSState {
public class ExposedState extends State{ public ExposedSEIRSState(agents.SEIRSAgent SEIRSAgent) {
super(SEIRSAgent);
public ExposedState(Agent agent) {
super(agent);
} }
@Override @Override
public void onMovement() { public void onMovement() {
if (agent.isInfected()) { if (agent.isInfected()) {
agent.changeState(new InfectedState(agent)); agent.changeState(new InfectedSEIRSState(agent));
} }
} }
......
package sma.agents.states; package agents.states;
import sma.agents.Agent; public class InfectedSEIRSState extends SEIRSState {
public class InfectedState extends State{ public InfectedSEIRSState(agents.SEIRSAgent SEIRSAgent) {
super(SEIRSAgent);
public InfectedState(Agent agent) {
super(agent);
} }
@Override @Override
public void onMovement() { public void onMovement() {
if (agent.isRecovered()) { if (agent.isRecovered()) {
agent.changeState(new RecoveredState(agent)); agent.changeState(new RecoveredSEIRSState(agent));
} }
} }
......
package sma.agents.states; package agents.states;
import sma.agents.Agent; import agents.SEIRSAgent;
public class RecoveredState extends State{ public class RecoveredSEIRSState extends SEIRSState {
public RecoveredState(Agent agent) { public RecoveredSEIRSState(SEIRSAgent SEIRSAgent) {
super(agent); super(SEIRSAgent);
} }
@Override @Override
public void onMovement() { public void onMovement() {
if (agent.hasLostImmunity()) { if (agent.hasLostImmunity()) {
agent.changeState(new SuceptibleState(agent)); agent.changeState(new SuceptibleSEIRSState(agent));
} }
} }
......
package sma.agents.states; package agents.states;
import sma.agents.Agent; import agents.SEIRSAgent;
public abstract class State { public abstract class SEIRSState {
public final static String EXPOSED = "EXPOSED"; public final static String EXPOSED = "EXPOSED";
public final static String INFECTED = "INFECTED"; public final static String INFECTED = "INFECTED";
public final static String SUCEPTIBLE = "SUCEPTIBLE"; public final static String SUCEPTIBLE = "SUCEPTIBLE";
public final static String RECOVERED = "RECOVERED"; public final static String RECOVERED = "RECOVERED";
protected Agent agent; protected final agents.SEIRSAgent agent;
State(Agent agent) { SEIRSState(SEIRSAgent agent) {
this.agent = agent; this.agent = agent;
} }
......
package sma.agents.states; package agents.states;
import sma.agents.Agent; public class SuceptibleSEIRSState extends SEIRSState {
import java.awt.*; public SuceptibleSEIRSState(agents.SEIRSAgent SEIRSAgent) {
super(SEIRSAgent);
public class SuceptibleState extends State{
public SuceptibleState(Agent agent) {
super(agent);
} }
@Override @Override
public void onMovement() { public void onMovement() {
if (agent.isExposed()) { if (agent.isExposed()) {
agent.changeState(new ExposedState(agent)); agent.changeState(new ExposedSEIRSState(agent));
} }
} }
......
package environment;
public interface Environment {
}
package environment;
import agents.Agent;
import java.awt.*;
public interface Environment2D extends Environment {
void notifyNewPosition(Point oldPosition, Point newPosition, Agent agent);
}
package sma.environment; package environment;
import sma.agents.Agent; import agents.Agent;
import sma.agents.states.State; import agents.SEIRSAgent;
import agents.states.SEIRSState;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
public class SquaredChunksEnvironment implements Environment { @SuppressWarnings("unchecked")
public class SEIRSEnvironment implements SquareEnvironment2D {
public final static int RADIUS = 10; public final static int RADIUS = 10;
public final static int CHUNK_SIZE = 2*RADIUS; public final static int CHUNK_SIZE = 2*RADIUS;
public int size; public final int size;
private Agent[] agents; private final SEIRSAgent[] agents;
private List<Agent>[][] chunks; private List<SEIRSAgent>[][] chunks;
public SquaredChunksEnvironment(int size, Agent[] agents) { public SEIRSEnvironment(int size, SEIRSAgent[] agents) {
this.agents = agents; this.agents = agents;
this.size = size; this.size = size;
} }
...@@ -29,7 +31,7 @@ public class SquaredChunksEnvironment implements Environment { ...@@ -29,7 +31,7 @@ public class SquaredChunksEnvironment implements Environment {
chunks[i][j] = new ArrayList<>(); chunks[i][j] = new ArrayList<>();
} }
} }
for (Agent agent : agents) { for (SEIRSAgent agent : agents) {
int x = agent.getPosition().x/CHUNK_SIZE; int x = agent.getPosition().x/CHUNK_SIZE;
int y = agent.getPosition().y/CHUNK_SIZE; int y = agent.getPosition().y/CHUNK_SIZE;
chunks[x][y].add(agent); chunks[x][y].add(agent);
...@@ -57,12 +59,12 @@ public class SquaredChunksEnvironment implements Environment { ...@@ -57,12 +59,12 @@ public class SquaredChunksEnvironment implements Environment {
}; };
} }
private List<Agent> getChunkNeighbors(int relativeTo, Point p) { private List<SEIRSAgent> getChunkNeighbors(int relativeTo, Point p) {
Point newPosition = getRelativePoint(relativeTo,p); Point newPosition = getRelativePoint(relativeTo,p);
Point chunk = new Point(newPosition.x/CHUNK_SIZE,newPosition.y/CHUNK_SIZE); Point chunk = new Point(newPosition.x/CHUNK_SIZE,newPosition.y/CHUNK_SIZE);
var neighbors = new ArrayList<Agent>(); List<SEIRSAgent> neighbors = new ArrayList<>();
try{ try{
for (Agent agent : chunks[chunk.x][chunk.y]) { for (SEIRSAgent agent : chunks[chunk.x][chunk.y]) {
if (detectCollision(p, agent.getPosition())) { if (detectCollision(p, agent.getPosition())) {
neighbors.add(agent); neighbors.add(agent);
} }
...@@ -73,12 +75,11 @@ public class SquaredChunksEnvironment implements Environment { ...@@ -73,12 +75,11 @@ public class SquaredChunksEnvironment implements Environment {
return neighbors; return neighbors;
} }
@Override public List<SEIRSAgent> getNeighbors(Point position) {
public List<Agent> getNeighbors(Point position) {
if (chunks == null) { if (chunks == null) {
throw new IllegalStateException("Chunks aren't initialized, you should use the initiateMethod() first."); throw new IllegalStateException("Chunks aren't initialized, you should use the initiateMethod() first.");
} }
var neighbors = new ArrayList<Agent>(); var neighbors = new ArrayList<SEIRSAgent>();
for (int i = 0; i < MAX_CHUNK; i++) { for (int i = 0; i < MAX_CHUNK; i++) {
neighbors.addAll(getChunkNeighbors(i,position)); neighbors.addAll(getChunkNeighbors(i,position));
...@@ -86,30 +87,33 @@ public class SquaredChunksEnvironment implements Environment { ...@@ -86,30 +87,33 @@ public class SquaredChunksEnvironment implements Environment {
return neighbors; return neighbors;
} }
@Override
public void notifyNewPosition(Point oldPosition, Point newPosition, Agent agent) { public void notifyNewPosition(Point oldPosition, Point newPosition, Agent agent) {
if (chunks == null) { if (chunks == null) {
throw new IllegalStateException("Chunks aren't initialized, you should use the initiateMethod() first."); throw new IllegalStateException("Chunks aren't initialized, you should use the initiateMethod() first.");
} }
if (oldPosition.x/CHUNK_SIZE != newPosition.x/CHUNK_SIZE || oldPosition.y/CHUNK_SIZE != newPosition.y/CHUNK_SIZE) { if (oldPosition.x/CHUNK_SIZE != newPosition.x/CHUNK_SIZE || oldPosition.y/CHUNK_SIZE != newPosition.y/CHUNK_SIZE) {
chunks[oldPosition.x/CHUNK_SIZE][oldPosition.y/CHUNK_SIZE].remove(agent); chunks[oldPosition.x/CHUNK_SIZE][oldPosition.y/CHUNK_SIZE].remove((SEIRSAgent) agent);
chunks[newPosition.x/CHUNK_SIZE][newPosition.y/CHUNK_SIZE].add(agent); chunks[newPosition.x/CHUNK_SIZE][newPosition.y/CHUNK_SIZE].add((SEIRSAgent) agent);
} }
} }
@Override
public HashMap<String,Integer> getAgentStatus() { public HashMap<String,Integer> getAgentStatus() {
var map = new HashMap<String,Integer>(); var map = new HashMap<String,Integer>();
map.put(State.EXPOSED,0); map.put(SEIRSState.EXPOSED,0);
map.put(State.INFECTED,0); map.put(SEIRSState.INFECTED,0);
map.put(State.RECOVERED,0); map.put(SEIRSState.RECOVERED,0);
map.put(State.SUCEPTIBLE,0); map.put(SEIRSState.SUCEPTIBLE,0);
for (Agent agent : agents) { for (SEIRSAgent SEIRSAgent : agents) {
String state = agent.getState().toString(); String state = SEIRSAgent.getState().toString();
map.put(state,map.get(state)+1); map.put(state,map.get(state)+1);
} }
return map; return map;
} }
@Override
public int getSize() {
return size;
}
} }
package sma.environment; package environment;
import sma.agents.Agent; public interface SquareEnvironment2D extends Environment2D {
import java.awt.Point;
import java.util.HashMap;
import java.util.List;
public interface Environment {
int LEFT = 0; int LEFT = 0;
int RIGHT = 1; int RIGHT = 1;
int UP = 2; int UP = 2;
...@@ -18,7 +12,5 @@ public interface Environment { ...@@ -18,7 +12,5 @@ public interface Environment {
int DOWN_RIGHT = 8; int DOWN_RIGHT = 8;
int MAX_CHUNK = 9; int MAX_CHUNK = 9;
List<Agent> getNeighbors(Point position); int getSize();
void notifyNewPosition(Point oldPosition, Point newPosition, Agent agent);
HashMap<String,Integer> getAgentStatus();
} }
package models; package models;
@SuppressWarnings("unused")
public class Parameters { public class Parameters {
private int seed; private int seed;
......
package scheduler;
public abstract class AsynchronousScheduler implements Scheduler {
}
package sma.scheduler; package scheduler;
import sma.agents.Agent; import agents.Agent;
import sma.agents.RandomWalkingAgent;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -10,17 +9,19 @@ import java.util.concurrent.*; ...@@ -10,17 +9,19 @@ import java.util.concurrent.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class FairAsynchronousScheduler implements Scheduler{ public class FairAsynchronousScheduler extends AsynchronousScheduler {
private ExecutorService executor = Executors.newSingleThreadExecutor(); private final ExecutorService executor = Executors.newSingleThreadExecutor();
private Queue<Agent> queue; private Queue<Agent> queue;
public FairAsynchronousScheduler(Agent[] agents) { @Override
public void init(Agent[] agents) {
this.queue = new ConcurrentLinkedQueue<>(Arrays.stream(agents).toList()); this.queue = new ConcurrentLinkedQueue<>(Arrays.stream(agents).toList());
} }
public void nextCycle() { @Override
List<Future<Agent>> results = queue.parallelStream().map(agent -> executor.submit(() -> {agent.move(); return agent;})).toList(); public void doNextCycle() {
List<Future<Agent>> results = queue.parallelStream().map(agent -> executor.submit(() -> {agent.wakeUp(); return agent;})).toList();
Function<Future<Agent>, Agent> futureTreatment = futureAgent -> { Function<Future<Agent>, Agent> futureTreatment = futureAgent -> {
try { try {
return futureAgent.get(); return futureAgent.get();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment