package org.jactr.modules.pm.aural.memory.impl.filter;
/*
* default logging
*/
import java.util.Comparator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.production.request.ChunkTypeRequest;
import org.jactr.core.slot.IConditionalSlot;
import org.jactr.modules.pm.aural.IAuralModule;
import org.jactr.modules.pm.common.memory.filter.AbstractIndexFilter;
import org.jactr.modules.pm.common.memory.filter.IIndexFilter;
import org.jactr.modules.pm.visual.IVisualModule;
/**
* provides nearest filtering and also normalizes all references to current,
* highest,lowest
*
* @author harrison
*/
public class NearestAuralFilter extends
AbstractIndexFilter<Double>
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(NearestAuralFilter.class);
private final double[] _referenceLocation;
final private IAuralModule _auralModule;
public NearestAuralFilter(IAuralModule auralModule)
{
this(new double[2],auralModule);
}
public NearestAuralFilter(double[] referenceLocation, IAuralModule auralModule)
{
_auralModule = auralModule;
_referenceLocation = new double[referenceLocation.length];
System.arraycopy(referenceLocation, 0, _referenceLocation, 0,
referenceLocation.length);
}
public IAuralModule getAuralModule()
{
return _auralModule;
}
@Override
protected Double compute(ChunkTypeRequest request)
{
IChunk visualLocation = getVisualLocation(request);
if (visualLocation != null)
{
double[] coords = getCoordinates(visualLocation);
double sqDistance = 0;
// length may be 2 or 3 (if depth was provided)
int len = Math.min(coords.length, _referenceLocation.length);
for (int i = 0; i < len; i++)
sqDistance += Math.pow(coords[i] - _referenceLocation[i], 2);
return sqDistance;
}
return null;
}
/*
* if we've gotten this far..
*/
public boolean accept(ChunkTypeRequest template)
{
return get(template)!=null;
}
public Comparator<ChunkTypeRequest> getComparator()
{
return new Comparator<ChunkTypeRequest>() {
public int compare(ChunkTypeRequest o1, ChunkTypeRequest o2)
{
if (o1 == o2) return 0;
Double d1 = get(o1);
Double d2 = get(o2);
if (d1 < d2) return -1;
if (d1 > d2) return 1;
return 0;
}
};
}
public IIndexFilter instantiate(ChunkTypeRequest request)
{
int index = 0;
double[] location = null;
for (IConditionalSlot cSlot : request.getConditionalSlots())
{
/*
* I should do the validity test here
*/
index++;
if (IVisualModule.NEAREST_SLOT.equals(cSlot.getName())
&& cSlot.getCondition() == IConditionalSlot.EQUALS)
{
IChunk visualLocation = (IChunk) cSlot.getValue();
if (visualLocation != null)
{
location = getCoordinates(visualLocation);
break;
}
else if (LOGGER.isWarnEnabled())
LOGGER.warn("nearest was null, ignoring");
}
}
if (location == null) return null;
// NearestAuralFilter filter = new NearestAuralFilter(
// location);
// filter.setWeight(index);
// filter.setPerceptualMemory(getPerceptualMemory());
//
// return filter;
return null;
}
// public void normalizeRequest(ChunkTypeRequest searchRequest)
// {
// IChunk currentLocation = getVisualMemory().getVisualModule()
// .getVisualLocationBuffer().getCurrentVisualLocation();
//
// if (currentLocation == null)
// currentLocation = getVisualMemory().getVisualLocationChunkAt(0, 0);
//
// for (IConditionalSlot cSlot : searchRequest.getConditionalSlots())
// {
// if (!(cSlot.getValue() instanceof IChunk)) continue;
//
// String chunkName = ((IChunk) cSlot.getValue()).getSymbolicChunk()
// .getName();
//
// if (IVisualModule.CURRENT_CHUNK.equals(chunkName))
// {
// /*
// * resolve the current chunk - but how? for all cases but one, the
// * conditional slot named "x" will have its value assigned to
// * currentLocation's slot named "x". Unless the slots name is NEAREST,
// * in which case the value of the conditional slot will be the current
// * chunk itself
// */
// if (IVisualModule.NEAREST_SLOT.equals(cSlot.getName()))
// cSlot.setValue(currentLocation);
// else
// cSlot.setValue(currentLocation.getSymbolicChunk().getSlot(
// cSlot.getName()).getValue());
// }
// else if (IVisualModule.LESS_THAN_CURRENT_CHUNK.equals(chunkName))
// {
// cSlot.setCondition(IConditionalSlot.LESS_THAN);
// cSlot.setValue(currentLocation.getSymbolicChunk().getSlot(
// cSlot.getName()).getValue());
// }
// else if (IVisualModule.GREATER_THAN_CURRENT_CHUNK.equals(chunkName))
// {
// cSlot.setCondition(IConditionalSlot.GREATER_THAN);
// cSlot.setValue(currentLocation.getSymbolicChunk().getSlot(
// cSlot.getName()).getValue());
// }
// }
// }
protected IChunk getVisualLocation(IChunk visualChunk)
{
Object location = visualChunk.getSymbolicChunk().getSlot(
IVisualModule.SCREEN_POSITION_SLOT).getValue();
if (!(location instanceof IChunk)) return null;
// if (((IChunk) location).isA(_visualLocationChunkType))
// return (IChunk) location;
return null;
}
protected IChunk getVisualLocation(ChunkTypeRequest request)
{
double x = Double.NaN;
double y = Double.NaN;
for (IConditionalSlot cSlot : request.getConditionalSlots())
if (cSlot.getCondition() == IConditionalSlot.EQUALS)
if (cSlot.getName().equals(IVisualModule.SCREEN_X_SLOT))
x = ((Number) cSlot.getValue()).doubleValue();
else if (cSlot.getName().equals(IVisualModule.SCREEN_Y_SLOT))
y = ((Number) cSlot.getValue()).doubleValue();
// if (!Double.isNaN(x) && !Double.isNaN(y))
// return _visualMemory.getVisualLocationChunkAt(x, y);
return null;
}
protected double[] getCoordinates(IChunk visualLocation)
{
double[] rtn = new double[3];
rtn[0] = ((Number) visualLocation.getSymbolicChunk().getSlot(
IVisualModule.SCREEN_X_SLOT).getValue()).doubleValue();
rtn[1] = ((Number) visualLocation.getSymbolicChunk().getSlot(
IVisualModule.SCREEN_Y_SLOT).getValue()).doubleValue();
Object depth = visualLocation.getSymbolicChunk().getSlot(
IVisualModule.SCREEN_Z_SLOT).getValue();
if (depth instanceof Number) rtn[2] = ((Number) depth).doubleValue();
return rtn;
}
}