Problema nella scrittura di LHS delle regole Drools / JBoss in cui sto abbinando un fatto e quindi usando quel fatto per determinare se esiste un altro fatto

StackOverflow https://stackoverflow.com/questions/415907

  •  03-07-2019
  •  | 
  •  

Domanda

Sto usando Drools (per la prima volta) per esprimere alcune regole e finora ha funzionato molto bene. Tuttavia mi è stata data una nuova condizione che non sono in grado di esprimere molto chiaramente nel linguaggio delle regole.

In sostanza, devo eseguire un'azione sul conto dei giocatori se hanno un saldo in sospeso sul conto tra un certo importo, in cui non hanno effettuato un pagamento nell'ultima settimana e in cui non hanno effettuato un pagamento in le ultime 4 settimane che sono maggiori o uguali a una detrazione settimanale. Ci sono alcune altre regole ma le ho rimosse nel tentativo di semplificare la regola per questa domanda. È l'ultima regola che mi sta causando un problema.

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

Il problema è che semplicemente non funziona, continuo a ricevere eccezioni org.drools.rule.InvalidRulePackage. Stavo solo indovinando la sintassi ma non riuscivo a trovare un esempio che mostrasse quello che sto cercando di fare. È anche possibile?


Il messaggio di errore originale completo è:

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

Dopo aver provato il suggerimento nel primo commento, l'errore è:

"[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"
È stato utile?

Soluzione

sì, come hai indovinato, devi inserire un esplicito " e " all'interno del "non" modello per unirli insieme.

L'unica volta in cui non hai bisogno di " e " è al livello più alto:

ad esempio

when Foo() Bar()

Non richiede un " e "

ma implicitamente è lo stesso di

when Foo() and Bar()

Quindi la tua soluzione sembra corretta. La mancanza di un livello superiore "e"; sembra essere una convenzione nella maggior parte delle lingue delle regole (tornando a CLIPS!)

Altri suggerimenti

Dopo qualche altro hacking in giro, ciò che segue non causa errori di runtime (anche se non sono ancora sicuro che sia "corretto"). Ho riscritto la clausola per mettere gli esistenti attorno a entrambi i fatti e ho usato un'infisso e raggrupparli.

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

Grazie per tutto l'aiuto finora.

Che dire di ($ deduction- > amountInPence * 4) ? Penso che il - > dovrebbe essere invece un .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top