package dailyBot.model;
import java.beans.XMLEncoder;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import dailyBot.analysis.SignalHistoryRecord;
import dailyBot.control.DailyLog;
import dailyBot.control.DailyProperties;
import dailyBot.control.DailyUtils;
import dailyBot.model.SignalProvider.SignalProviderId;
import dailyBot.model.Strategy.StrategyId;
public class MultiFilter implements Serializable
{
private static final long serialVersionUID = -2010581534111176537L;
protected final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
protected final Lock read = readWriteLock.readLock();
protected final Lock write = DailyUtils.getSafeWriteLock(readWriteLock);
private boolean active = false;
private boolean[][][] activeArray = new boolean[StrategyId.values().length][Pair.values().length][2];
private int[][][] activeFilters = new int[StrategyId.values().length][Pair.values().length][2];
private Filter[] filters = new Filter[0];
private SignalProviderId id;
public MultiFilter()
{
}
public MultiFilter(SignalProviderId id)
{
this.id = id;
}
public void startFilters()
{
String[] filterNames = DailyProperties.getProperty("dailyBot.model.MultiFilter." + id + ".filters").split(",");
Filter[] newFilters = new Filter[filterNames.length];
int i = 0;
for(String filter : filterNames)
{
String type = DailyProperties.getProperty("dailyBot.model.Filter." + filter + ".type");
if(type == null)
throw new RuntimeException("Null filter type in provider: " + id);
if(type.equals("external"))
newFilters[i++] = new ExternalProcessFilter(filter, id.toString() + "." + filter);
else if(type.equals("basic"))
newFilters[i++] = new BasicFilter();
else
throw new RuntimeException("Unknown filter type: " + type + " in provider: " + id);
}
write.lock();
try
{
this.filters = newFilters;
}
finally
{
write.unlock();
}
}
public boolean hasActive(StrategyId strategyId, Pair pair, boolean isBuy)
{
read.lock();
try
{
return activeArray[strategyId.ordinal()][pair.ordinal()][isBuy ? 1 : 0] && active;
}
finally
{
read.unlock();
}
}
public void changeActive(StrategyId strategyId, Pair pair, boolean isBuy, boolean active)
{
write.lock();
try
{
activeArray[strategyId.ordinal()][pair.ordinal()][isBuy ? 1 : 0] = active;
}
finally
{
write.unlock();
}
}
public void changeActiveFilter(StrategyId strategyId, Pair pair, boolean isBuy, int newValue)
{
write.lock();
try
{
activeFilters[strategyId.ordinal()][pair.ordinal()][isBuy ? 1 : 0] = newValue;
}
finally
{
write.unlock();
}
}
public boolean[][][] getActiveArray()
{
read.lock();
try
{
return activeArray;
}
finally
{
read.unlock();
}
}
private boolean[][][] fixSize(boolean[][][] array)
{
int sizeX = StrategyId.values().length;
int sizeY = Pair.values().length;
int sizeZ = 2;
if(array.length != sizeX || array.length == 0 || array[0].length != sizeY)
{
boolean[][][] newArray = new boolean[sizeX][sizeY][sizeZ];
for(int i = 0; i < Math.min(array.length, newArray.length); i++)
if(newArray.length != 0 && array.length != 0)
for(int j = 0; j < Math.min(array[0].length, newArray[0].length); j++)
if(newArray[0].length != 0 && array[0].length != 0)
for(int k = 0; k < Math.min(array[0][0].length, newArray[0][0].length); k++)
newArray[i][j][k] = array[i][j][k];
return newArray;
}
else
return array;
}
public void setActiveArray(boolean[][][] activeArray)
{
write.lock();
try
{
this.activeArray = fixSize(activeArray);
}
finally
{
write.unlock();
}
}
public int[][][] getActiveFilters()
{
read.lock();
try
{
return activeFilters;
}
finally
{
read.unlock();
}
}
private int[][][] fixSize(int[][][] array)
{
int sizeX = StrategyId.values().length;
int sizeY = Pair.values().length;
int sizeZ = 2;
if(array.length != sizeX || array.length == 0 || array[0].length != sizeY)
{
int[][][] newArray = new int[sizeX][sizeY][sizeZ];
for(int i = 0; i < Math.min(array.length, newArray.length); i++)
if(newArray.length != 0 && array.length != 0)
for(int j = 0; j < Math.min(array[0].length, newArray[0].length); j++)
if(newArray[0].length != 0 && array[0].length != 0)
for(int k = 0; k < Math.min(array[0][0].length, newArray[0][0].length); k++)
newArray[i][j][k] = array[i][j][k];
return newArray;
}
else
return array;
}
public void setActiveFilters(int[][][] activeFilters)
{
write.lock();
try
{
this.activeFilters = fixSize(activeFilters);
}
finally
{
write.unlock();
}
}
public boolean isActive()
{
read.lock();
try
{
return active;
}
finally
{
read.unlock();
}
}
public void setActive(boolean active)
{
write.lock();
try
{
this.active = active;
}
finally
{
write.unlock();
}
}
public SignalProviderId getId()
{
read.lock();
try
{
return id;
}
finally
{
read.unlock();
}
}
public synchronized void setId(SignalProviderId id)
{
write.lock();
try
{
this.id = id;
}
finally
{
write.unlock();
}
}
public boolean filter(SignalHistoryRecord record, boolean sendMessage, double entryPrice)
{
read.lock();
try
{
if((!active) || (!activeArray[record.id.ordinal()][record.pair.ordinal()][record.buy ? 1 : 0]))
return false;
int activeInt = activeFilters[record.id.ordinal()][record.pair.ordinal()][record.buy ? 1 : 0];
boolean or = (activeInt & 1) == 1;
activeInt >>= 1;
if(filters.length == 0 || activeInt == 0)
return false;
boolean ok = or ? false : true;
boolean any = false;
String message = "Intentando abrir " + id.toString() + ", " + record.id.toString() + ", "
+ record.pair.toString() + ", " + entryPrice + ", "
+ (record.buy ? "BUY" : "SELL");
message += " precio actual: " + record.pair.getCurrentPrice(record.buy) + "\n";
for(int i = 0; i < filters.length; i++)
{
if((activeInt & 1) == 1)
{
any = true;
boolean current = filters[i].filter(record);
if(or)
ok = ok || current;
else
ok = ok && current;
message += filters[i].getName() + ": " + current + "\n";
}
activeInt >>= 1;
}
if(sendMessage)
DailyLog.addRangeInfo("intentos de apertura", message);
return any && ok;
}
finally
{
read.unlock();
}
}
public void writePersistence()
{
try
{
FileOutputStream fos = new FileOutputStream("filters/" + id + ".xml");
XMLEncoder encoder = new XMLEncoder(fos);
encoder.writeObject(this);
encoder.close();
fos.close();
}
catch(Exception e)
{
DailyLog.logError("Error writing filter: " + id.name() + " " + e.getMessage());
}
}
public Filter[] filters()
{
read.lock();
try
{
return filters;
}
finally
{
read.unlock();
}
}
public void changeFilters(Filter[] filters)
{
write.lock();
try
{
this.filters = filters;
}
finally
{
write.unlock();
}
}
}