To find what all condition element is true in a rule - drools

In drool we have any option to find what all condition tuples satisfied in a rule, when I execute a stateless session with fact.
ex: if we have rule condition in a rule RUL1,
car.schi == 'A' || car.carKind str[startsWith] 'A'
if RUL1 is satisfied because of car.schi, then do we have any API where I can get this info(car.schi).
The example what I given was simpler but our actual business rule was so complex as shown below,
(car.carKind != \"EZZ\" && car.carKind != \"ENG\" && car.carKind != \"ETD\") && ((car.schi contains \"N1\" || car.schi contains \"N2\") || ((car.schi contains \"IH\" || car.schi contains \"N4\" || car.schi contains \"OM\" || car.schi contains \"DA\" || car.schi contains \"N5\" || car.schi contains \"PA\" || car.schi contains \"FG\" || car.schi contains \"PL\" || car.schi contains \"PC\" || car.schi contains \"PO\" || car.schi contains \"NG\" || car.schi contains \"OX\" || car.schi contains \"OP\" || car.schi contains \"NS\" || car.schi contains \"FS\" || car.schi contains \"FL\" || car.schi contains \"N3\" || car.schi contains \"CM\" || car.schi contains \"DW\" || car.schi contains \"PB\") && (validateElementRule($trainrulesRequestDTO.getElementRuleMap(),\"1_N\",true,$trainrulesRequestDTO.getCar().getCarNumb())))) && (((car.prevSchi not contains \"N2\" && car.prevSchi not contains \"N1\") && (car.prevLoadEmpty == \"L\") && ((car.prevCarKind str[startsWith] \"F\" || car.prevCarKind str[startsWith] \"YF\") && (car.prevCarKind not str[startsWith] \"FI\" && car.prevCarKind not str[startsWith] \"FA\" && car.prevCarKind not str[startsWith] \"FW\" && car.prevCarKind not str[startsWith] \"FB\") && (car.prevCarKind != \"YFB\"))) || ((car.nextSchi not contains \"N2\" && car.nextSchi not contains \"N1\") && (car.nextLoadEmpty == \"L\") && ((car.nextCarKind str[startsWith] \"F\" || car.nextCarKind str[startsWith] \"YF\") && (car.nextCarKind not str[startsWith] \"FA\" && car.nextCarKind not str[startsWith] \"FB\" && car.nextCarKind not str[startsWith] \"FI\" && car.nextCarKind not str[startsWith] \"FW\") && (car.nextCarKind != \"Y\" || car.nextCarKind != \"YFB\"))))
If we are to split it as different rules to find if the rule was satisfied because of( prevCarKind , prevSchi , prevLoadEmpty) or (nextCarKind, nextSchi,nextLoadEmpty) it would be too hard to split the complex rule.
I have also given the rule condition as image took from our UI application.
Pictorial view of above rule condition string
Would be helpful if someone can let us know on how to find if the above is satisfied based on which condition.
Regards,
Madhankumar. B
Thanks,
Madhan

No you can't. But you could split the rule into multiple rules like this:
rule "RUL1A"
when
car.schi == 'A'
then
...
end
rule "RUL1B"
when
car.carKind[0] == 'A'
then
...
end

You could split your condtion into several functions (and define them in drl):
function boolean isKindEzzEngEtd(Car car) {
return car.carKind in ["EZZ", "ENG", "ETD"];
}
function boolean isSchiContainsN1N2(Car car) {
return (car.schi contains "N1" || car.schi contains "N2");
}
...
then use the functions inside your rules (it also improves readablility and re-use):
rule "RUL1"
when
$car: Car()
!isKindEzzEngEtd($car) || isSchiContainsN1N2($car) && ...
then
-- call the functions one by one to find out which one returned true:
System.out.println("NOT isKindEzzEngEtd: " + !isKindEzzEngEtd($car));
System.out.println("isSchiContainsN1N2: " + isSchiContainsN1N2($car));
end

Related

How can I search based on relevance to flutter?

How can I search based on relevance to flutter? I'm not just talking about displaying the searched data. I am talking about the ones closest to the term to be searched in terms of their letters to the top. Normally the index order with listviewbuilder is 1,2,3 ... normally. But if the search term is closest to the word having the 2nd id among the data, I want the order to change to 2, 1, 3. How can I achieve this?
the codes I tried
_dataResults = _dataList.where((a) {
return (a.data_name.contains(controller.text) ||
a.data_name.toLowerCase().contains(controller.text) ||
a.data_name.toUpperCase().contains(controller.text) ||
a.data_name.startsWith(controller.text) ||
a.data_name.endsWith(controller.text) ||
a.data_title.contains(controller.text) ||
a.data_title.toLowerCase().contains(controller.text) ||
a.data_title.startsWith(controller.text) ||
a.data_title.endsWith(controller.text) ||
a.data_description.contains(controller.text) ||
a.data_description.toLowerCase().contains(controller.text) ||
a.data_description.startsWith(controller.text) ||
a.data_description.endsWith(controller.text));
}).toList();

mismatched input 'from' in rule

I am setting up a project to take in a decision table as input and create the rules.
Error encountered is "mismatched input 'from' in rule".
Fact set is :
Class Member{
double salary;
List<Tag> tagList;
string ruleResult;
}
Class Tag{
string key;
string value;
}
Decision table:
-----------------------------------------
|| Condition || Condition||
-----------------------------------------
m:Member()
tg:Tag() from tagList
-----------------------------------------
|| key==$param || salary >$1 && salary <$2
-----------------------------------------
|| Tag Conditon || sal condition ||
-----------------------------------------
|| "key1" || 1000,2000 ||
-----------------------------------------
I didnt find much documentation on usage of "from". Any help here to proceed further is greatly appreciated.
DRL example: ( I am expecting this as the output for the rule)
rule "drl_rule"
salience 65535
when
m:Member(tg:tagList,salary>1000 && salary<2000)
Tag(key=="key1", value=="value1") from tg
then
m.setRuleResult("Rule Result1");
end

How to rewrite an Impromptu case statement in Cognos Framework Manager?

I have a case statement in Impropmtu that I need to recreate in Framework Manager. I need help with case statement syntax in Framework manager, and in this special case, there is a nested statement involved that makes it a bit more complicated.
I tried using the predefined components in Framework Manager to create the case statement but it doesn't work. I am thinking maybe it is because of the syntax.
This is the Impromptu expression from *.IQD file:
CASE
WHEN ((CASE
WHEN ((((((((('D12' || "ACCOUNT1") = 'E4GM') or
(('D12' || "ACCOUNT1") = 'E4M')) or
(('D12' || "ACCOUNT1") = 'DAM')) or
(('D12' || "ACCOUNT1") = 'DGM')) or
(('D12' || "ACCOUNT1") = 'DJM')) or
(('D12' || "ACCOUNT1") = 'DNM')) or
(('D12' || "ACCOUNT1") = 'DQM')) or
(('D12' || "ACCOUNT1") = 'DWM'))
THEN ('Units')
ELSE null END) = 'Units')
THEN (CASE
WHEN ("MODEL" BETWEEN '10%' AND '19%') THEN ('Mini Unit')
WHEN ("MODEL" BETWEEN '21%' AND '22%') THEN ('Small Unit')
WHEN ("MODEL" BETWEEN '32%' AND '33%') THEN ('Medium Unit')
WHEN ("MODEL" BETWEEN '38%' AND '39%') THEN ('Large Unit')
WHEN ("MODEL" BETWEEN 'M3%' AND 'M4%') THEN ('WH Unit')
ELSE null END) ELSE null END as c21,

Count before order, skip and take

I'm using Entity Framework together with Unit-of-work and repository pattern.
For a function with ordering, pagination, etc. I use the following code:
stammdatenEntityModels =
_unitOfWork.StammdatenRepository.Get()
.Where(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
))
.OrderBy(orderBy)
.Skip(inputModel.EntriesToDisplay*(inputModel.Page - 1))
.Take(inputModel.EntriesToDisplay)
.ToList();
Now I need to know the numbers of records, but before the skip and take (for pagination) is performed.
Therefore I have the same code again:
totalCount = _unitOfWork.StammdatenRepository.Get()
.Count(
s =>
s.Geloescht == false &&
((s.Auftraggeber != null && s.Auftraggeber.Bezeichnung.ToLower().Contains(keyword)) ||
(s.SerienNummer.Contains(keyword)) ||
(s.Bezeichnung.ToLower().Contains(keyword)) ||
(s.StammdatenKunde != null && s.StammdatenKunde.Name.ToLower().Contains(keyword)) ||
(s.BeginnVos.HasValue && s.BeginnVos == dateTime) ||
(s.VosDauer != null && s.VosDauer.Bezeichnung.ToLower().Contains(keyword)) ||
(s.Geraetewert.HasValue && s.Geraetewert.Value.ToString().Contains(keyword))
));
Unfortunately this leads to a lot of redundance and my query is performed twice. Is there any better solution?
I agree with the redundancy. What you can do is to cache the count result for the specific parameters (keyword, dateTime) a certain amount of time and use it again at subsequent calls to deliver paginated (skip, take) results from the StammDatenRepository.
This way you only have the overall count-call one time for specific parameters.
Found this SO question where a respected member states:
Thinking about it from a SQL point of view, I can't think of a way in
a single normal query to retrieve both the total count and a subset of
the data, so I don't think you will be able to do it in LINQ either.
So, I really think you have to cache some counts results to increase performance. You know best how to do it for your specific situation and if it's worth it at all...

EF 4.4 freeze on large table query

I m using EF 4.4 on ASP.NET MVC project with SQL server and my below query freeze every run.
PSSAL has 426.000 rows and PU_CustProduct has 1600 rows
Have any idea or offer for query?
var model = (from p in dbCont.PU_CustProduct
where !(from pt in dbCont.PSSAL
where pt.PSSAL_DATE > d1
&& pt.PSSAL_PSPRP_ID == p.CustProductID
select pt.PSSAL_PSPRP_ID).Contains(p.CustProductID)
&& p.IsActive == true
&& (!p.IsSleepMode == true)
&& p.ProductType == intId
&& p.CustomerID != null
&& p.IsSychSuspend != true
select new WarningViewModel
{
PrpName = p.LicenceName,
CrmID = p.CustomerID.ToString(),
PsprpId = p.CustProductID.ToString(),
}).Distinct().OrderBy(o => o.PrpName).ToList();