Problème lors de l'écriture de LHS de Drools / JBoss Rules où je fais correspondre un fait et que j'utilise ensuite ce fait pour déterminer si un autre fait existe
-
03-07-2019 - |
Question
J'utilise Drools (pour la première fois) pour exprimer certaines règles et cela fonctionne très bien jusqu'à présent. Cependant, on m'a donné une nouvelle condition que je ne suis pas en mesure d'exprimer très clairement dans le langage des règles.
Je dois effectuer une action sur le compte du joueur s’il a un solde en souffrance entre un certain montant, s’il n’a pas effectué de paiement la semaine dernière et s’il n’a pas effectué de paiement dans les 4 dernières semaines qui est supérieure ou égale à une déduction hebdomadaire. Il y a quelques autres règles mais je les ai supprimées dans le but de simplifier la règle pour cette question. C’est la dernière règle qui me pose problème.
rule "The broken rule"
salience 10
no-loop
when
Player( $playerNumber : playerNumber )
$a : Account( // balance between £5 and £100 and no arrangement
playerNumber == $playerNumber &&
accountBalanceInPence >= 500 &&
accountBalanceInPence <= 10000
)
not ( // no payment in last week
exists AccountTransaction(
playerNumber == $playerNumber &&
transactionDate >= oneWeekAgo &&
transactionCode == "P" // payment
)
)
/* It's this next bit that is broken */
not ( // no payment > (weekly cost * 4) paid within last 4 weeks
$deduction : AccountTransaction( // a recent transaction
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "D" // deduction
)
exists AccountTransaction( // the payment
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "P" // payment
amountInPence >= ($deduction->amountInPence * 4)
)
)
then
// do some action to the account
end
Le problème est que cela ne fonctionne tout simplement pas, je continue à recevoir des exceptions org.drools.rule.InvalidRulePackage. J'étais en train de deviner la syntaxe mais je n'arrivais pas à trouver un exemple montrant ce que j'essayais de faire. Est-ce même possible?
Le message d'erreur d'origine complet est le suivant:
"unknown:50:3 mismatched token: [@255,1690:1695='exists',<39>,50:3]; expecting type RIGHT_PAREN[54,4]: unknown:54:4 mismatched token: [@284,1840:1852='amountInPence',<7>,54:4]; expecting type RIGHT_PAREN[54,22]: unknown:54:22 Unexpected token '$payment'"
Après avoir essayé la suggestion du premier commentaire, l'erreur est la suivante:
"[50,3]: unknown:50:3 mismatched token: [@255,1690:1695='exists',<39>,50:3]; expecting type RIGHT_PAREN[54,4]: unknown:54:4 mismatched token: [@284,1840:1852='amountInPence',<7>,54:4]; expecting type RIGHT_PAREN[54,45]: unknown:54:45 mismatched token: [@293,1881:1881='*',<71>,54:45]; expecting type LEFT_PAREN[55,3]: unknown:55:3 mismatched token: [@298,1890:1890=')',<12>,55:3]; expecting type THEN"
La solution
Oui, comme vous l'avez deviné, vous devez définir explicitement les "" and"; à l'intérieur du " pas " motif pour les joindre ensemble.
La seule fois où vous n’avez pas besoin des " et " est au plus haut niveau:
par exemple
when Foo() Bar()
Ne nécessite pas de """
mais cela est implicitement identique à
when Foo() and Bar()
Votre solution semble donc correcte. L'absence d'un niveau supérieur "et" semble être une convention dans la plupart des langages de règles (revenir à CLIPS!)
Autres conseils
Après un peu plus de piratage, ce qui suit n’entraîne aucune erreur d’exécution (bien que je ne sois pas sûr que ce soit "correct"). J'ai réécrit la clause pour mettre les existences autour des faits et j'ai utilisé un infixe pour les regrouper.
not ( // no payment > (weekly cost * 4) paid within last 4 weeks
exists (
AccountTransaction( // a recent transaction
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "D" // deduction
$recentDeducation : amountInPence
) and
AccountTransaction( // the payment
playerNumber == $playerNumber &&
transactionDate >= fourWeeksAgo &&
transactionCode == "P" // payment
amountInPence >= ($recentDeducation * 4)
)
)
)
Merci pour toute l'aide apportée jusqu'à présent.
Qu'en est-il de ($ deduction- > amountInPence * 4)
? Je pense que le - >
devrait être un .
à la place.