2009-01-06 3 views
1

J'utilise Drools (pour la première fois) pour exprimer quelques règles et ça a vraiment fonctionné bien jusqu'à présent. Cependant, on m'a donné une nouvelle condition que je ne suis pas capable d'exprimer très clairement dans le langage des règles. Essentiellement, je dois effectuer une action sur le compte des joueurs s'ils ont un solde impayé sur un compte entre un certain montant, où ils n'ont pas effectué de paiement la semaine dernière et où ils n'ont pas effectué de paiement au cours des 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 cause un problème.Problème d'écriture LHS de Drools/JBoss Rules où je fais correspondre un fait et ensuite utiliser ce fait pour déterminer si un autre fait existe

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 ça ne marche pas, je continue à obtenir des exceptions org.drools.rule.InvalidRulePackage jetés. Je ne faisais que deviner la syntaxe, mais je n'arrivais pas à trouver un exemple qui montre ce que j'essaie de faire. Est-ce même possible?


Le message d'erreur complet d'origine est:

"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 dans le premier commentaire l'erreur est:

"[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" 

Répondre

1

oui comme vous l'avez deviné, vous devez mettre un "et" explicite dans le motif "non" pour les joindre ensemble.

Le seul moment où vous n'avez pas besoin « et » est au niveau supérieur:

par exemple

when Foo() Bar() 

Ne nécessite pas un « et »

mais est implicitement le même que

when Foo() and Bar() 

Donc votre solution semble correcte. Le manque d'un niveau supérieur "et" semble être conventionnel dans la plupart des langages de règles (retour à CLIPS!)

+0

J'ai accepté cette réponse même si je l'ai piratée moi-même, votre réponse explique pourquoi cela fonctionne! – BenM

+0

Eh bien merci - mais vous avez travaillé dur! J'ai juste essayé d'expliquer pourquoi cela a fonctionné.FYI cette exception que vous obtenez est parce qu'il a échoué à compiler (je pense que dans la version future, vous devez vérifier l'erreur dans le code, aucune exception ne sera levée IIRC) –

0

Qu'en est-($deduction->amountInPence * 4)? Je pense, le -> devrait être un . à la place.

+0

Malheureusement, cela n'a pas fonctionné, je vais mettre à jour la question avec plus de détails sur les messages d'erreur (ils ne ne correspond pas à un commentaire). – BenM

+0

Je pense que c'était une faute de frappe qui a été éditée - parce que oui, le "->" semble faux. C'était une ancienne syntaxe qui n'est plus nécessaire. –

1

Après un peu plus de piratage autour de ce qui suit ne provoque pas d'erreurs d'exécution (même si je ne suis pas sûr si c'est "correct" pour le moment). J'ai réécrit la clause pour mettre l'existence autour des deux faits et utilisé un infixe et 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 jusqu'à présent.

+0

Vous n'avez probablement pas besoin du "&&" et pouvez mettre chaque contrainte de champ séparée par un "," - juste une suggestion –