/**
* Set off departure offsets (immutable)
*
* @author ab
*/
package btools.memrouter;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
public class OffsetSet
{
private Map<BitSet, OffsetSet> existingSets = new HashMap<BitSet, OffsetSet>();
private static final int size = 185;
protected BitSet mask;
public OffsetSet emptySet()
{
return new OffsetSet( new BitSet( size ), existingSets );
}
public static OffsetSet fullSet()
{
BitSet allbits = new BitSet( size );
allbits.set( 0, size );
return new OffsetSet( allbits, new HashMap<BitSet, OffsetSet>() );
}
private OffsetSet( BitSet m, Map<BitSet, OffsetSet> knownSets )
{
existingSets = knownSets;
existingSets.put( m , this );
mask = m;
}
private OffsetSet create( BitSet m )
{
if ( m.isEmpty() )
{
return null;
}
if ( m.equals( mask ) )
{
return this;
}
OffsetSet set = existingSets.get( m );
if ( set == null )
{
set = new OffsetSet( m, existingSets );
// System.out.println( "created set: " + set + " instancecount=" + existingSets.size() );
}
return set;
}
public OffsetSet create( List<Integer> offsets )
{
BitSet m = new BitSet( size );
for ( Integer offset : offsets )
{
int i = offset.intValue();
if ( i >= 0 && i < size )
{
m.set( i );
}
}
return create( m );
}
public OffsetSet filterWithSet( SortedSet<Integer> usedTimes, int minuteArrival )
{
BitSet fmask = (BitSet)mask.clone();
int idx = 0;
int maxtime = usedTimes.isEmpty() ? Integer.MAX_VALUE: usedTimes.first().intValue() + size();
for(;;)
{
idx = fmask.nextSetBit( idx );
if ( idx < 0 ) break;
int i = minuteArrival + idx;
if ( i > maxtime || !usedTimes.add( Integer.valueOf(i) ) )
{
fmask.set( idx, false );
}
idx++;
}
return create( fmask );
}
public int size()
{
return size;
}
public boolean contains( int offset )
{
return mask.get( offset );
}
public OffsetSet add( int offset )
{
if ( mask.get( offset ) )
{
return this;
}
BitSet m = (BitSet)mask.clone();
m.set( offset );
return create( m );
}
public OffsetSet add( OffsetSet offsets )
{
BitSet m = (BitSet)mask.clone();
m.or( offsets.mask );
return create( m );
}
// clear all bits from this set in the argument set
public OffsetSet filter( OffsetSet in )
{
BitSet fmask = (BitSet)in.mask.clone();
fmask.andNot( mask );
return create( fmask );
}
public OffsetSet ensureMaxOffset( int max )
{
if ( max < size )
{
BitSet fmask = (BitSet)mask.clone();
fmask.set( max > 0 ? max : 0, size, false );
return create( fmask );
}
return this;
}
public OffsetSet filterAndClose( OffsetSetHolder gateHolder, boolean closeGate )
{
OffsetSet gate = gateHolder.getOffsetSet();
BitSet gmask = (BitSet)gate.mask.clone();
BitSet fmask = (BitSet)mask.clone();
fmask.andNot( gmask );
gmask.or( fmask );
if ( closeGate )
{
gateHolder.setOffsetSet( create( gmask ) ); // modify the gate
}
return create( fmask );
}
public OffsetSet sweepWith( OffsetSet sweeper, int timeDiff )
{
BitSet sweepmask = sweeper.mask;
BitSet fmask = (BitSet)mask.clone();
if ( timeDiff >= 0 )
{
int idx = 0;
for(;;)
{
idx = sweepmask.nextSetBit( idx ) + 1;
if ( idx < 1 ) break;
int sweepStart = Math.max( 0, idx-timeDiff );
fmask.set( sweepStart, idx, false );
}
int sweepStart = Math.max( 0, size-timeDiff );
fmask.set( sweepStart, size, false );
}
// System.out.println( "sweep: " + mask + " with: " + sweepmask + "=" + fmask );
return create( fmask );
}
@Override
public String toString()
{
return mask.toString();
}
}