Handling forward 1:n relationships with drools - drools

I'm trying to write a rule that applies on a set of facts based on the content of another fact. I have simplified the problem to a House with Rooms. Let's say we have something like:
House(id);
Room(id, houseId, floor, side, paint);
Now, if I want to trigger a rule on all the Houses with all Rooms in left side painted on green I would write something like:
rule "Left side 1st floor green"
when
$h: House()
forall($r: Room(houseId=$h.id, floor==1, side=="left")
Room(id == $r.id, paint == "green"))
then
//Do whatever on rule triggering
end
But what if the objects in the working memory are organized in this way:
House(id, List<> roomIds);
Room(id, floor, side, paint);
How can I write a foreach condition (or any other approach) to make the same consideration on the rooms for a given house? Does it make sense or should I better try to reorganize my objects in advance to have the relationship expressed the other way around?
Thanks

Assuming in House the List<> roomIds is a List of Room.id(s), then you can do something like:
rule "Left side 1st floor green"
when
$h: House(/* .. conditions for specific house? .. */)
$r : Room($h.roomIds contains id, floor==1, side=="left", paint == "green")
then
//Do whatever on rule triggering
end
However this is a bit unefficient, and I do agree as others replied, changing a bit the business/data model would make writing this kind of rule more idiomatic and more efficient. For example if the House did have the list of Rooms, you can also use OOPath to navigate as desired the structure.

According to your rule, you do not have houses with rooms. According to what you have defined you have houses in your working memory and you have rooms in your working memory and you try to match these.
Why don't you have a List of Rooms in your House? That would make much more sense:
House(houseId, List<Room> rooms)
Room(roomId, floor, side, paint)
Then your rule would be:
rule "Left side 1st floor green"
when
$houses : House ($rooms : rooms, $houseId : houseId)
$room : Room ($roomId : roomId, floor==1 && side=="left" && paint == "green") from $rooms
then
//Rule would trigger for each room left side 1st floor green rooms
System.out.println("House "+$houseId+" has following left side 1st floor green room: "+$roomId);
end

Related

Calculate the force of interaction of objects in UE

I want to calculate the force of the collision. For example, the car is on the bridge, and I want to find
pressure force. In the second case, I have a falling car, and I want to find the force of the impact. Are there any functions for this?
I want to use c ++.
All you do is multiply the Mass and the Speed together
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
float HitForce = OtherActor->GetVelocity.Size() * OtherComp->GetMass();
UE_LOG(LogTemp, Warning, TEXT(HitForce));
}
HitForce is the variable you're looking for.

Calculated field affected the Grand Total in Tableau

Used a calculated field by using the window_max and window_min functions:
IF
([eCPM]) = WINDOW_MAX(([eCPM]))
THEN "Least efficient" ////Red
ELSEIF [eCPM] = WINDOW_MIN(([eCPM]))
THEN "Most efficient CPM" ///Green
ELSE "Neither" ///Gray
END
But this also affected my Grand Total. I don't want any coloring in totals. How to handle this? (Solved)
Since my calculation is based upon eCPM, can only this column be highlighted as green rather entire row, without highlighting media cost and visits green as well?
Since my calculation is based upon eCPM, can only this column be highlighted as green rather entire row, without highlighting media cost and visits green as well?
You just need to "wrap" you if statement with another one in order to handle the grand total using size which returns the number of rows in the partition.
Using the superstore you can create a calculated field like this:
// Handle Grand Total
IF SIZE() = 1 THEN "Neutral"
// Handle all other "rows"
ELSE
IF sum([Sales]) = WINDOW_MAX(sum([Sales]))
THEN "Green"
ELSEIF sum([Sales]) = WINDOW_MIN(sum([Sales]))
THEN "Red"
ELSE "Neutral"
END
END
The result could look like this:

Vehicle position tracking

I've been trying to track the velocities of vehicles in a specific road, this road have parking lots. This is the code i made to track each vehicle in a certain population, this code is running in a event block that runs every 15 seconds.
for (i = 0 ;i < car.size(); i++){
if(car(i).isCarOn(road1)){
car(i).id.setText(String.valueOf(i));
vCar = autos(i).getSpeed();
text = text + System.lineSeparator() + "Car (" + i + "):" + vCar;
}else if (car(i).isCarOn(road)){
car(i).id.setText(String.valueOf(i));
vCar = car(i).getSpeed();
text2 = text2 + System.lineSeparator() + "Car (" + i + "):" + vCar;
}
}
the issue is that when a car is changing from road to parking lot, it throws an NullPointerException error, is there a way to fix this issue track the speed of those vehicles? Also it would be great if there is an explanation for this error.
Thanks in advance
Ok, after your clarifications it's almost certain that the error occurs because the cars are getting into the road too fast and kept on the queue of the carSource.
When cars are in this queue they cannot be accessed as cars even though they exist in the car population... This is maybe weird, but it's how things are.
Now if you want to know speeds in a specific road, you should get the cars in that road:
for (Car c : road.getCars(true)){//true means forward lane
vCar=c.getSpeed();
}
for (Car c : road.getCars(false)){//false means backwards lane
vCar=c.getSpeed();
}
Nevertheless, to continue doing what you are doing, I did a video a long time ago on this topic.. unfortunately the video is a bit long (7 minutes) and boring (I was testing my youtube abilities), but it's related to your problem... it's a trick to avoid problems with this carSource queue:
https://www.youtube.com/watch?v=EgYqraEibD4

