Problema al escribir LHS de Drools / Reglas de JBoss donde coincido con un hecho y luego lo uso para determinar si existe otro hecho
-
03-07-2019 - |
Pregunta
Estoy usando Drools (por primera vez) para expresar algunas reglas y ha estado funcionando muy bien hasta ahora. Sin embargo, me han dado una nueva condición que no puedo expresar muy claramente en el lenguaje de las reglas.
Esencialmente, necesito realizar una acción en la cuenta de los jugadores si tienen un saldo pendiente en esa cuenta entre cierta cantidad, en la que no han realizado un pago en la última semana y en la que no han realizado un pago en las últimas 4 semanas que es mayor o igual a una deducción semanal. Hay algunas otras reglas, pero las he eliminado en un esfuerzo por simplificar la regla para esta pregunta. Es la última regla que me está 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
El problema es que simplemente no funciona, sigo recibiendo las excepciones de org.drools.rule.InvalidRulePackage. Estaba adivinando sobre la sintaxis, pero no pude encontrar un ejemplo que mostrara lo que estoy tratando de hacer. ¿Es incluso posible?
El mensaje de error original completo es:
"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'"
Después de intentar la sugerencia en el primer comentario, el error es:
"[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"
Solución
sí, como lo adivinó, necesita poner un explícito '' y '' dentro de " no " Patrón para unirlos juntos.
La única vez que no necesita el " y " está en el nivel superior:
por ejemplo
when Foo() Bar()
No requiere un " y "
pero esto es implícitamente lo mismo que
when Foo() and Bar()
Entonces tu solución parece correcta. La falta de un nivel superior '' y '' parece ser una convención en la mayoría de los lenguajes de reglas (¡volviendo a CLIPS!)
Otros consejos
Después de un poco más de pirateo, lo siguiente no causa ningún error de tiempo de ejecución (aunque todavía no estoy seguro de si es correcto). Reescribí la cláusula para poner lo existente en torno a los hechos y usé un infijo y los agrupé.
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)
)
)
)
Gracias por toda la ayuda hasta ahora.
¿Qué pasa con ($ deducción- > amountInPence * 4)
? Creo que el - >
debería ser un .
en su lugar.