Set local variable/fact in Drools rule engine - drools

I have a simple rule that is based on TaskPlanning example. It looks like this:
rule "It is better if user does not overexceeds its hours"
when
$emp : Employee()
$task : Task( $taskType : taskType, employee == $emp)
accumulate( Task(employee == $emp);
$minutesOfEmplSpend : sum($taskType.getBaseDuration());
$emp.getMinutesAvailable() < $minutesOfEmplSpend
)
then
scoreHolder.addMediumConstraintMatch(kcontext,
$emp.getMinutesAvailable()-$minutesOfEmplSpend);
end
And OK, it is working. But I would also like to add additional constraint there. $task variable has isSerious property, that holds boolean value. I would like it to be also taken into consideration when adding medium constraint.
I would like to achieve something like this:
scoreHolder.addMediumConstraintMatch(kcontext,
$emp.getMinutesAvailable()-$minutesOfEmplSpend - ($task.isSerious == true ? 100 : 10) ));
But I am getting rules errors. I think I've tried everything - please at least point me to the right direction.

Normal java code should work, try $task.isSerious() instead of $task.isSerious

Related

QgsField won't accept parameter typeName

I'm trying to create new vector layer with the same fields as contained in original layer.
original_layer_fields_list = original_layer.fields().toList()
new_layer = QgsVectorLayer("Point", "new_layer", "memory")
pr = new_layer.dataProvider()
However, when I try:
for fld in original_layer_fields_list:
type_name = fld.typeName()
pr.addAttributes([QgsField(name = fld.name(), typeName = type_name)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
I get a layer with no fields in attribute table.
If I try something like:
for fld in original_layer_fields_list:
if fld.type() == 2:
pr.addAttributes([QgsField(name = fld.name(), type = QVariant.Int)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
... it works like charm.
Anyway ... I'd rather like the first solution to work in case if one wants to automate the process and not check for every field type and then find an appropriate code. Besides - I really am not able to find any documentation about codes for data types. I managed to find this post https://gis.stackexchange.com/questions/353975/get-only-fields-with-datatype-int-in-pyqgis where in comments Kadir pointed on this sourcecode (https://codebrowser.dev/qt5/qtbase/src/corelib/kernel/qvariant.h.html#QVariant::Type).
I'd really be thankful for any kind of direction.

ZKOSS version 7.0.0 checkbox or clear radiogroup

Good morning, everyone,
I am having a problem with the handling of two checkboxes which should be mutually exclusive, on the page we cannot put an id because multiselection is provided.
enter image description here
Here the zkoss code:
<cell colspan="2">
<checkbox
label="${labels.label.giaAddebitata}"
checked="#load(each.flagAddebitata eq '1')"
onCheck="#command('addebitata', fladd=event.checked,idPer=each.idPerizia )"
onFocus="#command('manageList', idPer=each.idPerizia)"
disabled="#load(each.statoContabile eq 4 ? true : false)"/>
</cell>
<cell colspan="2">
<checkbox
label="${labels.label.nonAddebitare}"
checked="#load(each.nonAddebitare eq '1')"
onCheck="#command('nonaddebitata',flnoadd=event.checked, idPer=each.idPerizia)"
onFocus="#command('manageList', idPer=each.idPerizia)"
disabled="#load(each.statoContabile eq 4 ? true : false)"/>
</cell>
and the java functions
#Command
#NotifyChange ({ "flagAddebitata","nonAddebitare", "selectedRic"})
public void addebitata(#BindingParam("fladd") boolean fladd,#BindingParam("idPer")int idPerizia ) {
boolean addebitata = fladd;
selectedRic = new HashSet<AddebitoClienteViewDTO>();
for(AddebitoClienteViewDTO add : carList) {
if(add.getIdPerizia() == idPerizia) {
add.setFlagAddebitata(booleanToString.apply(fladd));
selectedRic.add(add);
}
}
logger.debug("SELECTEDRIC non addebitare " + selectedRic);
logger.debug("addebitata funzione " +addebitata);
}
#Command
#NotifyChange ({ "nonAddebitare", "selectedRic"})
public void nonaddebitata(#BindingParam("flnoadd") boolean flnoadd,#BindingParam("idPer")int idPerizia ) {
boolean nonaddebitata = flnoadd;
selectedRic = new HashSet<AddebitoClienteViewDTO>();
for(AddebitoClienteViewDTO add : carList) {
if(add.getIdPerizia() == idPerizia) {
add.setNonAddebitare(booleanToString.apply(flnoadd));
selectedRic.add(add);
}
}
logger.debug("SELECTEDRIC non addebitare " + selectedRic);
logger.debug("nonaddebitata funzione " +nonaddebitata);
}
We tried using the && != " the != alone and adding another binding param to the java functions.
The result we want to achieve is that if one check is clicked the other if it is already selected loses the check.
Alternatively we tried the radiogroup but it does not allow the non-selection of radioboxes, one is always mandatory.
Is there a way to clear the radiobutton without a java clear function?
Thanks
That's a lot of code and hard to turn into a reproducing case due to all of the extra objects, so I'll focus more on the functional requirement.
From your description, I understand that what you want to create is a system in which you can either select "A", "B" or "none".
There is some unspecified behavior in there (like if "A" is selected, can I select "B" and automatically clear selection on "A"? Or does having "A" selected mean that "B" is non-selectable).
From your stated requirement, the component I would choose to express that structure is a dropdown menu with 3 choices ("not selected", "A", "B"), but that might not be what you are trying to achieve with the UI design here?
If you want to make something like that using checkboxes, you may want to keep a single state for the selection status, and a command to update the selection status.
See a simple code sample here: https://zkfiddle.org/sample/hb7f7k/1-Another-new-ZK-fiddle
The left 2 checkboxes work on a "unselect others if selected" workflow.
The right 2 checkboxes work on a "cannot select others while selected, but can unselect" workflow.
Note: that sample is a "bare minimum" implementation. In a real case, you'd improve it by factorizing the code, making it into a template, etc. rather than declaring these values inline.

Parametrize the after operator in drools

i have a fairly simple question, i have this rule
rule 'Rule1'
when
$inMess : MetaMessage()
not(MetaMessage(this after[0, 10000] $inMess, this != $inMess))
then
log.info("Message id:"+ $inMess.getId());
end
It works perfectly (in the after operand, if you use only a number it assumes milliseconds), i have only one other thing to do, parametrize the after operator so it can accept a property of the MetaMessage.
Something like this
rule 'Rule1'
when
$inMess : MetaMessage($delay : delay)
not(MetaMessage(this after[0, $delay] $inMess, this != $inMess))
then
log.info("Message id:"+ $inMess.getId());
end
Is there a way to do this?

OptaPlanner : I tried to print out the justificationList of ConstraintMatch, but got objects of SubnetworkTuple which are not my domain classes

I'm using OptaPlanner to solve a planning problem. I use drools to do score calculation. When I tried to print out the justificationList of each constraintMatch, I got objects which are instances of SubnetworkTuple besides my domain class objects. These seem to be objects that are used in
its internal implementation.
I have not used drools rule engine before :) . And this is my first time to use OptaPlanner. As far I know, justificationList should contain all objects that are involved in that rule.
drools rule:
rule "roomPriority"
when
EduClassRoomPriority($left : leftEduClass, $right : rightEduClass, $priority : priority)
exists(LectureOfEduClass(eduClass == $left,$room1 : room ) and LectureOfEduClass(eduClass == $right, $room1 != room))
then
scoreHolder.addSoftConstraintMatch(kcontext,-$priority);
end
java:
for (ConstraintMatchTotal constraintMatchTotal : constraintMatchTotals) {
String constraintName = constraintMatchTotal.getConstraintName();
Score totalScore = constraintMatchTotal.getScore();
Set<ConstraintMatch> constraintMatchSet = constraintMatchTotal.getConstraintMatchSet();
logger.info(totalScore.toShortString() + " constraint(" + constraintName + ") has " + constraintMatchSet.size() + " matches");
for (ConstraintMatch constraintMatch : constraintMatchSet) {
List<Object> justificationList = constraintMatch.getJustificationList();
Score score = constraintMatch.getScore();
logger.info(score.toShortString() + justificationList.toString());
}
}
I wonder what I can do to fix that problem, because these extra objects would confuse users. I can do instance of check. But That shouldn't be the right way to resolve it.
Thank everyone in advance.
Caused and fixed by https://issues.jboss.org/browse/DROOLS-4423 for 7.26.

Drools MVEL Dialect - Semi-Colon Requirement

I am just curious as to why my Eclipse Drools compiler (6.5.0) requires semi-colons at the end of statements in the For loop, as below:
Map businessRulesRequest = $root.containsKey("BusinessRulesRequest") ? $root.get("BusinessRulesRequest") : null
Map quoteRequest = businessRulesRequest!=null && businessRulesRequest.containsKey("QuoteRequest") ? businessRulesRequest.get("QuoteRequest") : null
List resultsByKey = quoteRequest!=null && quoteRequest.containsKey("resultsByKey") ? quoteRequest.get("resultsByKey") : new ArrayList()
for (Map search : resultsByKey) {
Map searchInfo = (search.containsKey("searchInfo") ? search.get("searchInfo") : null);
String searchName = searchInfo!=null && searchInfo.containsKey("searchName") ? searchInfo.get("searchName").toString() : "";
List results = (searchName=="quotesMotor" && search.containsKey("results") ? search.get("results") : new ArrayList());
}
If I remove the semi-colons from the first or second lines in the For loop, I get an "unexpected token" error, but not if I remove it from the last line in the loop.
Is it due to Drools evaluating RHS lines as a single statement and so they must be separated inside any loops?
Note: I understand it is not best practice to code assuming semi-colons are not required, however I came across this issue while experimenting and am just interested to know the reason for the compiler error. Thanks.
I guess the answer is because of MVEL itself. Drools may be delegating the entire chunk of code to MVEL to evaluate and execute.
According to this guide, in MVEL the use of a semi-colon is not mandatory in cases where you have 1 statement, or in the last statement of a script.
Hope it helps,