package org.jactr.tools.track.chunktype; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.buffer.IActivationBuffer; import org.jactr.core.buffer.event.ActivationBufferEvent; import org.jactr.core.buffer.event.ActivationBufferListenerAdaptor; import org.jactr.core.buffer.event.IActivationBufferListener; import org.jactr.core.chunk.IChunk; import org.jactr.core.concurrent.ExecutorServices; import org.jactr.core.model.IModel; import org.jactr.core.model.event.IModelListener; import org.jactr.core.model.event.ModelEvent; import org.jactr.core.model.event.ModelListenerAdaptor; import org.jactr.core.module.procedural.event.IProceduralModuleListener; import org.jactr.core.module.procedural.event.ProceduralModuleEvent; import org.jactr.core.module.procedural.event.ProceduralModuleListenerAdaptor; import org.jactr.core.production.IInstantiation; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.core.utils.RollingFileWriter; import org.jactr.core.utils.StringUtilities; import org.jactr.core.utils.parameter.IParameterized; import org.jactr.core.utils.parameter.ParameterHandler; import org.jactr.instrument.IInstrument; public class ChunkTypeProductionTracker implements IInstrument, IParameterized { /** * Logger definition */ static private transient Log LOGGER = LogFactory .getLog(ChunkTypeProductionTracker.class); static public final String FILENAME = "FileName"; static public final String MAX_FILE_SIZE = "MaxFileSize"; static public final String MAX_BACKUPS = "NumberOfBackups"; private IModelListener _modelListener; private IProceduralModuleListener _proceduralListener; private IActivationBufferListener _goalListener; private String _fileName = "production.txt"; private int _backups = 3; private long _maxSize = 1; // meg private PrintWriter _output; private Sequence _currentSequence; public ChunkTypeProductionTracker() { _proceduralListener = new ProceduralModuleListenerAdaptor() { @Override public void productionFired(ProceduralModuleEvent pme) { IInstantiation instantiation = (IInstantiation) pme.getProduction(); double now = pme.getSimulationTime(); if (_currentSequence == null) { IChunk goal = pme.getSource().getModel().getActivationBuffer( IActivationBuffer.GOAL).getSourceChunk(); if (goal != null) _currentSequence = new Sequence(goal); else _currentSequence = new Sequence(); } // remove the last terminal time if (_currentSequence._firingTimes.size() != 0) _currentSequence._firingTimes.remove(_currentSequence._firingTimes .size() - 1); _currentSequence._firingTimes.add(now); _currentSequence._firingTimes.add(now + instantiation.getSubsymbolicProduction().getFiringTime()); _currentSequence._productions.add(instantiation.getProduction() .toString()); } }; _goalListener = new ActivationBufferListenerAdaptor() { @Override public void sourceChunkAdded(ActivationBufferEvent abe) { if (_currentSequence != null) { _currentSequence._terminaGoalString = StringUtilities.toString(abe .getSourceChunks().iterator().next()); dump(_currentSequence); } _currentSequence = new Sequence(abe.getSourceChunks().iterator().next()); } @Override public void sourceChunkRemoved(ActivationBufferEvent abe) { if (_currentSequence != null) { _currentSequence._terminaGoalString = StringUtilities.toString(abe .getSourceChunks().iterator().next()); dump(_currentSequence); } _currentSequence = null; } }; _modelListener = new ModelListenerAdaptor() { public void exceptionThrown(ModelEvent me) { if (_currentSequence != null) dump(_currentSequence); _currentSequence = null; } }; } public void initialize() { } public void install(IModel model) { model.addListener(_modelListener, ExecutorServices.INLINE_EXECUTOR); model.getActivationBuffer(IActivationBuffer.GOAL).addListener( _goalListener, ExecutorServices.INLINE_EXECUTOR); model.getProceduralModule().addListener(_proceduralListener, ExecutorServices.INLINE_EXECUTOR); } public void uninstall(IModel model) { model.removeListener(_modelListener); model.getActivationBuffer(IActivationBuffer.GOAL).removeListener( _goalListener); model.getProceduralModule().removeListener(_proceduralListener); } protected void dump(Sequence sequence) { StringBuilder times = new StringBuilder(); StringBuilder productions = new StringBuilder(); NumberFormat format = NumberFormat.getNumberInstance(); double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; for (Double time : sequence._firingTimes) { times.append(format.format(time)).append("\t"); if (time < min) min = time; if (time > max) max = time; } for (String production : sequence._productions) productions.append(production).append("\t"); _output.println(sequence._chunkType); _output.println(format.format(Math.max(0, max - min))); _output.println("\t" + sequence._initialGoalString); _output.println("\t" + sequence._terminaGoalString); _output.println("\t" + times.toString()); _output.println("\t" + productions.toString()); _output.println(); _output.println(); _output.flush(); } public String getParameter(String key) { return null; } public Collection<String> getPossibleParameters() { return getSetableParameters(); } public Collection<String> getSetableParameters() { return Arrays.asList(FILENAME, MAX_FILE_SIZE, MAX_BACKUPS); } public void setParameter(String key, String value) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Setting parameter " + key + "=" + value); if (FILENAME.equalsIgnoreCase(key)) _fileName = value; else if (MAX_BACKUPS.equalsIgnoreCase(key)) _backups = ParameterHandler.numberInstance().coerce(value).intValue(); else if (MAX_FILE_SIZE.equalsIgnoreCase(key)) _maxSize = ParameterHandler.numberInstance().coerce(value).longValue(); try { _output = new PrintWriter(new RollingFileWriter(ACTRRuntime.getRuntime() .getWorkingDirectory(), _fileName, _maxSize * 1024 * 1024,_backups)); } catch (Exception e) { _output = new PrintWriter(System.err); } } private class Sequence { String _chunkType; String _initialGoalString; String _terminaGoalString; Collection<String> _productions; List<Double> _firingTimes; public Sequence(IChunk goalChunk) { this(); _chunkType = goalChunk.getSymbolicChunk().getChunkType().toString(); _initialGoalString = StringUtilities.toString(goalChunk); } public Sequence() { _chunkType = "<empty>"; _initialGoalString = "<empty>"; _productions = new ArrayList<String>(); _firingTimes = new ArrayList<Double>(); } } }