package org.jactr.tools.experiment.misc; /* * default logging */ import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.concurrent.ModelCycleExecutor; import org.jactr.core.model.IModel; import org.jactr.core.module.procedural.six.learning.IProceduralLearningModule6; import org.jactr.core.queue.timedevents.RunnableTimedEvent; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.core.runtime.controller.IController; public class ModelUtilities { static private final transient Log LOGGER = LogFactory .getLog(ModelUtilities.class); /** * reward/punish the model using {@link #executeLater(IModel, Runnable)} * * @param model * @param reward * @return * @throws IllegalStateException */ static public Future<Boolean> reward(final IModel model, final double reward) throws IllegalStateException { return executeNow(model, new Runnable() { public void run() { IProceduralLearningModule6 plm = (IProceduralLearningModule6) model .getModule(IProceduralLearningModule6.class); if (plm != null) plm.reward(reward); else if (LOGGER.isWarnEnabled()) LOGGER.warn(String.format( "Cannot reward %1$s, no IProceduralLearningModule6 installed.", model)); } }); } /** * will execute the runnable on the model thread at the earliest possible * moment * * @param model * @param runnable * @return future boolean if the runnable was fired (false if aborted) * @throws IllegalStateException * if the model is not running */ static public Future<Boolean> executeLater(IModel model, final Runnable onFire, final Runnable onAbort) throws IllegalStateException { IController controller = ACTRRuntime.getRuntime().getController(); if (controller == null || !controller.isRunning()) throw new IllegalStateException("Model is not running"); double now = ACTRRuntime.getRuntime().getClock(model).getTime(); final ExecuteLater<Boolean> future = new ExecuteLater<Boolean>(); Runnable fire = new Runnable() { public void run() { try { onFire.run(); future.setResult(true); } catch (Exception e) { future.setException(e); } } }; Runnable abort = new Runnable() { public void run() { try { if (onAbort != null) onAbort.run(); future.setResult(false); } catch (Exception e) { future.setException(e); } } }; model.getTimedEventQueue().enqueue( new RunnableTimedEvent(now, fire, abort)); return future; } /** * post this runnable to execute after the current cycle finishes * @param model * @param onFire * @return */ static public Future<Boolean> executeNow(IModel model, final Runnable onFire) { IController controller = ACTRRuntime.getRuntime().getController(); if (controller == null || !controller.isRunning()) throw new IllegalStateException("Model is not running"); final ExecuteLater<Boolean> future = new ExecuteLater<Boolean>(); Runnable fire = new Runnable() { public void run() { try { onFire.run(); future.setResult(true); } catch (Exception e) { future.setException(e); } } }; new ModelCycleExecutor(model, ModelCycleExecutor.When.ASAP).execute(fire); return future; } static public Future<Boolean> executeLater(IModel model, Runnable onFire) throws IllegalStateException { return executeLater(model, onFire, null); } static private class ExecuteLater<T> extends FutureTask<T> { public ExecuteLater() { super(new Runnable() { public void run() { } }, null); } public void setResult(T result) { set(result); } public void setException(Throwable thrown) { super.setException(thrown); } } }