Hi guys,
I'm new to drools, and i'm trying to build a small prototype.
I have 2 entities in my model: Offers and Bids. Both have a size (and a price). I need a rule that matches a single Bid with multiple Offers adding up in size to the Bid size. Matched Offers have to be sorted by (increasing) insertion time .
I have managed to write a rule using 'accumulate', but i feel it's not too efficient, since i have to match every Offer in the working memory with the right price, sort them and then pick the first n ones.
Here's the rule:
rule "Match Bids"
when
$b : Bid($s:size, $p:price)
$i : OfferAccumulator(acumSize >= $s) from accumulate ( $o:Offer(price<=$p) ,
init(OfferAccumulator accum = new OfferAccumulator($s); ),
action( accum.add($o);),
reverse ( accum.remove($o);),
result( accum ))
then
System.out.println( "Matched Bid:" + $b + "," + $i.getOffers());
end
and here's OfferAccumulator:
public class OfferAccumulator {
private int sizeLimit=0;
private int accumSize=0;
Set<Offer> offers = new TreeSet<Offer>();
public OfferAccumulator(int sizeLimit) {
this.sizeLimit = sizeLimit;
}
public void add(Offer op) {
accumSize+=op.getSize();
offers.add(op);
}
public void remove(Offer op) {
if (offers.remove(op)) {
accumSize-=op.getSize();
}
}
public List<Offer> getOffers() {
List<Offer> ret = new ArrayList<Offer>();
int accum=0;
Iterator<Offer> it = offers.iterator();
while (it.hasNext() && acum<sizeLimit) {
Offer offer = it.next();
accum+=offer.getSize();
ret.add(offer);
}
return ret;
}
}
Can you think of a more efficient way of achieving the same result? Is there a way of controlling the order in which facts are feeded to the accumulator?
Thanks in advance!
Andres