From a8a5689784c0beb4e9ef9538e8343f3dd5505b6a Mon Sep 17 00:00:00 2001 From: BrunoDatoMeneses <bruno.dato.meneses@gmail.com> Date: Tue, 17 Sep 2019 14:30:44 +0200 Subject: [PATCH] Revert "DEL: to delete" This reverts commit 6fb8d526633649fc9624168ed8236a59ffdf7038. --- AMAKFX/src/fr/irit/smac/amak/Agent.java | 9 +- AMAKFX/src/fr/irit/smac/amak/Amas.java | 21 +- .../fr/irit/smac/amak/CommunicatingAgent.java | 2 +- AMAKFX/src/fr/irit/smac/amak/Environment.java | 295 +++-- AMAKFX/src/fr/irit/smac/amak/Scheduler.java | 690 +++++----- .../philosophers/PhilosopherExample.java | 398 +++--- .../philosophers/PhilosophersAMASExample.java | 153 ++- .../PhilosophersLaunchExample.java | 20 +- .../examples/philosophers/TableExample.java | 48 +- .../amak/examples/randomants/AntExample.java | 178 ++- .../examples/randomants/AntHillExample.java | 72 +- .../randomants/AntsLaunchExample.java | 13 +- .../randomants/AntsLaunchExampleMultiUI.java | 59 - .../examples/randomants/WorldExample.java | 59 +- .../fr/irit/smac/amak/tests/AsyncTest.java | 178 ++- .../amak/tests/CommandLineOnlyResolution.java | 80 +- AMAKFX/src/fr/irit/smac/amak/tests/Order.java | 122 +- .../irit/smac/amak/tests/ScalibilityTest.java | 196 +-- .../fr/irit/smac/amak/tests/VisibleUI.java | 27 +- .../smac/amak/tests/executionorder/Test.java | 164 +-- AMAKFX/src/fr/irit/smac/amak/ui/AmakPlot.java | 34 +- .../src/fr/irit/smac/amak/ui/AmasWindow.java | 266 ---- AMAKFX/src/fr/irit/smac/amak/ui/VUI.java | 1154 ++++++++--------- .../agent/TestAgentTwoPhaseScheduling.java | 2 +- .../testutils/ObjectsForAgentTesting.java | 4 +- 25 files changed, 1925 insertions(+), 2319 deletions(-) delete mode 100644 AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExampleMultiUI.java delete mode 100644 AMAKFX/src/fr/irit/smac/amak/ui/AmasWindow.java diff --git a/AMAKFX/src/fr/irit/smac/amak/Agent.java b/AMAKFX/src/fr/irit/smac/amak/Agent.java index d67c8b8f..9685e065 100644 --- a/AMAKFX/src/fr/irit/smac/amak/Agent.java +++ b/AMAKFX/src/fr/irit/smac/amak/Agent.java @@ -8,8 +8,6 @@ import java.util.Map.Entry; import fr.irit.smac.amak.Amas.ExecutionPolicy; import fr.irit.smac.amak.tools.Log; -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; /** * This class must be overridden by all agents @@ -22,10 +20,6 @@ import fr.irit.smac.amak.ui.MainWindow; * The kind of Environment the agent AND the Amas refer to */ public abstract class Agent<A extends Amas<E>, E extends Environment> implements Runnable { - - public AmasWindow amasWindow; - - /** * Neighborhood of the agent (must refer to the same couple amas, environment */ @@ -109,8 +103,7 @@ public abstract class Agent<A extends Amas<E>, E extends Environment> implements * @param params * The params to initialize the agent */ - public Agent(AmasWindow window, A amas, Object... params) { - this.amasWindow = window; + public Agent(A amas, Object... params) { this.id = uniqueIndex++; this.params = params; this.amas = amas; diff --git a/AMAKFX/src/fr/irit/smac/amak/Amas.java b/AMAKFX/src/fr/irit/smac/amak/Amas.java index 6dcfd7c9..a73d0e51 100644 --- a/AMAKFX/src/fr/irit/smac/amak/Amas.java +++ b/AMAKFX/src/fr/irit/smac/amak/Amas.java @@ -13,7 +13,6 @@ import java.util.stream.Collectors; import fr.irit.smac.amak.tools.Log; import fr.irit.smac.amak.tools.RunLaterHelper; -import fr.irit.smac.amak.ui.AmasWindow; import fr.irit.smac.amak.ui.MainWindow; import fr.irit.smac.amak.ui.SchedulerToolbar; import fr.irit.smac.amak.ui.VUI; @@ -27,9 +26,6 @@ import fr.irit.smac.amak.ui.VUI; * The environment of the MAS */ public class Amas<E extends Environment> implements Schedulable { - - public AmasWindow amasWindow; - /** * List of agents present in the system */ @@ -133,20 +129,17 @@ public class Amas<E extends Environment> implements Schedulable { * @param params * The params to initialize the amas */ - public Amas(AmasWindow window, E environment, Scheduling scheduling, Object... params) { - amasWindow = window; + public Amas(E environment, Scheduling scheduling, Object... params) { executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Configuration.allowedSimultaneousAgentsExecution); if (scheduling == Scheduling.DEFAULT) { -// System.out.println("Amas"); -// mainWindow.instance(); - this.scheduler = new Scheduler(amasWindow); - this.scheduler = this.scheduler.getDefaultScheduler(amasWindow); + MainWindow.instance(); + this.scheduler = Scheduler.getDefaultScheduler(); this.scheduler.add(this); } else { - this.scheduler = new Scheduler(amasWindow, this); + this.scheduler = new Scheduler(this); if (scheduling == Scheduling.UI && !Configuration.commandLineMode) { - //amasWindow.instance(); - amasWindow.addToolbar(new SchedulerToolbar("Amas #" + id, getScheduler())); + MainWindow.instance(); + MainWindow.addToolbar(new SchedulerToolbar("Amas #" + id, getScheduler())); } } this.scheduler.lock(); @@ -378,7 +371,7 @@ public class Amas<E extends Environment> implements Schedulable { * {@link Amas#onRenderingInitialization} */ protected void onUpdateRender() { - VUI.get(amasWindow).updateCanvas(); + VUI.get().updateCanvas(); } /** diff --git a/AMAKFX/src/fr/irit/smac/amak/CommunicatingAgent.java b/AMAKFX/src/fr/irit/smac/amak/CommunicatingAgent.java index bac17a3d..b0f2b5a3 100644 --- a/AMAKFX/src/fr/irit/smac/amak/CommunicatingAgent.java +++ b/AMAKFX/src/fr/irit/smac/amak/CommunicatingAgent.java @@ -84,7 +84,7 @@ public abstract class CommunicatingAgent<A extends Amas<E>, E extends Environmen * The strategy of messaging reader. */ public CommunicatingAgent(A amas, IMessagingReader msgReader, Object... params) { - super(null,amas, params); + super(amas, params); // build the address... final String randomUUID = getRawID(params); IAmakAddress address = messagingService.getOrCreateAmakAddress(randomUUID); diff --git a/AMAKFX/src/fr/irit/smac/amak/Environment.java b/AMAKFX/src/fr/irit/smac/amak/Environment.java index 1461349c..68433e45 100644 --- a/AMAKFX/src/fr/irit/smac/amak/Environment.java +++ b/AMAKFX/src/fr/irit/smac/amak/Environment.java @@ -1,150 +1,145 @@ -package fr.irit.smac.amak; - -import java.util.Random; - -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.SchedulerToolbar; - -/** - * This class must be overridden by environments - * - * @author Alexandre Perles - * - */ -public abstract class Environment implements Schedulable { - - public AmasWindow amasWindow; - - /** - * Unique index to give unique id to each environment - */ - private static int uniqueIndex; - - /** - * The id of the environment - */ - private final int id = uniqueIndex++; - - /** - * The parameters that are passed to {@link Environment#onInitialization()} - */ - protected Object[] params; - /** - * Random object common to the amas - */ - private Random random = new Random(); - /** - * The scheduler of the environment - */ - private Scheduler scheduler; - - /** - * Constructor - * - * @param _scheduling - * The scheduling of the environment - * @param params - * The parameters to initialize the environment - */ - public Environment(AmasWindow window, Scheduling _scheduling, Object... params) { - amasWindow = window; - if (_scheduling == Scheduling.DEFAULT) { - this.scheduler = new Scheduler(amasWindow); - this.scheduler = this.scheduler.getDefaultScheduler(amasWindow); - this.scheduler.add(this); - } else { - this.scheduler = new Scheduler(amasWindow,this); - if (_scheduling == Scheduling.UI && !Configuration.commandLineMode) - amasWindow.addToolbar(new SchedulerToolbar("Environment #" + id, getScheduler())); - } - this.scheduler.lock(); - this.params = params; - onInitialization(); - onInitialEntitiesCreation(); - if (!Configuration.commandLineMode) - onRenderingInitialization(); - this.scheduler.unlock(); - } - - /** - * Override this method is you wish to render environment. For example, you can - * use this method to create a VUI drawable object. - */ - private void onRenderingInitialization() { - } - - /** - * Getter for the scheduler - * - * @return the scheduler - */ - public Scheduler getScheduler() { - return scheduler; - } - - /** - * Set the seed for the common random object. This method should be called at - * the very beginning of the initialization process - * - * @param _seed - * The seed to initialize the random object - */ - public void setSeed(long _seed) { - random = new Random(_seed); - } - - /** - * This method is called during the initialization process of the environment - */ - public void onInitialization() { - } - - /** - * This method is called after the initialization process of the environment to - * create entities - */ - public void onInitialEntitiesCreation() { - } - - /** - * This method is called at each cycle of the environment - */ - public void onCycle() { - } - - @Override - public boolean stopCondition() { - return false; - } - - @Override - public final void cycle() { - onCycle(); - if (!Configuration.commandLineMode) - onUpdateRender(); - } - - /** - * Override this method to update rendering related to the environment - */ - protected void onUpdateRender() { - } - - /** - * Getter for the random object - * - * @return the random object - */ - public Random getRandom() { - return random; - } - - @Override - public void onSchedulingStarts() { - } - - @Override - public void onSchedulingStops() { - } -} +package fr.irit.smac.amak; + +import java.util.Random; + +import fr.irit.smac.amak.ui.MainWindow; +import fr.irit.smac.amak.ui.SchedulerToolbar; + +/** + * This class must be overridden by environments + * + * @author Alexandre Perles + * + */ +public abstract class Environment implements Schedulable { + + /** + * Unique index to give unique id to each environment + */ + private static int uniqueIndex; + + /** + * The id of the environment + */ + private final int id = uniqueIndex++; + + /** + * The parameters that are passed to {@link Environment#onInitialization()} + */ + protected Object[] params; + /** + * Random object common to the amas + */ + private Random random = new Random(); + /** + * The scheduler of the environment + */ + private Scheduler scheduler; + + /** + * Constructor + * + * @param _scheduling + * The scheduling of the environment + * @param params + * The parameters to initialize the environment + */ + public Environment(Scheduling _scheduling, Object... params) { + if (_scheduling == Scheduling.DEFAULT) { + this.scheduler = Scheduler.getDefaultScheduler(); + this.scheduler.add(this); + } else { + this.scheduler = new Scheduler(this); + if (_scheduling == Scheduling.UI && !Configuration.commandLineMode) + MainWindow.addToolbar(new SchedulerToolbar("Environment #" + id, getScheduler())); + } + this.scheduler.lock(); + this.params = params; + onInitialization(); + onInitialEntitiesCreation(); + if (!Configuration.commandLineMode) + onRenderingInitialization(); + this.scheduler.unlock(); + } + + /** + * Override this method is you wish to render environment. For example, you can + * use this method to create a VUI drawable object. + */ + private void onRenderingInitialization() { + } + + /** + * Getter for the scheduler + * + * @return the scheduler + */ + public Scheduler getScheduler() { + return scheduler; + } + + /** + * Set the seed for the common random object. This method should be called at + * the very beginning of the initialization process + * + * @param _seed + * The seed to initialize the random object + */ + public void setSeed(long _seed) { + random = new Random(_seed); + } + + /** + * This method is called during the initialization process of the environment + */ + public void onInitialization() { + } + + /** + * This method is called after the initialization process of the environment to + * create entities + */ + public void onInitialEntitiesCreation() { + } + + /** + * This method is called at each cycle of the environment + */ + public void onCycle() { + } + + @Override + public boolean stopCondition() { + return false; + } + + @Override + public final void cycle() { + onCycle(); + if (!Configuration.commandLineMode) + onUpdateRender(); + } + + /** + * Override this method to update rendering related to the environment + */ + protected void onUpdateRender() { + } + + /** + * Getter for the random object + * + * @return the random object + */ + public Random getRandom() { + return random; + } + + @Override + public void onSchedulingStarts() { + } + + @Override + public void onSchedulingStops() { + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/Scheduler.java b/AMAKFX/src/fr/irit/smac/amak/Scheduler.java index 09dc4808..bffeeb2c 100644 --- a/AMAKFX/src/fr/irit/smac/amak/Scheduler.java +++ b/AMAKFX/src/fr/irit/smac/amak/Scheduler.java @@ -1,349 +1,341 @@ -package fr.irit.smac.amak; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; - -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.SchedulerToolbar; - -/** - * A scheduler associated to a MAS - * - * @author Alexandre Perles - * - */ -public class Scheduler implements Runnable, Serializable { - - public AmasWindow amasWindow; - - /** - * Unique ID meant to handle serialization correctly - */ - private static final long serialVersionUID = -4765899565369100376L; - /** - * The schedulables object handled by the scheduler - */ - private final Set<Schedulable> schedulables = new LinkedHashSet<>(); - /** - * The state of the scheduler {@link State} - */ - private State state; - /** - * The sleep time in ms between each cycle - */ - private int sleep; - /** - * A lock to protect the state - */ - private final ReentrantLock stateLock = new ReentrantLock(); - /** - * Method that is called when the scheduler stops - */ - private Consumer<Scheduler> onStop; - /** - * The methods called when the speed is changed. Useful to change the value of - * the GUI slider of {@link SchedulerToolbar} - */ - private List<Consumer<Scheduler>> onChange = new ArrayList<>(); - /** - * The idea is to prevent scheduler from launching if the schedulables are not - * yet fully ready - */ - private int locked = 0; - /** - * The default scheduler - */ - private static Scheduler defaultScheduler; - /** - * The schedulables that must be added - */ - private Queue<Schedulable> pendingAdditionSchedulables = new LinkedList<>(); - /** - * The schedulables that must be removed - */ - private Queue<Schedulable> pendingRemovalSchedulables = new LinkedList<>(); - - /** - * State of the scheduler - * - */ - public enum State { - /** - * The scheduler is running - */ - RUNNING, - /** - * The scheduler is paused - */ - IDLE, - /** - * The scheduler is expected to stop at the end at the current cycle - */ - PENDING_STOP - - } - - /** - * Constructor which set the initial state and auto start if requested - * - * @param _schedulables - * the corresponding schedulables - */ - public Scheduler(AmasWindow window, Schedulable... _schedulables) { - amasWindow = window; - - - for (Schedulable schedulable : _schedulables) { - this.add(schedulable); - } - this.state = State.IDLE; - } - - /** - * Create or return the default scheduler - * - * @return The default scheduler - */ - public Scheduler getDefaultScheduler(AmasWindow window) { - amasWindow = window; - if (defaultScheduler == null) { - defaultScheduler = new Scheduler(amasWindow); - if (!Configuration.commandLineMode) { -// System.out.println("getDefaultScheduler"); -// mainWindow.instance(); - SchedulerToolbar st = new SchedulerToolbar("Default", defaultScheduler); - amasWindow.addToolbar(st); - } - } - return defaultScheduler; - } - - /** - * Set the delay between two cycles and launch the scheduler if it is not - * running - * - * @param i - * the delay between two cycles - */ - public void startWithSleep(int i) { - if (locked > 0) { - - synchronized (onChange) { - onChange.forEach(c -> c.accept(this)); - } - return; - } - setSleep(i); - stateLock.lock(); - switch (state) { - case IDLE: - state = State.RUNNING; - new Thread(this).start(); - break; - default: - break; - } - stateLock.unlock(); - synchronized (onChange) { - onChange.forEach(c -> c.accept(this)); - } - } - - /** - * Start (or continue) with no delay between cycles - */ - public void start() { - startWithSleep(Schedulable.DEFAULT_SLEEP); - } - - /** - * Execute one cycle - */ - public void step() { - if (locked > 0) { - synchronized (onChange) { - onChange.forEach(c -> c.accept(this)); - } - return; - } - this.setSleep(0); - stateLock.lock(); - switch (state) { - case IDLE: - state = State.PENDING_STOP; - new Thread(this).start(); - break; - default: - break; - - } - stateLock.unlock(); - synchronized (onChange) { - onChange.forEach(c -> c.accept(this)); - } - } - - /** - * Stop the scheduler if it is running - */ - public void stop() { - stateLock.lock(); - switch (state) { - case RUNNING: - state = State.PENDING_STOP; - break; - default: - break; - - } - stateLock.unlock(); - synchronized (onChange) { - onChange.forEach(c -> c.accept(this)); - } - } - - /** - * Threaded run method - */ - @Override - public void run() { - treatPendingSchedulables(); - for (Schedulable schedulable : schedulables) { - schedulable.onSchedulingStarts(); - } - boolean mustStop; - do { - for (Schedulable schedulable : schedulables) { - schedulable.cycle(); - } - if (getSleep() != 0) { - try { - Thread.sleep(getSleep()); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - mustStop = false; - for (Schedulable schedulable : schedulables) { - mustStop |= schedulable.stopCondition(); - } - } while (state == State.RUNNING && !mustStop); - stateLock.lock(); - state = State.IDLE; - stateLock.unlock(); - - for (Schedulable schedulable : schedulables) { - schedulable.onSchedulingStops(); - } - treatPendingSchedulables(); - if (onStop != null) - onStop.accept(this); - } - - /** - * Effectively Add or Remove the schedulables that were added or removed during - * a cycle to avoid {@link ConcurrentModificationException} - */ - private void treatPendingSchedulables() { - while (!pendingAdditionSchedulables.isEmpty()) - schedulables.add(pendingAdditionSchedulables.poll()); - while (!pendingRemovalSchedulables.isEmpty()) - schedulables.remove(pendingRemovalSchedulables.poll()); - - } - - /** - * Set the method that must be executed when the system is stopped - * - * @param _onStop - * Consumer method - */ - public final void setOnStop(Consumer<Scheduler> _onStop) { - this.onStop = _onStop; - } - - /** - * Add a method that must be executed when the scheduler speed is changed - * - * @param _onChange - * Consumer method - */ - public final void addOnChange(Consumer<Scheduler> _onChange) { - synchronized (onChange) { - this.onChange.add(_onChange); - } - } - - /** - * Is the scheduler running ? - * - * @return true if the scheduler is running - */ - public boolean isRunning() { - return state == State.RUNNING; - } - - /** - * Getter for the sleep time - * - * @return the sleep time - */ - - public int getSleep() { - return sleep; - } - - /** - * Setter for the sleep time - * - * @param sleep - * The time between each cycle - */ - public void setSleep(int sleep) { - this.sleep = sleep; - } - - /** - * Plan to add a schedulable - * - * @param _schedulable - * the schedulable to add - */ - public void add(Schedulable _schedulable) { - this.pendingAdditionSchedulables.add(_schedulable); - } - - /** - * Plan to remove a schedulable - * - * @param _schedulable - * the schedulable to remove - */ - public void remove(Schedulable _schedulable) { - this.pendingRemovalSchedulables.add(_schedulable); - } - - /** - * Soft lock the scheduler to avoid a too early running - */ - public void lock() { - locked++; - } - - /** - * Soft unlock the scheduler to avoid a too early running - */ - public void unlock() { - locked--; - } - -} +package fr.irit.smac.amak; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; + +import fr.irit.smac.amak.ui.MainWindow; +import fr.irit.smac.amak.ui.SchedulerToolbar; + +/** + * A scheduler associated to a MAS + * + * @author Alexandre Perles + * + */ +public class Scheduler implements Runnable, Serializable { + /** + * Unique ID meant to handle serialization correctly + */ + private static final long serialVersionUID = -4765899565369100376L; + /** + * The schedulables object handled by the scheduler + */ + private final Set<Schedulable> schedulables = new LinkedHashSet<>(); + /** + * The state of the scheduler {@link State} + */ + private State state; + /** + * The sleep time in ms between each cycle + */ + private int sleep; + /** + * A lock to protect the state + */ + private final ReentrantLock stateLock = new ReentrantLock(); + /** + * Method that is called when the scheduler stops + */ + private Consumer<Scheduler> onStop; + /** + * The methods called when the speed is changed. Useful to change the value of + * the GUI slider of {@link SchedulerToolbar} + */ + private List<Consumer<Scheduler>> onChange = new ArrayList<>(); + /** + * The idea is to prevent scheduler from launching if the schedulables are not + * yet fully ready + */ + private int locked = 0; + /** + * The default scheduler + */ + private static Scheduler defaultScheduler; + /** + * The schedulables that must be added + */ + private Queue<Schedulable> pendingAdditionSchedulables = new LinkedList<>(); + /** + * The schedulables that must be removed + */ + private Queue<Schedulable> pendingRemovalSchedulables = new LinkedList<>(); + + /** + * State of the scheduler + * + */ + public enum State { + /** + * The scheduler is running + */ + RUNNING, + /** + * The scheduler is paused + */ + IDLE, + /** + * The scheduler is expected to stop at the end at the current cycle + */ + PENDING_STOP + + } + + /** + * Constructor which set the initial state and auto start if requested + * + * @param _schedulables + * the corresponding schedulables + */ + public Scheduler(Schedulable... _schedulables) { + + for (Schedulable schedulable : _schedulables) { + this.add(schedulable); + } + this.state = State.IDLE; + } + + /** + * Create or return the default scheduler + * + * @return The default scheduler + */ + public static Scheduler getDefaultScheduler() { + if (defaultScheduler == null) { + defaultScheduler = new Scheduler(); + if (!Configuration.commandLineMode) { + MainWindow.instance(); + SchedulerToolbar st = new SchedulerToolbar("Default", defaultScheduler); + MainWindow.addToolbar(st); + } + } + return defaultScheduler; + } + + /** + * Set the delay between two cycles and launch the scheduler if it is not + * running + * + * @param i + * the delay between two cycles + */ + public void startWithSleep(int i) { + if (locked > 0) { + + synchronized (onChange) { + onChange.forEach(c -> c.accept(this)); + } + return; + } + setSleep(i); + stateLock.lock(); + switch (state) { + case IDLE: + state = State.RUNNING; + new Thread(this).start(); + break; + default: + break; + } + stateLock.unlock(); + synchronized (onChange) { + onChange.forEach(c -> c.accept(this)); + } + } + + /** + * Start (or continue) with no delay between cycles + */ + public void start() { + startWithSleep(Schedulable.DEFAULT_SLEEP); + } + + /** + * Execute one cycle + */ + public void step() { + if (locked > 0) { + synchronized (onChange) { + onChange.forEach(c -> c.accept(this)); + } + return; + } + this.setSleep(0); + stateLock.lock(); + switch (state) { + case IDLE: + state = State.PENDING_STOP; + new Thread(this).start(); + break; + default: + break; + + } + stateLock.unlock(); + synchronized (onChange) { + onChange.forEach(c -> c.accept(this)); + } + } + + /** + * Stop the scheduler if it is running + */ + public void stop() { + stateLock.lock(); + switch (state) { + case RUNNING: + state = State.PENDING_STOP; + break; + default: + break; + + } + stateLock.unlock(); + synchronized (onChange) { + onChange.forEach(c -> c.accept(this)); + } + } + + /** + * Threaded run method + */ + @Override + public void run() { + treatPendingSchedulables(); + for (Schedulable schedulable : schedulables) { + schedulable.onSchedulingStarts(); + } + boolean mustStop; + do { + for (Schedulable schedulable : schedulables) { + schedulable.cycle(); + } + if (getSleep() != 0) { + try { + Thread.sleep(getSleep()); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + mustStop = false; + for (Schedulable schedulable : schedulables) { + mustStop |= schedulable.stopCondition(); + } + } while (state == State.RUNNING && !mustStop); + stateLock.lock(); + state = State.IDLE; + stateLock.unlock(); + + for (Schedulable schedulable : schedulables) { + schedulable.onSchedulingStops(); + } + treatPendingSchedulables(); + if (onStop != null) + onStop.accept(this); + } + + /** + * Effectively Add or Remove the schedulables that were added or removed during + * a cycle to avoid {@link ConcurrentModificationException} + */ + private void treatPendingSchedulables() { + while (!pendingAdditionSchedulables.isEmpty()) + schedulables.add(pendingAdditionSchedulables.poll()); + while (!pendingRemovalSchedulables.isEmpty()) + schedulables.remove(pendingRemovalSchedulables.poll()); + + } + + /** + * Set the method that must be executed when the system is stopped + * + * @param _onStop + * Consumer method + */ + public final void setOnStop(Consumer<Scheduler> _onStop) { + this.onStop = _onStop; + } + + /** + * Add a method that must be executed when the scheduler speed is changed + * + * @param _onChange + * Consumer method + */ + public final void addOnChange(Consumer<Scheduler> _onChange) { + synchronized (onChange) { + this.onChange.add(_onChange); + } + } + + /** + * Is the scheduler running ? + * + * @return true if the scheduler is running + */ + public boolean isRunning() { + return state == State.RUNNING; + } + + /** + * Getter for the sleep time + * + * @return the sleep time + */ + + public int getSleep() { + return sleep; + } + + /** + * Setter for the sleep time + * + * @param sleep + * The time between each cycle + */ + public void setSleep(int sleep) { + this.sleep = sleep; + } + + /** + * Plan to add a schedulable + * + * @param _schedulable + * the schedulable to add + */ + public void add(Schedulable _schedulable) { + this.pendingAdditionSchedulables.add(_schedulable); + } + + /** + * Plan to remove a schedulable + * + * @param _schedulable + * the schedulable to remove + */ + public void remove(Schedulable _schedulable) { + this.pendingRemovalSchedulables.add(_schedulable); + } + + /** + * Soft lock the scheduler to avoid a too early running + */ + public void lock() { + locked++; + } + + /** + * Soft unlock the scheduler to avoid a too early running + */ + public void unlock() { + locked--; + } + +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosopherExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosopherExample.java index d3f6e0bd..c52a91a4 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosopherExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosopherExample.java @@ -1,199 +1,199 @@ -package fr.irit.smac.amak.examples.philosophers; - -import java.util.Random; - -import fr.irit.smac.amak.Agent; -import fr.irit.smac.amak.ui.VUI; -import fr.irit.smac.amak.ui.drawables.Drawable; -import fr.irit.smac.amak.ui.drawables.DrawableRectangle; -import javafx.scene.paint.Color; - -/** - * This class represents a philosopher; - * - * @author perles - * - */ -public class PhilosopherExample extends Agent<PhilosophersAMASExample, TableExample> { - - /** - * The fork on the left of its plate - */ - private ForkExample left; - /** - * The fork on the right of its plate - */ - private ForkExample right; - /** - * The amount of time (in cycle) the philosopher haven't ate (while in state - * hungry) - */ - private double hungerDuration; - /** - * The amount of eaten pastas - */ - private double eatenPastas; - - /** - * The id of the philosopher - */ - private int id; - - /** - * States philosophers can be in - * - * @author perles - * - */ - public enum State { - /** - * The philosopher is thinking. It essentially means that they are not hungry - * and not eating - */ - THINK, - /** - * The philosopher is hungry. He wants to be in the state eating. - */ - HUNGRY, - /** - * The philosopher has obtained the two forks and eat. - */ - EATING - } - - /** - * The current state of the philosopher - */ - private State state = State.THINK; - - /** - * A rectangle meant to render the state and the location of the philosopher - */ - private DrawableRectangle drawableRectangle; - /** - * The rendering of the left fork when handled by the philosopher - */ - private Drawable drawableLeftFork; - /** - * The rendering of the right fork when handled by the philosopher - */ - private Drawable drawableRightFork; - - /** - * Constructor of the philosopher - * - * @param id - * the identifier of the philosopher - * @param amas - * the corresponding MAS - * @param left - * the left fork - * @param right - * the right fork - */ - public PhilosopherExample(int id, PhilosophersAMASExample amas, ForkExample left, ForkExample right) { - super(null, amas, id, left, right); - } - - @Override - public void onInitialization() { - this.id = (int) params[0]; - this.left = (ForkExample) params[1]; - this.right = (ForkExample) params[2]; - } - - @Override - protected void onRenderingInitialization() { - double x = 100 * Math.cos(2 * Math.PI * id / this.amas.getEnvironment().getForks().length); - double y = 100 * Math.sin(2 * Math.PI * id / this.amas.getEnvironment().getForks().length); - drawableRectangle = VUI.get(mainWindow).createAndAddRectangle(x, y, 20, 20); - drawableRectangle.setName("Philosopher "+getId()); - drawableLeftFork = VUI.get(mainWindow).createAndAddRectangle(x - 10, y, 5, 20).setColor(Color.BLACK).setStrokeOnly().hide().setShowInExplorer(false); - drawableRightFork = VUI.get(mainWindow).createAndAddRectangle(x + 10, y, 5, 20).setColor(Color.BLACK).setStrokeOnly().hide().setShowInExplorer(false); - - } - - @Override - protected void onPerceive() { - // Nothing goes here as the perception of neighbors criticality is already made - // by the framework - } - - @Override - protected void onDecideAndAct() { - State nextState = state; - switch (state) { - case EATING: - eatenPastas++; - if (new Random().nextInt(101) > 50) { - left.release(this); - right.release(this); - nextState = State.THINK; - } - break; - case HUNGRY: - hungerDuration++; - if (getMostCriticalNeighbor(true) == this) { - left.tryTake(this); - right.tryTake(this); - if (left.owned(this) && right.owned(this)) - nextState = State.EATING; - - } else { - left.release(this); - right.release(this); - } - break; - case THINK: - if (new Random().nextInt(101) > 50) { - hungerDuration = 0; - nextState = State.HUNGRY; - } - break; - default: - break; - - } - - state = nextState; - } - - @Override - protected double computeCriticality() { - if (state == State.HUNGRY) - return hungerDuration; - return -1; - } - - @Override - public void onUpdateRender() { - drawableRectangle.setInfo( - "Philosopher "+getId()+" :\n"+ - "State : "+state+"\n"+ - "Eaten pastas : "+eatenPastas+"." - ); - amas.plot.addData("Eaten pasta", id, eatenPastas); - switch (state) { - case EATING: - drawableRectangle.setColor(Color.BLUE); - break; - case HUNGRY: - drawableRectangle.setColor(Color.RED); - break; - case THINK: - drawableRectangle.setColor(Color.GREEN); - break; - - } - if (left.owned(this)) { - drawableLeftFork.show(); - } else { - drawableLeftFork.hide(); - } - if (right.owned(this)) { - drawableRightFork.show(); - } else { - drawableRightFork.hide(); - } - } -} +package fr.irit.smac.amak.examples.philosophers; + +import java.util.Random; + +import fr.irit.smac.amak.Agent; +import fr.irit.smac.amak.ui.VUI; +import fr.irit.smac.amak.ui.drawables.Drawable; +import fr.irit.smac.amak.ui.drawables.DrawableRectangle; +import javafx.scene.paint.Color; + +/** + * This class represents a philosopher; + * + * @author perles + * + */ +public class PhilosopherExample extends Agent<PhilosophersAMASExample, TableExample> { + + /** + * The fork on the left of its plate + */ + private ForkExample left; + /** + * The fork on the right of its plate + */ + private ForkExample right; + /** + * The amount of time (in cycle) the philosopher haven't ate (while in state + * hungry) + */ + private double hungerDuration; + /** + * The amount of eaten pastas + */ + private double eatenPastas; + + /** + * The id of the philosopher + */ + private int id; + + /** + * States philosophers can be in + * + * @author perles + * + */ + public enum State { + /** + * The philosopher is thinking. It essentially means that they are not hungry + * and not eating + */ + THINK, + /** + * The philosopher is hungry. He wants to be in the state eating. + */ + HUNGRY, + /** + * The philosopher has obtained the two forks and eat. + */ + EATING + } + + /** + * The current state of the philosopher + */ + private State state = State.THINK; + + /** + * A rectangle meant to render the state and the location of the philosopher + */ + private DrawableRectangle drawableRectangle; + /** + * The rendering of the left fork when handled by the philosopher + */ + private Drawable drawableLeftFork; + /** + * The rendering of the right fork when handled by the philosopher + */ + private Drawable drawableRightFork; + + /** + * Constructor of the philosopher + * + * @param id + * the identifier of the philosopher + * @param amas + * the corresponding MAS + * @param left + * the left fork + * @param right + * the right fork + */ + public PhilosopherExample(int id, PhilosophersAMASExample amas, ForkExample left, ForkExample right) { + super(amas, id, left, right); + } + + @Override + public void onInitialization() { + this.id = (int) params[0]; + this.left = (ForkExample) params[1]; + this.right = (ForkExample) params[2]; + } + + @Override + protected void onRenderingInitialization() { + double x = 100 * Math.cos(2 * Math.PI * id / this.amas.getEnvironment().getForks().length); + double y = 100 * Math.sin(2 * Math.PI * id / this.amas.getEnvironment().getForks().length); + drawableRectangle = VUI.get().createAndAddRectangle(x, y, 20, 20); + drawableRectangle.setName("Philosopher "+getId()); + drawableLeftFork = VUI.get().createAndAddRectangle(x - 10, y, 5, 20).setColor(Color.BLACK).setStrokeOnly().hide().setShowInExplorer(false); + drawableRightFork = VUI.get().createAndAddRectangle(x + 10, y, 5, 20).setColor(Color.BLACK).setStrokeOnly().hide().setShowInExplorer(false); + + } + + @Override + protected void onPerceive() { + // Nothing goes here as the perception of neighbors criticality is already made + // by the framework + } + + @Override + protected void onDecideAndAct() { + State nextState = state; + switch (state) { + case EATING: + eatenPastas++; + if (new Random().nextInt(101) > 50) { + left.release(this); + right.release(this); + nextState = State.THINK; + } + break; + case HUNGRY: + hungerDuration++; + if (getMostCriticalNeighbor(true) == this) { + left.tryTake(this); + right.tryTake(this); + if (left.owned(this) && right.owned(this)) + nextState = State.EATING; + + } else { + left.release(this); + right.release(this); + } + break; + case THINK: + if (new Random().nextInt(101) > 50) { + hungerDuration = 0; + nextState = State.HUNGRY; + } + break; + default: + break; + + } + + state = nextState; + } + + @Override + protected double computeCriticality() { + if (state == State.HUNGRY) + return hungerDuration; + return -1; + } + + @Override + public void onUpdateRender() { + drawableRectangle.setInfo( + "Philosopher "+getId()+" :\n"+ + "State : "+state+"\n"+ + "Eaten pastas : "+eatenPastas+"." + ); + amas.plot.addData("Eaten pasta", id, eatenPastas); + switch (state) { + case EATING: + drawableRectangle.setColor(Color.BLUE); + break; + case HUNGRY: + drawableRectangle.setColor(Color.RED); + break; + case THINK: + drawableRectangle.setColor(Color.GREEN); + break; + + } + if (left.owned(this)) { + drawableLeftFork.show(); + } else { + drawableLeftFork.hide(); + } + if (right.owned(this)) { + drawableRightFork.show(); + } else { + drawableRightFork.hide(); + } + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersAMASExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersAMASExample.java index f996df54..5b00921f 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersAMASExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersAMASExample.java @@ -1,79 +1,74 @@ -package fr.irit.smac.amak.examples.philosophers; - -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Configuration; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.RunLaterHelper; -import fr.irit.smac.amak.ui.AmakPlot; -import fr.irit.smac.amak.ui.AmakPlot.ChartType; -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.VUI; -import javafx.scene.control.Label; -import javafx.scene.paint.Color; - -public class PhilosophersAMASExample extends Amas<TableExample> { - - public MainWindow mainWindow; - - private Label comp; - private PhilosopherExample[] ps; - - public AmakPlot plot; - - public PhilosophersAMASExample(MainWindow window, TableExample env) { - super(window, env, Scheduling.DEFAULT); - - mainWindow = window; - } - - @Override - protected void onRenderingInitialization() { - super.onRenderingInitialization(); - plot = new AmakPlot(mainWindow, "Eaten pasten", ChartType.BAR, "Philosophers", "Number of eaten pastas"); - } - - @Override - protected void onInitialConfiguration() { - Configuration.executionPolicy = ExecutionPolicy.TWO_PHASES; - comp = new Label("Cycle"); - mainWindow.addToolbar(comp); - - VUI.get(mainWindow).createAndAddRectangle(20, 20, 20, 20).setColor(Color.RED).setFixed().setLayer(10).setShowInExplorer(false); - VUI.get(mainWindow).createAndAddString(45, 25, "Hungry").setFixed().setLayer(10).setShowInExplorer(false); - - VUI.get(mainWindow).createAndAddRectangle(20, 45, 20, 20).setColor(Color.BLUE).setFixed().setLayer(10).setShowInExplorer(false); - VUI.get(mainWindow).createAndAddString(45, 50, "Eating").setFixed().setLayer(10).setShowInExplorer(false); - - VUI.get(mainWindow).createAndAddRectangle(20, 70, 20, 20).setColor(Color.GREEN).setFixed().setLayer(10).setShowInExplorer(false); - VUI.get(mainWindow).createAndAddString(45, 75, "Thinking").setFixed().setLayer(10).setShowInExplorer(false); - } - - @Override - protected void onInitialAgentsCreation() { - ps = new PhilosopherExample[getEnvironment().getForks().length]; - // Create one agent per fork - for (int i = 0; i < getEnvironment().getForks().length - 1; i++) { - ps[i] = new PhilosopherExample(i, this, getEnvironment().getForks()[i], getEnvironment().getForks()[i + 1]); - } - - // Let the last philosopher takes the first fork (round table) - ps[getEnvironment().getForks().length - 1] = new PhilosopherExample(getEnvironment().getForks().length - 1, - this, getEnvironment().getForks()[getEnvironment().getForks().length - 1], - getEnvironment().getForks()[0]); - - // Add neighborhood - for (int i = 1; i < ps.length; i++) { - ps[i].addNeighbor(ps[i - 1]); - ps[i - 1].addNeighbor(ps[i]); - } - ps[0].addNeighbor(ps[ps.length - 1]); - ps[ps.length - 1].addNeighbor(ps[0]); - } - - @Override - protected void onSystemCycleBegin() { - RunLaterHelper.runLater(() -> { - comp.setText("Cycle " + getCycle()); - }); - } -} +package fr.irit.smac.amak.examples.philosophers; + +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Configuration; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.RunLaterHelper; +import fr.irit.smac.amak.ui.AmakPlot; +import fr.irit.smac.amak.ui.AmakPlot.ChartType; +import fr.irit.smac.amak.ui.MainWindow; +import fr.irit.smac.amak.ui.VUI; +import javafx.scene.control.Label; +import javafx.scene.paint.Color; + +public class PhilosophersAMASExample extends Amas<TableExample> { + private Label comp; + private PhilosopherExample[] ps; + + public AmakPlot plot; + + public PhilosophersAMASExample(TableExample env) { + super(env, Scheduling.DEFAULT); + } + + @Override + protected void onRenderingInitialization() { + super.onRenderingInitialization(); + plot = new AmakPlot("Eaten pasten", ChartType.BAR, "Philosophers", "Number of eaten pastas"); + } + + @Override + protected void onInitialConfiguration() { + Configuration.executionPolicy = ExecutionPolicy.TWO_PHASES; + comp = new Label("Cycle"); + MainWindow.addToolbar(comp); + + VUI.get().createAndAddRectangle(20, 20, 20, 20).setColor(Color.RED).setFixed().setLayer(10).setShowInExplorer(false); + VUI.get().createAndAddString(45, 25, "Hungry").setFixed().setLayer(10).setShowInExplorer(false); + + VUI.get().createAndAddRectangle(20, 45, 20, 20).setColor(Color.BLUE).setFixed().setLayer(10).setShowInExplorer(false); + VUI.get().createAndAddString(45, 50, "Eating").setFixed().setLayer(10).setShowInExplorer(false); + + VUI.get().createAndAddRectangle(20, 70, 20, 20).setColor(Color.GREEN).setFixed().setLayer(10).setShowInExplorer(false); + VUI.get().createAndAddString(45, 75, "Thinking").setFixed().setLayer(10).setShowInExplorer(false); + } + + @Override + protected void onInitialAgentsCreation() { + ps = new PhilosopherExample[getEnvironment().getForks().length]; + // Create one agent per fork + for (int i = 0; i < getEnvironment().getForks().length - 1; i++) { + ps[i] = new PhilosopherExample(i, this, getEnvironment().getForks()[i], getEnvironment().getForks()[i + 1]); + } + + // Let the last philosopher takes the first fork (round table) + ps[getEnvironment().getForks().length - 1] = new PhilosopherExample(getEnvironment().getForks().length - 1, + this, getEnvironment().getForks()[getEnvironment().getForks().length - 1], + getEnvironment().getForks()[0]); + + // Add neighborhood + for (int i = 1; i < ps.length; i++) { + ps[i].addNeighbor(ps[i - 1]); + ps[i - 1].addNeighbor(ps[i]); + } + ps[0].addNeighbor(ps[ps.length - 1]); + ps[ps.length - 1].addNeighbor(ps[0]); + } + + @Override + protected void onSystemCycleBegin() { + RunLaterHelper.runLater(() -> { + comp.setText("Cycle " + getCycle()); + }); + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersLaunchExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersLaunchExample.java index 94c4576b..872f28a1 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersLaunchExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/PhilosophersLaunchExample.java @@ -1,10 +1,10 @@ -package fr.irit.smac.amak.examples.philosophers; - -public class PhilosophersLaunchExample { - - public static void main(String[] args) { - TableExample env = new TableExample(); - new PhilosophersAMASExample(null, env); - - } -} +package fr.irit.smac.amak.examples.philosophers; + +public class PhilosophersLaunchExample { + + public static void main(String[] args) { + TableExample env = new TableExample(); + new PhilosophersAMASExample(env); + + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/TableExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/TableExample.java index a84c75bd..c5227eff 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/TableExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/philosophers/TableExample.java @@ -1,24 +1,24 @@ -package fr.irit.smac.amak.examples.philosophers; - -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; - -public class TableExample extends Environment { - public TableExample(Object...params) { - super(null, Scheduling.HIDDEN, params); - } - - private ForkExample[] forks; - - @Override - public void onInitialization() { - // Set 10 forks on the table - forks = new ForkExample[10]; - for (int i = 0; i < forks.length; i++) - forks[i] = new ForkExample(); - } - - public ForkExample[] getForks() { - return forks; - } -} +package fr.irit.smac.amak.examples.philosophers; + +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; + +public class TableExample extends Environment { + public TableExample(Object...params) { + super(Scheduling.HIDDEN, params); + } + + private ForkExample[] forks; + + @Override + public void onInitialization() { + // Set 10 forks on the table + forks = new ForkExample[10]; + for (int i = 0; i < forks.length; i++) + forks[i] = new ForkExample(); + } + + public ForkExample[] getForks() { + return forks; + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntExample.java index c0d48981..8186b0d4 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntExample.java @@ -1,90 +1,88 @@ -package fr.irit.smac.amak.examples.randomants; - -import fr.irit.smac.amak.Agent; -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.VUI; -import fr.irit.smac.amak.ui.drawables.DrawableImage; - -public class AntExample extends Agent<AntHillExample, WorldExample> { - - private boolean dead = false; - - /** - * X coordinate of the ant in the world - */ - public double dx; - /** - * Y coordinate of the ant in the world - */ - public double dy; - /** - * Angle in radians - */ - private double angle = Math.random() * Math.PI * 2; - private DrawableImage image; - - /** - * Constructor of the ant - * - * @param amas - * the amas the ant belongs to - * @param startX - * Initial X coordinate - * @param startY - * Initial Y coordinate - */ - public AntExample(AmasWindow amasWindow, AntHillExample amas, double startX, double startY) { - super(amasWindow, amas, startX, startY); - } - @Override - public void onInitialization() { - dx = (double) params[0]; - dy = (double) params[1]; - } - - @Override - protected void onRenderingInitialization() { - image = VUI.get(amasWindow).createAndAddImage(dx, dy, "file:resources/ant.png"); - image.setName("Ant "+getId()); - } - - /** - * Move in a random direction - */ - @Override - protected void onDecideAndAct() { - double random = amas.getEnvironment().getRandom().nextGaussian(); - angle += random * 0.1; - dx += Math.cos(angle); - dy += Math.sin(angle); - while (dx >= getAmas().getEnvironment().getWidth() / 2) - dx -= getAmas().getEnvironment().getWidth(); - while (dy >= getAmas().getEnvironment().getHeight() / 2) - dy -= getAmas().getEnvironment().getHeight(); - while (dx < -getAmas().getEnvironment().getWidth() / 2) - dx += getAmas().getEnvironment().getWidth(); - while (dy < -getAmas().getEnvironment().getHeight() / 2) - dy += getAmas().getEnvironment().getHeight(); - - if (amas.getEnvironment().getRandom().nextDouble() < 0.001) { - dead = true; - destroy(); - } - - if (amas.getEnvironment().getRandom().nextDouble() < 0.001) { - new AntExample(amasWindow, getAmas(), dx, dy); - } - } - - @Override - public void onUpdateRender() { - image.move(dx, dy); - image.setAngle(angle); - image.setInfo("Ant "+getId()+"\nPosition "+dx+" "+dy+"\nAngle "+angle); - if(dead) { - image.setFilename("file:Resources/ant_dead.png"); - image.setInfo("Ant "+getId()+"\nPosition "+dx+" "+dy+"\nAngle "+angle+"\nDead"); - } - } -} +package fr.irit.smac.amak.examples.randomants; + +import fr.irit.smac.amak.Agent; +import fr.irit.smac.amak.ui.VUI; +import fr.irit.smac.amak.ui.drawables.DrawableImage; + +public class AntExample extends Agent<AntHillExample, WorldExample> { + + private boolean dead = false; + + /** + * X coordinate of the ant in the world + */ + public double dx; + /** + * Y coordinate of the ant in the world + */ + public double dy; + /** + * Angle in radians + */ + private double angle = Math.random() * Math.PI * 2; + private DrawableImage image; + + /** + * Constructor of the ant + * + * @param amas + * the amas the ant belongs to + * @param startX + * Initial X coordinate + * @param startY + * Initial Y coordinate + */ + public AntExample(AntHillExample amas, double startX, double startY) { + super(amas, startX, startY); + } + @Override + public void onInitialization() { + dx = (double) params[0]; + dy = (double) params[1]; + } + + @Override + protected void onRenderingInitialization() { + image = VUI.get().createAndAddImage(dx, dy, "file:resources/ant.png"); + image.setName("Ant "+getId()); + } + + /** + * Move in a random direction + */ + @Override + protected void onDecideAndAct() { + double random = amas.getEnvironment().getRandom().nextGaussian(); + angle += random * 0.1; + dx += Math.cos(angle); + dy += Math.sin(angle); + while (dx >= getAmas().getEnvironment().getWidth() / 2) + dx -= getAmas().getEnvironment().getWidth(); + while (dy >= getAmas().getEnvironment().getHeight() / 2) + dy -= getAmas().getEnvironment().getHeight(); + while (dx < -getAmas().getEnvironment().getWidth() / 2) + dx += getAmas().getEnvironment().getWidth(); + while (dy < -getAmas().getEnvironment().getHeight() / 2) + dy += getAmas().getEnvironment().getHeight(); + + if (amas.getEnvironment().getRandom().nextDouble() < 0.001) { + dead = true; + destroy(); + } + + if (amas.getEnvironment().getRandom().nextDouble() < 0.001) { + new AntExample(getAmas(), dx, dy); + } + } + + @Override + public void onUpdateRender() { + image.move(dx, dy); + image.setAngle(angle); + image.setInfo("Ant "+getId()+"\nPosition "+dx+" "+dy+"\nAngle "+angle); + if(dead) { + image.setFilename("file:Resources/ant_dead.png"); + image.setInfo("Ant "+getId()+"\nPosition "+dx+" "+dy+"\nAngle "+angle+"\nDead"); + } + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntHillExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntHillExample.java index 76d93405..6e276bb0 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntHillExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntHillExample.java @@ -1,39 +1,33 @@ -package fr.irit.smac.amak.examples.randomants; - -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.RunLaterHelper; -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.VUI; -import fr.irit.smac.amak.ui.drawables.DrawableString; - -public class AntHillExample extends Amas<WorldExample> { - - - - private DrawableString antsCountLabel; - - public AntHillExample(AmasWindow window, WorldExample env) { - super(window, env, Scheduling.DEFAULT); - } - - @Override - protected void onRenderingInitialization() { - VUI.get(amasWindow).createAndAddImage(20, 20, "file:Resources/ant.png").setFixed().setLayer(10).setShowInExplorer(false); - antsCountLabel = (DrawableString) VUI.get(amasWindow).createAndAddString(45, 25, "Ants count").setFixed().setLayer(10).setShowInExplorer(false); - - - } - - @Override - protected void onInitialAgentsCreation() { - for (int i = 0; i < 50; i++) - new AntExample(amasWindow, this, 0, 0); - } - - @Override - protected void onSystemCycleEnd() { - RunLaterHelper.runLater(()->antsCountLabel.setText("Ants count: " + getAgents().size())); - } -} +package fr.irit.smac.amak.examples.randomants; + +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.RunLaterHelper; +import fr.irit.smac.amak.ui.VUI; +import fr.irit.smac.amak.ui.drawables.DrawableString; + +public class AntHillExample extends Amas<WorldExample> { + + private DrawableString antsCountLabel; + + public AntHillExample(WorldExample env) { + super(env, Scheduling.DEFAULT); + } + + @Override + protected void onRenderingInitialization() { + VUI.get().createAndAddImage(20, 20, "file:Resources/ant.png").setFixed().setLayer(10).setShowInExplorer(false); + antsCountLabel = (DrawableString) VUI.get().createAndAddString(45, 25, "Ants count").setFixed().setLayer(10).setShowInExplorer(false); + } + + @Override + protected void onInitialAgentsCreation() { + for (int i = 0; i < 50; i++) + new AntExample(this, 0, 0); + } + + @Override + protected void onSystemCycleEnd() { + RunLaterHelper.runLater(()->antsCountLabel.setText("Ants count: " + getAgents().size())); + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExample.java index ce6e3f17..52344207 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExample.java @@ -1,6 +1,5 @@ package fr.irit.smac.amak.examples.randomants; -import fr.irit.smac.amak.ui.AmasWindow; import fr.irit.smac.amak.ui.MainWindow; import javafx.scene.control.Label; import javafx.scene.layout.Pane; @@ -8,20 +7,14 @@ import javafx.scene.layout.Pane; public class AntsLaunchExample { public static void main(String[] args) { + WorldExample env = new WorldExample(); - AmasWindow amasWindowAntHillExample = new AmasWindow(); - - - WorldExample env = new WorldExample(amasWindowAntHillExample); - - - - new AntHillExample(amasWindowAntHillExample, env); + new AntHillExample(env); Pane panel = new Pane(); panel.getChildren().add(new Label("AntHill simulation\n" + "Ants move randomly.\n" + "This demo is here to show AMAK rendering capacities.\n")); - amasWindowAntHillExample.setLeftPanel(panel); + MainWindow.setLeftPanel(panel); } } diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExampleMultiUI.java b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExampleMultiUI.java deleted file mode 100644 index 5d45bb7f..00000000 --- a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/AntsLaunchExampleMultiUI.java +++ /dev/null @@ -1,59 +0,0 @@ -package fr.irit.smac.amak.examples.randomants; - -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; -import javafx.scene.control.Label; -import javafx.scene.layout.Pane; - -public class AntsLaunchExampleMultiUI { - - - - - - public static void main(String[] args) { - - - MainWindow mainWindow = new MainWindow(); - mainWindow.instance(); - - AmasWindow mainWindowAntHillExample = new AmasWindow(); - - - - //MainWindow mainWindowAntHillExample2 = new MainWindow(); - - - WorldExample env = new WorldExample(mainWindowAntHillExample); - - - - new AntHillExample(mainWindowAntHillExample, env); - - Pane panel = new Pane(); - panel.getChildren().add(new Label("AntHill simulation\n" - + "Ants move randomly.\n" - + "This demo is here to show AMAK rendering capacities.\n")); - mainWindowAntHillExample.setLeftPanel(panel); - - - - - } - - - -} - - - - - - - - - - - - - diff --git a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/WorldExample.java b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/WorldExample.java index a785f273..2c6ea56a 100644 --- a/AMAKFX/src/fr/irit/smac/amak/examples/randomants/WorldExample.java +++ b/AMAKFX/src/fr/irit/smac/amak/examples/randomants/WorldExample.java @@ -1,31 +1,28 @@ -package fr.irit.smac.amak.examples.randomants; - -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.ui.AmasWindow; -import fr.irit.smac.amak.ui.MainWindow; - -public class WorldExample extends Environment { - - public WorldExample(AmasWindow amasWindow, Object...params) { - super(amasWindow, Scheduling.DEFAULT, params); - } - - private int width; - private int height; - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - @Override - public void onInitialization() { - this.width = 800; - this.height = 600; - } - -} +package fr.irit.smac.amak.examples.randomants; + +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; + +public class WorldExample extends Environment { + public WorldExample(Object...params) { + super(Scheduling.DEFAULT, params); + } + + private int width; + private int height; + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + @Override + public void onInitialization() { + this.width = 800; + this.height = 600; + } + +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/AsyncTest.java b/AMAKFX/src/fr/irit/smac/amak/tests/AsyncTest.java index 5746c878..7fe3c2a6 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/AsyncTest.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/AsyncTest.java @@ -1,90 +1,88 @@ -package fr.irit.smac.amak.tests; - -import fr.irit.smac.amak.Agent; -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Configuration; -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.Log; -import fr.irit.smac.amak.tools.Profiler; -import fr.irit.smac.amak.ui.MainWindow; - -public class AsyncTest { - - public static void main(String[] args) { - new AsyncTest(); - } - - public AsyncTest() { - Configuration.allowedSimultaneousAgentsExecution = 10; - - Log.defaultMinLevel = Log.Level.DEBUG; - runAmas(); - } - - private void runAmas() { - MainWindow mainWindow = new MainWindow(); - MyAMAS amas = new MyAMAS(mainWindow, new MyEnvironment(), Scheduling.DEFAULT); - amas.getScheduler().setOnStop(s -> { - Log.defaultLog.inform("time", "Threads used: %d", Configuration.allowedSimultaneousAgentsExecution); - Log.defaultLog.inform("time", "Elapsed time: %s", Profiler.endHR("amas")); - }); - Profiler.start("amas"); - - amas.start(); - } - - public class MyAMAS extends Amas<MyEnvironment> { - - public MyAMAS(MainWindow mainWindow, MyEnvironment environment, Scheduling scheduling, Object... params) { - super(mainWindow, environment, scheduling); - } - - @Override - protected void onInitialAgentsCreation() { - for (int i = 0; i < 2; i++) { - new MyAgent(this); - } - } - } - - public class MyAgent extends Agent<MyAMAS, MyEnvironment> { - public int myCycle = 0; - - public MyAgent(MyAMAS amas, Object... params) { - super(null,amas, params); - } - - @Override - public void onInitialization() { - setAsynchronous(); - } - - @Override - protected void onPerceive() { - } - - @Override - protected void onAct() { - myCycle++; - // Sleep the thread to simulate a behavior - try { - Thread.sleep(getId() % 2 == 0 ? 0 : 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - @Override - protected void onAgentCycleEnd() { - Log.defaultLog.debug("AsyncTest", "Agent #%d cycle %d", getId(), myCycle); - } - } - - public class MyEnvironment extends Environment { - - public MyEnvironment(Object... params) { - super(null,Scheduling.DEFAULT, params); - } - } -} +package fr.irit.smac.amak.tests; + +import fr.irit.smac.amak.Agent; +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Configuration; +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.Log; +import fr.irit.smac.amak.tools.Profiler; + +public class AsyncTest { + + public static void main(String[] args) { + new AsyncTest(); + } + + public AsyncTest() { + Configuration.allowedSimultaneousAgentsExecution = 10; + + Log.defaultMinLevel = Log.Level.DEBUG; + runAmas(); + } + + private void runAmas() { + MyAMAS amas = new MyAMAS(new MyEnvironment(), Scheduling.DEFAULT); + amas.getScheduler().setOnStop(s -> { + Log.defaultLog.inform("time", "Threads used: %d", Configuration.allowedSimultaneousAgentsExecution); + Log.defaultLog.inform("time", "Elapsed time: %s", Profiler.endHR("amas")); + }); + Profiler.start("amas"); + + amas.start(); + } + + public class MyAMAS extends Amas<MyEnvironment> { + + public MyAMAS(MyEnvironment environment, Scheduling scheduling, Object... params) { + super(environment, scheduling); + } + + @Override + protected void onInitialAgentsCreation() { + for (int i = 0; i < 2; i++) { + new MyAgent(this); + } + } + } + + public class MyAgent extends Agent<MyAMAS, MyEnvironment> { + public int myCycle = 0; + + public MyAgent(MyAMAS amas, Object... params) { + super(amas, params); + } + + @Override + public void onInitialization() { + setAsynchronous(); + } + + @Override + protected void onPerceive() { + } + + @Override + protected void onAct() { + myCycle++; + // Sleep the thread to simulate a behavior + try { + Thread.sleep(getId() % 2 == 0 ? 0 : 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + protected void onAgentCycleEnd() { + Log.defaultLog.debug("AsyncTest", "Agent #%d cycle %d", getId(), myCycle); + } + } + + public class MyEnvironment extends Environment { + + public MyEnvironment(Object... params) { + super(Scheduling.DEFAULT, params); + } + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/CommandLineOnlyResolution.java b/AMAKFX/src/fr/irit/smac/amak/tests/CommandLineOnlyResolution.java index 44b34b5a..c0979299 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/CommandLineOnlyResolution.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/CommandLineOnlyResolution.java @@ -1,40 +1,40 @@ -package fr.irit.smac.amak.tests; - -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Configuration; -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.Log; - -public class CommandLineOnlyResolution { - - public static void main(String[] args) { - new CommandLineOnlyResolution(); - } - public CommandLineOnlyResolution() { - Configuration.commandLineMode = true; - new MyAMAS().start(); - } - - public class MyAMAS extends Amas<MyEnv> { - - public MyAMAS() { - super(null,new MyEnv(), Scheduling.DEFAULT); - } - @Override - public boolean stopCondition() { - return cycle==100; - } - @Override - protected void onSystemCycleEnd() { - Log.defaultLog.debug("test", "yolo"); - } - } - public class MyEnv extends Environment { - - public MyEnv() { - super(null, Scheduling.DEFAULT); - } - } - -} +package fr.irit.smac.amak.tests; + +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Configuration; +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.Log; + +public class CommandLineOnlyResolution { + + public static void main(String[] args) { + new CommandLineOnlyResolution(); + } + public CommandLineOnlyResolution() { + Configuration.commandLineMode = true; + new MyAMAS().start(); + } + + public class MyAMAS extends Amas<MyEnv> { + + public MyAMAS() { + super(new MyEnv(), Scheduling.DEFAULT); + } + @Override + public boolean stopCondition() { + return cycle==100; + } + @Override + protected void onSystemCycleEnd() { + Log.defaultLog.debug("test", "yolo"); + } + } + public class MyEnv extends Environment { + + public MyEnv() { + super(Scheduling.DEFAULT); + } + } + +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/Order.java b/AMAKFX/src/fr/irit/smac/amak/tests/Order.java index d89b2bd7..ece97727 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/Order.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/Order.java @@ -1,61 +1,61 @@ -package fr.irit.smac.amak.tests; - -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Configuration; -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.Log; - -public class Order { - public boolean lastExecutedWasEnvironment; - public boolean firstFound = false; - public static void main(String[] args) { - new Order(); - - - } - public Order() { - Configuration.commandLineMode = true; - new MyAMAS().start(); - } - - public class MyAMAS extends Amas<MyEnv> { - - public MyAMAS() { - super(null,new MyEnv(), Scheduling.DEFAULT); - } - @Override - public boolean stopCondition() { - return cycle==100000000; - } - @Override - protected void onSystemCycleEnd() { - if (!firstFound) { - Log.defaultLog.debug("test","First is MAS"); - firstFound = true; - } - - if (!lastExecutedWasEnvironment) { - Log.defaultLog.fatal("test", "last executed was not the environment"); - System.exit(-1); - } - lastExecutedWasEnvironment = false; - } - } - public class MyEnv extends Environment { - - public MyEnv() { - super(null, Scheduling.DEFAULT); - } - @Override - public void onCycle() { - if (!firstFound) { - Log.defaultLog.debug("test","First is Environment"); - firstFound = true; - } - - lastExecutedWasEnvironment = true; - } - } - -} +package fr.irit.smac.amak.tests; + +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Configuration; +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.Log; + +public class Order { + public boolean lastExecutedWasEnvironment; + public boolean firstFound = false; + public static void main(String[] args) { + new Order(); + + + } + public Order() { + Configuration.commandLineMode = true; + new MyAMAS().start(); + } + + public class MyAMAS extends Amas<MyEnv> { + + public MyAMAS() { + super(new MyEnv(), Scheduling.DEFAULT); + } + @Override + public boolean stopCondition() { + return cycle==100000000; + } + @Override + protected void onSystemCycleEnd() { + if (!firstFound) { + Log.defaultLog.debug("test","First is MAS"); + firstFound = true; + } + + if (!lastExecutedWasEnvironment) { + Log.defaultLog.fatal("test", "last executed was not the environment"); + System.exit(-1); + } + lastExecutedWasEnvironment = false; + } + } + public class MyEnv extends Environment { + + public MyEnv() { + super(Scheduling.DEFAULT); + } + @Override + public void onCycle() { + if (!firstFound) { + Log.defaultLog.debug("test","First is Environment"); + firstFound = true; + } + + lastExecutedWasEnvironment = true; + } + } + +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/ScalibilityTest.java b/AMAKFX/src/fr/irit/smac/amak/tests/ScalibilityTest.java index 1a550f2f..d6b73ada 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/ScalibilityTest.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/ScalibilityTest.java @@ -1,98 +1,98 @@ -package fr.irit.smac.amak.tests; - -import fr.irit.smac.amak.Agent; -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.FileHandler; -import fr.irit.smac.amak.tools.Log; - -public class ScalibilityTest { - - public static void main(String[] args) { - new ScalibilityTest(); - - } - - private long startTime; - - public ScalibilityTest() { - Log.defaultMinLevel = Log.Level.INFORM; - runAmasWithNAgents(1); - } - - private void runAmasWithNAgents(int i) { - Log.defaultLog.inform("Global state", "start i:%d", i); - MyAMAS amas = new MyAMAS(new MyEnvironment(), Scheduling.HIDDEN, new Integer(i)); - amas.getScheduler().setOnStop(s -> { - int nextI = i; - FileHandler.writeCSVLine("scalability_results.csv", i+"", (System.currentTimeMillis() - startTime)+""); - switch (i) { - case 1: - nextI = 5; - break; - case 5: - nextI = 10; - break; - case 10: - nextI = 100; - break; - case 100: - nextI = 1000; - break; - default: - Log.defaultLog.inform("Global state", "end"); - return; - } - runAmasWithNAgents(nextI); - }); - startTime = System.currentTimeMillis(); - amas.start(); - } - - public class MyAMAS extends Amas<MyEnvironment> { - - public MyAMAS(MyEnvironment environment, Scheduling scheduling, Object... params) { - super(null, environment, scheduling, params); - } - - @Override - protected void onInitialAgentsCreation() { - for (int i = 0; i < (Integer) params[0]; i++) { - new MyAgent(this); - } - } - - @Override - public boolean stopCondition() { - return cycle == 100; - } - } - - public class MyAgent extends Agent<MyAMAS, MyEnvironment> { - - public MyAgent(MyAMAS amas, Object... params) { - super(null, amas, params); - } - - @Override - protected void onAct() { - // Sleep the thread to simulate a behavior - try { - Thread.sleep((long) ((amas.getEnvironment().getRandom().nextDouble() + 1) * 3)); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - } - - public class MyEnvironment extends Environment { - - public MyEnvironment(Object...params) { - super(null, Scheduling.DEFAULT, params); - } - - } -} +package fr.irit.smac.amak.tests; + +import fr.irit.smac.amak.Agent; +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.FileHandler; +import fr.irit.smac.amak.tools.Log; + +public class ScalibilityTest { + + public static void main(String[] args) { + new ScalibilityTest(); + + } + + private long startTime; + + public ScalibilityTest() { + Log.defaultMinLevel = Log.Level.INFORM; + runAmasWithNAgents(1); + } + + private void runAmasWithNAgents(int i) { + Log.defaultLog.inform("Global state", "start i:%d", i); + MyAMAS amas = new MyAMAS(new MyEnvironment(), Scheduling.HIDDEN, new Integer(i)); + amas.getScheduler().setOnStop(s -> { + int nextI = i; + FileHandler.writeCSVLine("scalability_results.csv", i+"", (System.currentTimeMillis() - startTime)+""); + switch (i) { + case 1: + nextI = 5; + break; + case 5: + nextI = 10; + break; + case 10: + nextI = 100; + break; + case 100: + nextI = 1000; + break; + default: + Log.defaultLog.inform("Global state", "end"); + return; + } + runAmasWithNAgents(nextI); + }); + startTime = System.currentTimeMillis(); + amas.start(); + } + + public class MyAMAS extends Amas<MyEnvironment> { + + public MyAMAS(MyEnvironment environment, Scheduling scheduling, Object... params) { + super(environment, scheduling, params); + } + + @Override + protected void onInitialAgentsCreation() { + for (int i = 0; i < (Integer) params[0]; i++) { + new MyAgent(this); + } + } + + @Override + public boolean stopCondition() { + return cycle == 100; + } + } + + public class MyAgent extends Agent<MyAMAS, MyEnvironment> { + + public MyAgent(MyAMAS amas, Object... params) { + super(amas, params); + } + + @Override + protected void onAct() { + // Sleep the thread to simulate a behavior + try { + Thread.sleep((long) ((amas.getEnvironment().getRandom().nextDouble() + 1) * 3)); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + } + + public class MyEnvironment extends Environment { + + public MyEnvironment(Object...params) { + super(Scheduling.DEFAULT, params); + } + + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/VisibleUI.java b/AMAKFX/src/fr/irit/smac/amak/tests/VisibleUI.java index a46a476b..5076bc23 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/VisibleUI.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/VisibleUI.java @@ -1,15 +1,12 @@ -package fr.irit.smac.amak.tests; - -import fr.irit.smac.amak.ui.MainWindow; -import fr.irit.smac.amak.ui.VUI; - -public class VisibleUI { - public static void main(String[] args) { - - MainWindow mainWindow = new MainWindow(); - - mainWindow.setWindowTitle("VUI Example"); - mainWindow.setWindowIcon("file:Resources/ant.png"); - VUI.get(mainWindow).createAndAddRectangle(0, 0, 200, 150); - } -} +package fr.irit.smac.amak.tests; + +import fr.irit.smac.amak.ui.MainWindow; +import fr.irit.smac.amak.ui.VUI; + +public class VisibleUI { + public static void main(String[] args) { + MainWindow.setWindowTitle("VUI Example"); + MainWindow.setWindowIcon("file:Resources/ant.png"); + VUI.get().createAndAddRectangle(0, 0, 200, 150); + } +} diff --git a/AMAKFX/src/fr/irit/smac/amak/tests/executionorder/Test.java b/AMAKFX/src/fr/irit/smac/amak/tests/executionorder/Test.java index 79ff94de..3eacfdf7 100644 --- a/AMAKFX/src/fr/irit/smac/amak/tests/executionorder/Test.java +++ b/AMAKFX/src/fr/irit/smac/amak/tests/executionorder/Test.java @@ -1,82 +1,82 @@ -package fr.irit.smac.amak.tests.executionorder; - -import fr.irit.smac.amak.Agent; -import fr.irit.smac.amak.Amas; -import fr.irit.smac.amak.Environment; -import fr.irit.smac.amak.Scheduling; -import fr.irit.smac.amak.tools.Log; - -public class Test { - - public static void main(String[] args) { - Log.defaultMinLevel = Log.Level.DEBUG; - new Test(); - } - - public Test() { - MyAMAS amas = new MyAMAS(new MyEnvironment()); - - new Agent1(amas); - new Agent2(amas); - new Agent2(amas); - new Agent1(amas); - - amas.start(); - } - - private class Agent1 extends Agent<MyAMAS, MyEnvironment> { - - public Agent1(MyAMAS amas) { - super(null, amas); - } - - @Override - protected int computeExecutionOrderLayer() { - return 1; - } - - @Override - protected void onAct() { - Log.defaultLog.debug(toString(), getExecutionOrder()+""); - } - } - - private class Agent2 extends Agent<MyAMAS, MyEnvironment> { - - public Agent2(MyAMAS amas) { - super(null, amas); - } - - @Override - protected int computeExecutionOrderLayer() { - return 2; - } - - @Override - protected void onAct() { - Log.defaultLog.debug(toString(), getExecutionOrder()+""); - } - } - - private class MyAMAS extends Amas<MyEnvironment> { - - public MyAMAS(MyEnvironment environment) { - super(null, environment, Scheduling.HIDDEN); - } - @Override - protected void onSystemCycleBegin() { - System.out.println("--"); - } - - } - - private class MyEnvironment extends Environment { - - public MyEnvironment(Object...params) { - super(null,Scheduling.DEFAULT, params); - // TODO Auto-generated constructor stub - } - - } - -} +package fr.irit.smac.amak.tests.executionorder; + +import fr.irit.smac.amak.Agent; +import fr.irit.smac.amak.Amas; +import fr.irit.smac.amak.Environment; +import fr.irit.smac.amak.Scheduling; +import fr.irit.smac.amak.tools.Log; + +public class Test { + + public static void main(String[] args) { + Log.defaultMinLevel = Log.Level.DEBUG; + new Test(); + } + + public Test() { + MyAMAS amas = new MyAMAS(new MyEnvironment()); + + new Agent1(amas); + new Agent2(amas); + new Agent2(amas); + new Agent1(amas); + + amas.start(); + } + + private class Agent1 extends Agent<MyAMAS, MyEnvironment> { + + public Agent1(MyAMAS amas) { + super(amas); + } + + @Override + protected int computeExecutionOrderLayer() { + return 1; + } + + @Override + protected void onAct() { + Log.defaultLog.debug(toString(), getExecutionOrder()+""); + } + } + + private class Agent2 extends Agent<MyAMAS, MyEnvironment> { + + public Agent2(MyAMAS amas) { + super(amas); + } + + @Override + protected int computeExecutionOrderLayer() { + return 2; + } + + @Override + protected void onAct() { + Log.defaultLog.debug(toString(), getExecutionOrder()+""); + } + } + + private class MyAMAS extends Amas<MyEnvironment> { + + public MyAMAS(MyEnvironment environment) { + super(environment, Scheduling.HIDDEN); + } + @Override + protected void onSystemCycleBegin() { + System.out.println("--"); + } + + } + + private class MyEnvironment extends Environment { + + public MyEnvironment(Object...params) { + super(Scheduling.DEFAULT, params); + // TODO Auto-generated constructor stub + } + + } + +} diff --git a/AMAKFX/src/fr/irit/smac/amak/ui/AmakPlot.java b/AMAKFX/src/fr/irit/smac/amak/ui/AmakPlot.java index b5399cc2..60a58286 100644 --- a/AMAKFX/src/fr/irit/smac/amak/ui/AmakPlot.java +++ b/AMAKFX/src/fr/irit/smac/amak/ui/AmakPlot.java @@ -23,8 +23,6 @@ import javafx.util.Duration; */ public class AmakPlot { - MainWindow mainWindow = null; - public enum ChartType {LINE, BAR;} /* STATIC */ @@ -35,13 +33,8 @@ public class AmakPlot { */ public static boolean useSamplingRenderer = false; - public void add(MainWindow window, AmakPlot chart) { - if(mainWindow == null) { - mainWindow = window; - } - mainWindow.addTabbedPanel(chart.name, new ChartViewer(chart.chart)); - - + public static void add(AmakPlot chart) { + MainWindow.addTabbedPanel(chart.name, new ChartViewer(chart.chart)); } /* ----- */ @@ -62,8 +55,7 @@ public class AmakPlot { * @param yAxisLabel label for the y (vertical) axis * @param autoAdd automatically make an {@link AmakPlot#add(AmakPlot)} call ? */ - public AmakPlot(MainWindow window, String name, ChartType chartType, String xAxisLabel, String yAxisLabel, boolean autoAdd) { - this.mainWindow = window; + public AmakPlot(String name, ChartType chartType, String xAxisLabel, String yAxisLabel, boolean autoAdd) { this.name = name; seriesCollection = new XYSeriesCollection(); switch (chartType) { @@ -87,10 +79,8 @@ public class AmakPlot { chart.setAntiAlias(false); chart.getPlot().setBackgroundPaint(Color.WHITE); if(autoAdd) { - add(mainWindow, this); + add(this); } - - } /** @@ -100,9 +90,8 @@ public class AmakPlot { * @param xAxisLabel label for the x (horizontal) axis * @param yAxisLabel label for the y (vertical) axis */ - public AmakPlot(MainWindow window, String name, ChartType chartType, String xAxisLabel, String yAxisLabel) { - this(window, name, chartType, xAxisLabel, yAxisLabel, true); - mainWindow = window; + public AmakPlot(String name, ChartType chartType, String xAxisLabel, String yAxisLabel) { + this(name, chartType, xAxisLabel, yAxisLabel, true); } @@ -113,12 +102,11 @@ public class AmakPlot { * @param chart the {@link JFreeChart} using a {@link XYSeriesCollection} for dataset. * @param autoAdd automatically make an {@link AmakPlot#add(AmakPlot)} call ? */ - public AmakPlot(MainWindow window, String name, JFreeChart chart, boolean autoAdd) { - mainWindow = window; + public AmakPlot(String name, JFreeChart chart, boolean autoAdd) { this.name = name; this.seriesCollection = (XYSeriesCollection) chart.getXYPlot().getDataset(); this.chart = chart; - add(mainWindow, this); + add(this); } /** @@ -127,10 +115,8 @@ public class AmakPlot { * @param name the name of the chart, used as the tab name. * @param chart the {@link JFreeChart} using a {@link XYSeriesCollection} for dataset. */ - public AmakPlot(MainWindow window, String name, JFreeChart chart) { - this(window, name, chart, true); - mainWindow = window; - + public AmakPlot(String name, JFreeChart chart) { + this(name, chart, true); } public String getName() { diff --git a/AMAKFX/src/fr/irit/smac/amak/ui/AmasWindow.java b/AMAKFX/src/fr/irit/smac/amak/ui/AmasWindow.java deleted file mode 100644 index 3cc17630..00000000 --- a/AMAKFX/src/fr/irit/smac/amak/ui/AmasWindow.java +++ /dev/null @@ -1,266 +0,0 @@ -package fr.irit.smac.amak.ui; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.locks.ReentrantLock; - -import javax.management.InstanceAlreadyExistsException; - -import fr.irit.smac.amak.Information; -import fr.irit.smac.amak.tools.RunLaterHelper; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.Node; -import javafx.scene.Scene; -import javafx.scene.control.Menu; -import javafx.scene.control.MenuBar; -import javafx.scene.control.MenuItem; -import javafx.scene.control.Tab; -import javafx.scene.control.TabPane; -import javafx.scene.control.ToolBar; -import javafx.scene.image.Image; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.stage.Stage; -import javafx.stage.WindowEvent; - -/** - * - * - */ -public class AmasWindow { - /** - * The window itself - */ - public Stage stage; - /** - * The panel which contains the toolbar - */ - public ToolBar toolbarPanel; - - /** - * The main pane of AMAK - */ - public BorderPane organizationPane; - - /** - * The menu bar of the window - */ - public MenuBar menuBar; - /** - * The menus - */ - public HashMap<String, Menu> menus = new HashMap<String, Menu>(); - /** - * The panel in which panels with tab can be added - */ - public TabPane tabbedPanel; - - /** - * Lock present to avoid the creation of a MainWindow while another is creating - */ - protected static ReentrantLock instanceLock = new ReentrantLock(); - protected static Object startEnded = new Object(); - - - private boolean applicationLaunched = false; - - /** - * Create the frame. - * - * @throws InstanceAlreadyExistsException - * if the MainWindow has already been instantiated. This constructor - * should be used by the Application of JavaFX only. - */ - public AmasWindow() { - - - - - - - } - - - - - - - public void start(Stage primaryStage) throws Exception { - synchronized (startEnded) { - VBox root = new VBox(); - - // Creation of the menu bar (Top) - menuBar = new MenuBar(); - root.getChildren().add(menuBar); - - // Border organization - organizationPane = new BorderPane(); - organizationPane.setMinSize(200, 200); //that way we avoid 0 size, which can cause problems - root.getChildren().add(organizationPane); - VBox.setVgrow(organizationPane, Priority.ALWAYS); - - // Creation of scene - primaryStage.setTitle("AMAK"); - Scene scene = new Scene(root, 450, 300); - stage = primaryStage; - stage.setScene(scene); - stage.setOnCloseRequest(new EventHandler<WindowEvent>() { - @Override - public void handle(WindowEvent event) { - Platform.exit(); - } - }); - - // Creation of the toolbar (Bottom) - toolbarPanel = new ToolBar(); - organizationPane.setBottom(toolbarPanel); - - // Creation of the right part of the split pane (Center Right) - tabbedPanel = new TabPane(); - organizationPane.setCenter(tabbedPanel); - - // Creation of the close menu item - MenuItem menuItem = new MenuItem("Close"); - menuItem.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - System.exit(0); - } - }); - addToMenu("Options", menuItem); - - menuBar.getMenus().add(new Menu("AMAKFX v" + Information.VERSION)); - - stage.show(); - - startEnded.notify(); - } - } - - /** - * Add an action when the JavaFX app close. - * - * @param onClose - * The action to be executed when the window is closed - */ - public static void addOnCloseAction(Runnable onClose) { - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { onClose.run(); } - }); - } - - - public void stop() throws Exception { - - System.exit(0); - } - - /** - * Change the icon of the window - * - * @param filename - * The filename of the icon - */ - public void setWindowIcon(String filename) { - - RunLaterHelper.runLater(() -> stage.getIcons().add(new Image(filename))); - } - - /** - * Change the title of the main window - * - * @param title - * The new title - */ - public void setWindowTitle(String title) { - System.out.println("setWindowTitle"); - RunLaterHelper.runLater(() -> stage.setTitle(title)); - } - - /** - * Add a button in the menu options - * - * @param title - * The title of the button - * @param event - * The action to be executed - */ - public void addOptionsItem(String title, EventHandler<ActionEvent> event) { - MenuItem menuItem = new MenuItem(title); - menuItem.setOnAction(event); - - RunLaterHelper.runLater(() -> addToMenu("Options", menuItem)); - } - - /** - * Add a tool in the toolbar. - * - * @param tool - */ - public void addToolbar(Node tool) { - RunLaterHelper.runLater(() -> toolbarPanel.getItems().add(tool)); - } - - /** - * Set a panel to the left - * - * @param panel - * The panel - */ - public void setLeftPanel(Node panel) { - RunLaterHelper.runLater(() -> organizationPane.setLeft(panel)); - } - - /** - * Set a panel to the right - * - * @param panel - * The panel - */ - public void setRightPanel(Node panel) { - RunLaterHelper.runLater(() -> organizationPane.setRight(panel)); - } - - - - - /** - * Add a panel with a tab - * - * @param title - * The title of the tab - * @param panel - * The panel to add - */ - public void addTabbedPanel(String title, Node panel) { - Tab t = new DraggableTab(title, panel); - RunLaterHelper.runLater(() -> tabbedPanel.getTabs().add(t)); - } - - /** - * Add a {@link MenuItem} to a {@link Menu}. May create the menu and add it to the menu bar. - * @param menuName the name of the menu where the item will be added. - * @param item the item to be added. - */ - public void addToMenu(String menuName, MenuItem item) { -// System.out.println("addToMenu"); -// instance(); - if( !this.menus.containsKey(menuName) ) { - Menu m = new Menu(menuName); - this.menus.put(menuName,m); - RunLaterHelper.runLater(() -> this.menuBar.getMenus().add(m)); - } - RunLaterHelper.runLater(() -> this.menus.get(menuName).getItems().add(item)); - } - - - - - - -} \ No newline at end of file diff --git a/AMAKFX/src/fr/irit/smac/amak/ui/VUI.java b/AMAKFX/src/fr/irit/smac/amak/ui/VUI.java index c6b8c50f..136cb472 100644 --- a/AMAKFX/src/fr/irit/smac/amak/ui/VUI.java +++ b/AMAKFX/src/fr/irit/smac/amak/ui/VUI.java @@ -1,577 +1,577 @@ -package fr.irit.smac.amak.ui; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Semaphore; -import java.util.concurrent.locks.ReentrantLock; - -import fr.irit.smac.amak.tools.RunLaterHelper; -import fr.irit.smac.amak.ui.drawables.Drawable; -import fr.irit.smac.amak.ui.drawables.DrawableImage; -import fr.irit.smac.amak.ui.drawables.DrawablePoint; -import fr.irit.smac.amak.ui.drawables.DrawableRectangle; -import fr.irit.smac.amak.ui.drawables.DrawableString; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.geometry.Insets; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.ToolBar; -import javafx.scene.control.Tooltip; -import javafx.scene.input.MouseEvent; -import javafx.scene.input.ScrollEvent; -import javafx.scene.layout.Background; -import javafx.scene.layout.BackgroundFill; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.CornerRadii; -import javafx.scene.layout.Pane; -import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; -import javafx.scene.text.TextAlignment; - -/** - * - * Vectorial UI: This class allows to create dynamic rendering with zoom and - * move capacities - * - * @author of original version (the Swing one) perles - * - */ -public class VUI { - /** - * The toolbar of the VUI. - */ - public ToolBar toolbar; - - /** - * The VUI explorer. - * @see VuiExplorer - */ - private VuiExplorer vuiExplorer; - - /** - * List of objects currently being drawn by the VUI - */ - private List<Drawable> drawables = new LinkedList<>(); - /** - * Lock to avoid concurrent modification on the list {@link #drawables} - */ - private ReentrantLock drawablesLock = new ReentrantLock(); - - /** - * A static map to facilitate access to different instances of VUI - */ - private static Map<String, VUI> instances = new HashMap<>(); - - /** - * The horizontal offset of the drawing zone. Used to allow the user to move the - * view. - */ - private double worldOffsetX; - - /** - * The vertical offset of the drawing zone. Used to allow the user to move the - * view. - */ - private double worldOffsetY; - - /** - * The last horizontal position of the mouse when dragging - */ - protected Double lastDragX; - - /** - * The last vertical position of the mouse when dragging - */ - protected Double lastDragY; - - /** - * The main panel of the VUI - */ - private BorderPane panel; - - /** - * The canvas on which all is drawn - */ - private Pane canvas; - - /** - * Label aiming at showing information about the VUI (zoom and offset) - */ - private Label statusLabel; - - /** - * The default value of the {@link #zoom} - */ - private double defaultZoom = 100; - /** - * The default horizontal position of the view - */ - private double defaultWorldCenterX = 0; - /** - * The default vertical position of the view - */ - private double defaultWorldCenterY = 0; - /** - * The value of the zoom. 100 means 1/1 scale - */ - protected double zoom = defaultZoom; - - /** - * The horizontal position of the view - */ - private double worldCenterX = defaultWorldCenterX; - - /** - * The vertical position of the view - */ - private double worldCenterY = defaultWorldCenterY; - - /** - * Used to be sure that only one thread at the same time create a VUI - */ - private static ReentrantLock instanceLock = new ReentrantLock(); - - /** - * Get the default VUI - * - * @return the default VUI - */ - public static VUI get(AmasWindow amasWindow) { - if(!instances.containsKey("Default")) - amasWindow.addTabbedPanel("Default VUI", get("Default").getPanel()); - return get("Default"); - } - - /** - * Create or get a VUI.<br/> - * You have add its panel to the MainWindow yourself. - * - * @param id - * The unique id of the VUI - * @return The VUI with id "id" - */ - public static VUI get(String id) { - instanceLock.lock(); - if (!instances.containsKey(id)) { - VUI value = new VUI(id); - instances.put(id, value); - instanceLock.unlock(); - return value; - } - instanceLock.unlock(); - return instances.get(id); - } - - /** - * Constructor of the VUI. This one is private as it can only be created through - * static method. - * - * @param title - * The title used for the vui - */ - private VUI(String title) { - Semaphore done = new Semaphore(0); - RunLaterHelper.runLater(() -> { - panel = new BorderPane(); - - toolbar = new ToolBar(); - statusLabel = new Label("status"); - statusLabel.setTextAlignment(TextAlignment.LEFT); - toolbar.getItems().add(statusLabel); - panel.setBottom(toolbar); - - Button resetButton = new Button("Reset"); - resetButton.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - zoom = defaultZoom; - worldCenterX = defaultWorldCenterX; - worldCenterY = defaultWorldCenterY; - updateCanvas(); - } - }); - toolbar.getItems().add(resetButton); - - canvas = new Pane(); - canvas.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY))); - // clip the canvas (avoid drawing outside of it) - Rectangle clip = new Rectangle(0, 0, 0, 0); - clip.widthProperty().bind(canvas.widthProperty()); - clip.heightProperty().bind(canvas.heightProperty()); - canvas.setClip(clip); - - canvas.setOnMousePressed(new EventHandler<MouseEvent>() { - @Override - public void handle(MouseEvent event) { - lastDragX = event.getX(); - lastDragY = event.getY(); - } - }); - canvas.setOnMouseExited(new EventHandler<MouseEvent>() { - @Override - public void handle(MouseEvent event) { - lastDragX = null; - lastDragY = null; - } - }); - canvas.setOnMouseDragged(new EventHandler<MouseEvent>() { - @Override - public void handle(MouseEvent event) { - try { - double transX = screenToWorldDistance(event.getX() - lastDragX); - double transY = screenToWorldDistance(event.getY() - lastDragY); - worldCenterX += transX; - worldCenterY += transY; - worldOffsetX += transX; - worldOffsetY += transY; - lastDragX = event.getX(); - lastDragY = event.getY(); - updateCanvas(); - } catch (Exception ez) { - // Catch exception occurring when mouse is out of the canvas - } - } - }); - - canvas.setOnScroll(new EventHandler<ScrollEvent>() { - @Override - public void handle(ScrollEvent event) { - double wdx = screenToWorldDistance(canvas.getWidth() / 2 - event.getX()); - double wdy = screenToWorldDistance(canvas.getHeight() / 2 - event.getY()); - zoom += event.getDeltaY() / event.getMultiplierY() * 10; - if (zoom < 10) - zoom = 10; - - double wdx2 = screenToWorldDistance(canvas.getWidth() / 2 - event.getX()); - double wdy2 = screenToWorldDistance(canvas.getHeight() / 2 - event.getY()); - worldCenterX -= wdx2 - wdx; - worldCenterY -= wdy2 - wdy; - updateCanvas(); - } - }); - - panel.setCenter(canvas); - - //add VuiExplorer - vuiExplorer = new VuiExplorer(this); - panel.setLeft(vuiExplorer); - Button veButton = new Button("VUI explorer"); - veButton.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - panel.setLeft(vuiExplorer); - } - }); - veButton.setTooltip(new Tooltip("Show the VUI explorer if it was hidden.")); - toolbar.getItems().add(veButton); - - done.release(); - }); - try { - done.acquire(); - } catch (InterruptedException e) { - System.err.println("Failed to make sure that the VUI is correctly initialized."); - e.printStackTrace(); - } - } - - /** - * Convert a distance in the world to its equivalent on the screen - * - * @param d - * the in world distance - * @return the on screen distance - */ - public double worldToScreenDistance(double d) { - return d * getZoomFactor(); - } - - /** - * Convert a distance on the screen to its equivalent in the world - * - * @param d - * the on screen distance - * @return the in world distance - */ - public double screenToWorldDistance(double d) { - return d / getZoomFactor(); - } - - /** - * Convert a X in the world to its equivalent on the screen - * - * @param x - * the X in world - * - * @return the X on screen distance - */ - public double worldToScreenX(double x) { - return (x + getWorldOffsetX()) * getZoomFactor(); - } - - /** - * A value that must be multiplied to scale objects - * - * @return the zoom factor - */ - public double getZoomFactor() { - return zoom / 100; - } - - /** - * Convert a Y in the world to its equivalent on the screen - * - * @param y - * the Y in world - * - * @return the Y on screen distance - */ - public double worldToScreenY(double y) { - return (-y + getWorldOffsetY()) * getZoomFactor(); - } - - /** - * Convert a X on the screen to its equivalent in the world - * - * @param x - * the X on screen - * - * @return the X in the world distance - */ - public double screenToWorldX(double x) { - return x / getZoomFactor() - getWorldOffsetX(); - } - - /** - * Convert a Y on the screen to its equivalent in the world - * - * @param y - * the Y on screen - * - * @return the Y in the world distance - */ - public double screenToWorldY(double y) { - return -y / getZoomFactor() + getWorldOffsetY(); - } - - /** - * Add a drawable to the VUI. - * - * @param d - * the new drawable - */ - public void add(Drawable d) { - d.setVUI(this); - RunLaterHelper.runLater(()-> canvas.getChildren().add(d.getNode())); - drawablesLock.lock(); - drawables.add(d); - drawablesLock.unlock(); - updateCanvas(); - } - - /** - * Remove a drawable from the VUI. - * - * @param d - * the new drawable - */ - public void remove(Drawable d) { - drawablesLock.lock(); - drawables.remove(d); - drawablesLock.unlock(); - RunLaterHelper.runLater(()-> canvas.getChildren().remove(d.getNode())); - updateCanvas(); - } - - /** - * Remove all drawables from the VUI. - */ - public void clear() { - drawablesLock.lock(); - drawables.clear(); - RunLaterHelper.runLater(()->canvas.getChildren().clear()); - drawablesLock.unlock(); - } - - /** - * Refresh the canvas - */ - public void updateCanvas() { - final double w = canvas.getWidth(); - final double h = canvas.getHeight(); - - setWorldOffsetX(worldCenterX + screenToWorldDistance(w / 2)); - setWorldOffsetY(worldCenterY + screenToWorldDistance(h / 2)); - - drawablesLock.lock(); - Collections.sort(drawables, (o1, o2) -> o1.getLayer() - o2.getLayer()); - for (Drawable d : drawables) - RunLaterHelper.runLater(()-> d.onDraw()); - drawablesLock.unlock(); - - RunLaterHelper.runLater(() -> { - statusLabel.setText(String.format("Zoom: %.2f Center: (%.2f,%.2f)", zoom, worldCenterX, worldCenterY)); - }); - - RunLaterHelper.runLater(()-> vuiExplorer.update(true)); - } - - /** - * Get the width of the canvas - * - * @return the canvas width - */ - public double getCanvasWidth() { - return canvas.getWidth(); - } - - /** - * Get the height of the canvas - * - * @return the canvas height - */ - public double getCanvasHeight() { - return canvas.getHeight(); - } - - /** - * Get the value that must be added to the X coordinate of in world object - * - * @return the X offset - */ - public double getWorldOffsetX() { - return worldOffsetX; - } - - /** - * Set the value that must be added to the X coordinate of in world object - * - * @param offsetX - * the X offset - */ - public void setWorldOffsetX(double offsetX) { - this.worldOffsetX = offsetX; - } - - /** - * Get the value that must be added to the Y coordinate of in world object - * - * @return the Y offset - */ - public double getWorldOffsetY() { - return worldOffsetY; - } - - /** - * Set the value that must be added to the Y coordinate of in world object - * - * @param offsetY - * the Y offset - */ - public void setWorldOffsetY(double offsetY) { - this.worldOffsetY = offsetY; - } - - /** - * Create a point and start rendering it - * - * @param dx - * the x coordinate - * @param dy - * the y coordinate - * @return the point object - */ - public DrawablePoint createAndAddPoint(double dx, double dy) { - DrawablePoint drawablePoint = new DrawablePoint(dx, dy); - add(drawablePoint); - return drawablePoint; - } - - /** - * Create a rectangle and start rendering it - * - * @param x - * the x coordinate - * @param y - * the y coordinate - * @param w - * the width - * @param h - * the height - * @return the rectangle object - */ - public DrawableRectangle createAndAddRectangle(double x, double y, double w, double h) { - DrawableRectangle d = new DrawableRectangle(x, y, w, h); - add(d); - return d; - } - - /** - * Set the default configuration of the view - * - * @param zoom - * the initial zoom value - * @param worldCenterX - * the initial X center value - * @param worldCenterY - * the initial Y center value - */ - public void setDefaultView(double zoom, double worldCenterX, double worldCenterY) { - this.zoom = zoom; - this.worldCenterX = worldCenterX; - this.worldCenterY = worldCenterY; - this.defaultZoom = zoom; - this.defaultWorldCenterX = worldCenterX; - this.defaultWorldCenterY = worldCenterY; - } - - /** - * Create an image and start rendering it - * - * @param dx - * the x coordinate - * @param dy - * the y coordinate - * @param filename - * the filename of the image - * @return the created image - */ - public DrawableImage createAndAddImage(double dx, double dy, String filename) { - DrawableImage image = new DrawableImage(dx, dy, filename); - add(image); - return image; - } - - /** - * Create a string and start rendering it - * - * @param dx - * the x coordinate - * @param dy - * the y coordinate - * @param text - * the text to display - * @return the created string - */ - public DrawableString createAndAddString(int dx, int dy, String text) { - DrawableString ds = new DrawableString(dx, dy, text); - add(ds); - return ds; - } - - public Pane getCanvas() { - return canvas; - } - - public BorderPane getPanel() { - return panel; - } - - public List<Drawable> getDrawables() { - return drawables; - } -} +package fr.irit.smac.amak.ui; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.ReentrantLock; + +import fr.irit.smac.amak.tools.RunLaterHelper; +import fr.irit.smac.amak.ui.drawables.Drawable; +import fr.irit.smac.amak.ui.drawables.DrawableImage; +import fr.irit.smac.amak.ui.drawables.DrawablePoint; +import fr.irit.smac.amak.ui.drawables.DrawableRectangle; +import fr.irit.smac.amak.ui.drawables.DrawableString; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ToolBar; +import javafx.scene.control.Tooltip; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.ScrollEvent; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundFill; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.CornerRadii; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.TextAlignment; + +/** + * + * Vectorial UI: This class allows to create dynamic rendering with zoom and + * move capacities + * + * @author of original version (the Swing one) perles + * + */ +public class VUI { + /** + * The toolbar of the VUI. + */ + public ToolBar toolbar; + + /** + * The VUI explorer. + * @see VuiExplorer + */ + private VuiExplorer vuiExplorer; + + /** + * List of objects currently being drawn by the VUI + */ + private List<Drawable> drawables = new LinkedList<>(); + /** + * Lock to avoid concurrent modification on the list {@link #drawables} + */ + private ReentrantLock drawablesLock = new ReentrantLock(); + + /** + * A static map to facilitate access to different instances of VUI + */ + private static Map<String, VUI> instances = new HashMap<>(); + + /** + * The horizontal offset of the drawing zone. Used to allow the user to move the + * view. + */ + private double worldOffsetX; + + /** + * The vertical offset of the drawing zone. Used to allow the user to move the + * view. + */ + private double worldOffsetY; + + /** + * The last horizontal position of the mouse when dragging + */ + protected Double lastDragX; + + /** + * The last vertical position of the mouse when dragging + */ + protected Double lastDragY; + + /** + * The main panel of the VUI + */ + private BorderPane panel; + + /** + * The canvas on which all is drawn + */ + private Pane canvas; + + /** + * Label aiming at showing information about the VUI (zoom and offset) + */ + private Label statusLabel; + + /** + * The default value of the {@link #zoom} + */ + private double defaultZoom = 100; + /** + * The default horizontal position of the view + */ + private double defaultWorldCenterX = 0; + /** + * The default vertical position of the view + */ + private double defaultWorldCenterY = 0; + /** + * The value of the zoom. 100 means 1/1 scale + */ + protected double zoom = defaultZoom; + + /** + * The horizontal position of the view + */ + private double worldCenterX = defaultWorldCenterX; + + /** + * The vertical position of the view + */ + private double worldCenterY = defaultWorldCenterY; + + /** + * Used to be sure that only one thread at the same time create a VUI + */ + private static ReentrantLock instanceLock = new ReentrantLock(); + + /** + * Get the default VUI + * + * @return the default VUI + */ + public static VUI get() { + if(!instances.containsKey("Default")) + MainWindow.addTabbedPanel("Default VUI", get("Default").getPanel()); + return get("Default"); + } + + /** + * Create or get a VUI.<br/> + * You have add its panel to the MainWindow yourself. + * + * @param id + * The unique id of the VUI + * @return The VUI with id "id" + */ + public static VUI get(String id) { + instanceLock.lock(); + if (!instances.containsKey(id)) { + VUI value = new VUI(id); + instances.put(id, value); + instanceLock.unlock(); + return value; + } + instanceLock.unlock(); + return instances.get(id); + } + + /** + * Constructor of the VUI. This one is private as it can only be created through + * static method. + * + * @param title + * The title used for the vui + */ + private VUI(String title) { + Semaphore done = new Semaphore(0); + RunLaterHelper.runLater(() -> { + panel = new BorderPane(); + + toolbar = new ToolBar(); + statusLabel = new Label("status"); + statusLabel.setTextAlignment(TextAlignment.LEFT); + toolbar.getItems().add(statusLabel); + panel.setBottom(toolbar); + + Button resetButton = new Button("Reset"); + resetButton.setOnAction(new EventHandler<ActionEvent>() { + @Override + public void handle(ActionEvent event) { + zoom = defaultZoom; + worldCenterX = defaultWorldCenterX; + worldCenterY = defaultWorldCenterY; + updateCanvas(); + } + }); + toolbar.getItems().add(resetButton); + + canvas = new Pane(); + canvas.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY))); + // clip the canvas (avoid drawing outside of it) + Rectangle clip = new Rectangle(0, 0, 0, 0); + clip.widthProperty().bind(canvas.widthProperty()); + clip.heightProperty().bind(canvas.heightProperty()); + canvas.setClip(clip); + + canvas.setOnMousePressed(new EventHandler<MouseEvent>() { + @Override + public void handle(MouseEvent event) { + lastDragX = event.getX(); + lastDragY = event.getY(); + } + }); + canvas.setOnMouseExited(new EventHandler<MouseEvent>() { + @Override + public void handle(MouseEvent event) { + lastDragX = null; + lastDragY = null; + } + }); + canvas.setOnMouseDragged(new EventHandler<MouseEvent>() { + @Override + public void handle(MouseEvent event) { + try { + double transX = screenToWorldDistance(event.getX() - lastDragX); + double transY = screenToWorldDistance(event.getY() - lastDragY); + worldCenterX += transX; + worldCenterY += transY; + worldOffsetX += transX; + worldOffsetY += transY; + lastDragX = event.getX(); + lastDragY = event.getY(); + updateCanvas(); + } catch (Exception ez) { + // Catch exception occurring when mouse is out of the canvas + } + } + }); + + canvas.setOnScroll(new EventHandler<ScrollEvent>() { + @Override + public void handle(ScrollEvent event) { + double wdx = screenToWorldDistance(canvas.getWidth() / 2 - event.getX()); + double wdy = screenToWorldDistance(canvas.getHeight() / 2 - event.getY()); + zoom += event.getDeltaY() / event.getMultiplierY() * 10; + if (zoom < 10) + zoom = 10; + + double wdx2 = screenToWorldDistance(canvas.getWidth() / 2 - event.getX()); + double wdy2 = screenToWorldDistance(canvas.getHeight() / 2 - event.getY()); + worldCenterX -= wdx2 - wdx; + worldCenterY -= wdy2 - wdy; + updateCanvas(); + } + }); + + panel.setCenter(canvas); + + //add VuiExplorer + vuiExplorer = new VuiExplorer(this); + panel.setLeft(vuiExplorer); + Button veButton = new Button("VUI explorer"); + veButton.setOnAction(new EventHandler<ActionEvent>() { + @Override + public void handle(ActionEvent event) { + panel.setLeft(vuiExplorer); + } + }); + veButton.setTooltip(new Tooltip("Show the VUI explorer if it was hidden.")); + toolbar.getItems().add(veButton); + + done.release(); + }); + try { + done.acquire(); + } catch (InterruptedException e) { + System.err.println("Failed to make sure that the VUI is correctly initialized."); + e.printStackTrace(); + } + } + + /** + * Convert a distance in the world to its equivalent on the screen + * + * @param d + * the in world distance + * @return the on screen distance + */ + public double worldToScreenDistance(double d) { + return d * getZoomFactor(); + } + + /** + * Convert a distance on the screen to its equivalent in the world + * + * @param d + * the on screen distance + * @return the in world distance + */ + public double screenToWorldDistance(double d) { + return d / getZoomFactor(); + } + + /** + * Convert a X in the world to its equivalent on the screen + * + * @param x + * the X in world + * + * @return the X on screen distance + */ + public double worldToScreenX(double x) { + return (x + getWorldOffsetX()) * getZoomFactor(); + } + + /** + * A value that must be multiplied to scale objects + * + * @return the zoom factor + */ + public double getZoomFactor() { + return zoom / 100; + } + + /** + * Convert a Y in the world to its equivalent on the screen + * + * @param y + * the Y in world + * + * @return the Y on screen distance + */ + public double worldToScreenY(double y) { + return (-y + getWorldOffsetY()) * getZoomFactor(); + } + + /** + * Convert a X on the screen to its equivalent in the world + * + * @param x + * the X on screen + * + * @return the X in the world distance + */ + public double screenToWorldX(double x) { + return x / getZoomFactor() - getWorldOffsetX(); + } + + /** + * Convert a Y on the screen to its equivalent in the world + * + * @param y + * the Y on screen + * + * @return the Y in the world distance + */ + public double screenToWorldY(double y) { + return -y / getZoomFactor() + getWorldOffsetY(); + } + + /** + * Add a drawable to the VUI. + * + * @param d + * the new drawable + */ + public void add(Drawable d) { + d.setVUI(this); + RunLaterHelper.runLater(()-> canvas.getChildren().add(d.getNode())); + drawablesLock.lock(); + drawables.add(d); + drawablesLock.unlock(); + updateCanvas(); + } + + /** + * Remove a drawable from the VUI. + * + * @param d + * the new drawable + */ + public void remove(Drawable d) { + drawablesLock.lock(); + drawables.remove(d); + drawablesLock.unlock(); + RunLaterHelper.runLater(()-> canvas.getChildren().remove(d.getNode())); + updateCanvas(); + } + + /** + * Remove all drawables from the VUI. + */ + public void clear() { + drawablesLock.lock(); + drawables.clear(); + RunLaterHelper.runLater(()->canvas.getChildren().clear()); + drawablesLock.unlock(); + } + + /** + * Refresh the canvas + */ + public void updateCanvas() { + final double w = canvas.getWidth(); + final double h = canvas.getHeight(); + + setWorldOffsetX(worldCenterX + screenToWorldDistance(w / 2)); + setWorldOffsetY(worldCenterY + screenToWorldDistance(h / 2)); + + drawablesLock.lock(); + Collections.sort(drawables, (o1, o2) -> o1.getLayer() - o2.getLayer()); + for (Drawable d : drawables) + RunLaterHelper.runLater(()-> d.onDraw()); + drawablesLock.unlock(); + + RunLaterHelper.runLater(() -> { + statusLabel.setText(String.format("Zoom: %.2f Center: (%.2f,%.2f)", zoom, worldCenterX, worldCenterY)); + }); + + RunLaterHelper.runLater(()-> vuiExplorer.update(true)); + } + + /** + * Get the width of the canvas + * + * @return the canvas width + */ + public double getCanvasWidth() { + return canvas.getWidth(); + } + + /** + * Get the height of the canvas + * + * @return the canvas height + */ + public double getCanvasHeight() { + return canvas.getHeight(); + } + + /** + * Get the value that must be added to the X coordinate of in world object + * + * @return the X offset + */ + public double getWorldOffsetX() { + return worldOffsetX; + } + + /** + * Set the value that must be added to the X coordinate of in world object + * + * @param offsetX + * the X offset + */ + public void setWorldOffsetX(double offsetX) { + this.worldOffsetX = offsetX; + } + + /** + * Get the value that must be added to the Y coordinate of in world object + * + * @return the Y offset + */ + public double getWorldOffsetY() { + return worldOffsetY; + } + + /** + * Set the value that must be added to the Y coordinate of in world object + * + * @param offsetY + * the Y offset + */ + public void setWorldOffsetY(double offsetY) { + this.worldOffsetY = offsetY; + } + + /** + * Create a point and start rendering it + * + * @param dx + * the x coordinate + * @param dy + * the y coordinate + * @return the point object + */ + public DrawablePoint createAndAddPoint(double dx, double dy) { + DrawablePoint drawablePoint = new DrawablePoint(dx, dy); + add(drawablePoint); + return drawablePoint; + } + + /** + * Create a rectangle and start rendering it + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param w + * the width + * @param h + * the height + * @return the rectangle object + */ + public DrawableRectangle createAndAddRectangle(double x, double y, double w, double h) { + DrawableRectangle d = new DrawableRectangle(x, y, w, h); + add(d); + return d; + } + + /** + * Set the default configuration of the view + * + * @param zoom + * the initial zoom value + * @param worldCenterX + * the initial X center value + * @param worldCenterY + * the initial Y center value + */ + public void setDefaultView(double zoom, double worldCenterX, double worldCenterY) { + this.zoom = zoom; + this.worldCenterX = worldCenterX; + this.worldCenterY = worldCenterY; + this.defaultZoom = zoom; + this.defaultWorldCenterX = worldCenterX; + this.defaultWorldCenterY = worldCenterY; + } + + /** + * Create an image and start rendering it + * + * @param dx + * the x coordinate + * @param dy + * the y coordinate + * @param filename + * the filename of the image + * @return the created image + */ + public DrawableImage createAndAddImage(double dx, double dy, String filename) { + DrawableImage image = new DrawableImage(dx, dy, filename); + add(image); + return image; + } + + /** + * Create a string and start rendering it + * + * @param dx + * the x coordinate + * @param dy + * the y coordinate + * @param text + * the text to display + * @return the created string + */ + public DrawableString createAndAddString(int dx, int dy, String text) { + DrawableString ds = new DrawableString(dx, dy, text); + add(ds); + return ds; + } + + public Pane getCanvas() { + return canvas; + } + + public BorderPane getPanel() { + return panel; + } + + public List<Drawable> getDrawables() { + return drawables; + } +} diff --git a/AMAKFX/tests/agent/TestAgentTwoPhaseScheduling.java b/AMAKFX/tests/agent/TestAgentTwoPhaseScheduling.java index 31f38213..5457b79b 100644 --- a/AMAKFX/tests/agent/TestAgentTwoPhaseScheduling.java +++ b/AMAKFX/tests/agent/TestAgentTwoPhaseScheduling.java @@ -95,7 +95,7 @@ public class TestAgentTwoPhaseScheduling { public class TestAMAS extends Amas<TestEnv> { public TestAMAS(TestEnv environment) { - super(null, environment, Scheduling.HIDDEN); + super(environment, Scheduling.HIDDEN); } @Override diff --git a/AMAKFX/tests/testutils/ObjectsForAgentTesting.java b/AMAKFX/tests/testutils/ObjectsForAgentTesting.java index 4c4a1645..a029283f 100644 --- a/AMAKFX/tests/testutils/ObjectsForAgentTesting.java +++ b/AMAKFX/tests/testutils/ObjectsForAgentTesting.java @@ -39,13 +39,13 @@ public class ObjectsForAgentTesting { public class TestEnv extends Environment { public TestEnv() { - super(null, Scheduling.HIDDEN); + super(Scheduling.HIDDEN); } } public class TestAMAS extends Amas<TestEnv> { public TestAMAS(TestEnv environment) { - super(null, environment, Scheduling.HIDDEN); + super(environment, Scheduling.HIDDEN); } } } -- GitLab