Contact and category bitmask - does only one, or both, need to be set?

So I'm learning how to check bitmask collisions in Swift and I'm confused about whether or not to set both bodies to have each other's contact bitmask.
My confusion comes from the following in the docs:
When two physics bodies overlap, a contact may occur. SceneKit
compares the body’s contact mask to the other body’s category mask by
performing a bitwise AND operation. If the result is a nonzero value,
SceneKit creates an SCNPhysicsContact object describing the contact
and sends messages to the contactDelegate object of the scene’s
physics world.
From what I understand, collisions do not need to be reciprocal - in other words, one can collide with another and the other stays without motion. Please correct me if I'm wrong. But when it comes to contact testing, if A has its category mask set to 1 and contact bitmask set to 2, and B has its category mask set to 2 and its contact bitmask set to 4, then will A and B colliding register as a contact? What if B sets its contact bitmask to 1 now? Will two collisions register?
Let me try to explain all these bit masks with an example from an actual game code. This game has the following objects: ball, pitch, ground, bat, boundary, batting stumps, bowling stumps which will have physics interactions.
Sorry the code is in ObjC, but translation to Swift is straightforward.
Step 1: Set up the category bit masks, which specify the type of each object
typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
CollisionCategoryBall = 1 << 1,
CollisionCategoryPitch = 1 << 2,
CollisionCategoryGround = 1 << 3,
CollisionCategoryBat = 1 << 4,
CollisionCategoryBoundary = 1 << 5,
CollisionCategoryBattingStumps = 1 << 6,
CollisionCategoryBowlingStumps = 1 << 7,
};
Step 2: Now we decide which objects have collisions with each other.
For example for the ball object, there are collisions with pitch, ground bat and boundary. This is setup as follows, a bitwise OR operation, assuming ballBody is a SCNPhysicsBody:
ballBody.collisionBitMask =
(CollisionCategoryPitch | CollisionCategoryGround | CollisionCategoryBat |
CollisionCategoryBoundary);
Step 3: (Optionally), if you want to be notified when two physics bodies are in contact with each other.
Here, you set up the contactTestBitMask. For the ball for example, I want to be notified when it is in contact with pitch, ground, bat, boundary. Again, to do that:
ballBody.contactTestBitMask =
(CollisionCategoryPitch | CollisionCategoryGround | CollisionCategoryBat |
CollisionCategoryBoundary);
When you set up the contactTestBitMask, you will handle the contact notifications in the physics delegate, which will be something like this:
- (void)physicsWorld:(SCNPhysicsWorld*)world
didBeginContact:(SCNPhysicsContact*)contact {
CollisionCategory contactMask = contact.nodeA.physicsBody.categoryBitMask |
contact.nodeB.physicsBody.categoryBitMask;
if ((contactMask == (CollisionCategoryBall | CollisionCategoryPitch)) &&
!self.ballLandedOnPitch) {
NSLog(#" Ball hit the pitch");
}
...
}
So overall you just categorize your objects, then setup the collision mask which is just a bitwise OR operation of the category masks of the objects with which there will be collisions and optionally to handle the contacts of bodies with each other, set up the contact test bit mask.
But when it comes to contact testing, if A has its category mask set to 1 and contact bitmask set to 2,
I am not sure if you intend to explicitly set the contact bit mask to 2 above; the contact mask should be really be a bitwise OR operation of the category masks of the objects with which there will be contacts and you want to be notified of.
I think the docs are a bit confusing and hope the above explanation clears up your doubts.

Compare value of property of all instances of class in python

I'm trying to write an object oriented program (as a learning exercise, I know there may be simpler ways to do it) in which beads bounce around a 2D plane bounded by a ring. Each bead is an object defined by a class ball. In setting the initial positions of the balls I need to check that no other ball has already been placed at the same x and y coordinates.
#Class for the beads
class ball:
NumbBalls = 0
#Constructor
def __init__(self,Beads):
self.ball = sphere(pos = vector(0,0,0), radius = radiusBall,color=color.red)
ball.NumbBalls += 1
self.ball.pos = self.createInitialPosition(Beads)
#Assign ball its initial position
def createInitialPosition(self,other):
#CODE to compare self.ball.pos and other.ball.pos which returns a unique position coordinate
#Main program
NumbBeads = 100
Beads = []#Create empty list for all the beads
#create balls in random initial positions
Beads = [ball(Beads) for item in range(NumbBeads)]
I can get this to work if I create two objects bead1 and bead2 and then pass bead1 and bead2 as arguments ie bead2 = ball(bead1) but how do I do this if I am generating a list of beads and want all of them to be compared with self. Hopefully that makes sense.
Perhaps rather than the approach you are currently taking, you should consider something along these lines (of course, with the necessary changes to your class definition/methods):
N = 100
initialPositions = []
while len(initialPositions) <= N:
newPosition = generateRandomPosition()
if newPosition in initialPositions:
pass
else:
initialPositions.append(newPosition)
ballList = [ ball(p) for p in initialPositions ]
In other words, generate a list of initial positions outside of the creation of your objects, and do whatever validation/restriction you need during that creation. Then just create your objects from that list. If N is really large, you might want to consider a dictionary (or a mutable set of some sort) instead of a list for initialPositions, to help speed up the membership testing, but it's still the same concept...