编写 Drools / JBoss 规则的 LHS 时出现问题,其中我匹配一个事实,然后使用该事实来确定另一个事实是否存在

发布于 2024-07-10 12:16:02 字数 2405 浏览 11 评论 0原文

我(第一次)使用 Drools 来表达一些规则,到目前为止它运行得非常好。 然而,我得到了一个新条件,我无法用规则语言非常清楚地表达它。

本质上,如果玩家帐户上的未清余额达到一定金额(上周未付款且过去 4 天内未付款),我需要对玩家帐户执行操作大于或等于每周扣除额的周数。 还有一些其他规则,但我已删除它们,以简化此问题的规则。 这是最后一条规则给我带来了问题。

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

问题是它不起作用,我不断抛出 org.drools.rule.InvalidRulePackage 异常。 我只是猜测语法,但似乎找不到一个示例来说明我正在尝试做的事情。 有可能吗?


完整的原始错误消息是:

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

尝试第一条评论中的建议后,错误是:

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

I'm using Drools (for the first time) to express some rules and it has been working really well so far. However I've been given a new condition that I'm not able to express in the rules language very clearly.

Essentially I need to perform an action on the players account if they have an outstanding balance on there account between a certain amount, where they haven't made a payment in the last week and where they haven't made a payment in the last 4 weeks that is greater than or equal to a weekly deduction. There are a few other rules but I've removed them in an effort to simplify the rule for this question. It's the last rule that is causing me a problem.

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

The problem is that it just doesn't work, I keep getting org.drools.rule.InvalidRulePackage exceptions thrown. I was just guessing on the syntax but couldn't seem to find an example that showed what I'm trying to do. Is it even possible?


The full original error message is:

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

After trying the suggestion in the first comment the error is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

悲念泪 2024-07-17 12:16:02

是的,正如您所猜测的,您需要在“非”模式中放置一个明确的“和”以将它们连接在一起。

您唯一不需要“和”的时候是在顶层:

例如

when Foo() Bar()

不需要“和”

,但这与隐式相同

when Foo() and Bar()

所以您的解决方案似乎是正确的。 缺乏顶级“和”似乎是大多数规则语言的惯例(回到 CLIPS!)

yes as you guessed, you need to put an explicit "and" inside the "not" pattern to join them together.

The only time you don't need the "and" is at the top level:

eg

when Foo() Bar()

Doesn't require a an "and"

but this is implicitly the same as

when Foo() and Bar()

So your solution seems correct. The lack of a top level "and" seems to be convention in most rule languages (going back to CLIPS !)

情绪 2024-07-17 12:16:02

经过一些更多的黑客攻击后,以下内容不会导致任何运行时错误(尽管我不确定它是否“正确”)。 我重写了该子句,将存在放在两个事实周围,并使用中缀并将它们分组。

  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)
        )
     )
  )

感谢迄今为止所有的帮助。

After some more hacking around the following doesn't cause any runtime errors (though I'm not sure if it's "correct" yet). I rewrote the clause to put the exists around both the facts and used an infix and to group them.

  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)
        )
     )
  )

Thanks for all the help so far.

烟花易冷人易散 2024-07-17 12:16:02

($deduction->amountInPence * 4) 怎么样? 我认为, -> 应该是 .

What about ($deduction->amountInPence * 4)? I think, the -> should be a . instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文