lógica booleana avaliador regra
-
05-07-2019 - |
Pergunta
Eu tenho essencialmente uma pesquisa que é mostrado, e as pessoas responder a perguntas muito como um teste, e há diferentes caminhos, é muito fácil até agora, mas eu queria torná-lo mais dinâmico, para que eu possa ter uma regra genérica que é para o teste com todos os caminhos, para fazer o avaliador mais fácil trabalhar com atualmente i apenas permitir e é, e cada um OR torna-se essencialmente uma outra regra no conjunto,
QuestionID, então i formar um monte de e regras gosta assim
<rule id="1">
<true>
<question ID=123>
<question ID=124>
</true>
<false>
<question ID=127>
<question ID=128>
</false>
</rule>
<rule id="2"><true>
<question ID=123>
<question ID=125>
</true>
<false>
<question ID=127>
</false>
</rule>
essa regra 1 diz que se pergunta 123, e 124 são respondidas verdadeiro, e 127, 128 são falsas, eles passam. OR (regra 2) é se 123 e 125 são verdadeiras e 127 é falso, passam bem. Isto torna-se tedioso se há muitas combinações, assim que eu quero implementar ou na lógica, eu não sou apenas certo o que melhor abordagem é para este problema.
Eu acho que as regras motor é muito complicado, deve haver uma maneira mais fácil, talvez construindo um gráfico como em LINQ e depois avaliar para ver se eles passam,
Obrigado!
-. Não um compsci importante
Solução
Isto não tem de ser complicado: você está a maior parte do caminho já, uma vez que seus e elementos efetivamente implementar uma regra do tipo E. Eu iria introduzir um elemento que pode segurar e elementos.
Em seu poderia, você poderia ter:
- class uma base de regra, com um "bool abstrato público Evaluate ()" método
- TrueRule, FalseRule e OrRule classes, que contêm listas de ruleBase objetos
- Um QuestionRule classe, que se refere a uma pergunta específica
Você iria implementar o método Avaliar em cada um deles como se segue:
- TrueRule: retorna true somente se todas as regras contidas retornar verdadeiro do Avaliar
- FalseRule: retorna true somente se todas as regras contidas retornar falso do Avaliar
- OrRule: retorna verdadeiro se pelo menos uma das regras constantes retornos verdadeiro do Avaliar
- QuestionRule: retorna a resposta para a pergunta original
Essa classe implementa hierarquia de uma árvore de sintaxe abstrata simples (AST). LINQ, na forma da classe System.Expressions.Expression, faz praticamente a mesma coisa, mas é útil para escrever o seu próprio, se não é óbvio como tudo se encaixa.
Outras dicas
Se você usar um motor de regras adequado que suporta inferência seria mais eficiente e extensível.
Dê uma olhada http://www.flexrule.com que é, um motor flexível regra extensível que suporta três tipos de regra. , regras de inferência e Estado-Flow processuais podem ser exteriorizado de sua aplicação e são executadas usando este quadro.
Eu não tenho certeza eu entendo totalmente o problema que você está tentando resolver, mas você poderia usar um XPath simples para chegar a do ID:
Isto lhe daria todo o "verdadeiro" ID é onde o ID regra = 1: / Rule [@ id = "1"] / true // @ ID
O mesmo que acima somente dá-lhe a identidade falsa de: / Rule [@ id = "1"] / false // @ ID
Por fim um link para uma introdução à XPath no .NET http://www.developer.com/xml/article.php/3383961
Good Luck
Eu sugiro colocar as respostas sobre as questões, em vez de usar true
e false
para agrupar as perguntas. Eu acho que ele faz para XML que é mais fácil de ler, o que é discutível. O que não é discutível é que ele torna possível avaliar um elemento question
de forma independente, ou seja, sem qualquer conhecimento do contexto em que você está tentando avaliá-lo. Isso faz de código mais simples.
Eu também tomar uma página do XML Schema e implementar sua lógica OR como um elemento choice
. Um elemento choice
é verdadeiro se qualquer um dos seus filhos são verdadeiras. Você pode, é claro, o ninho deles:
<rule id="1">
<question id="123" answer="true" />
<question id="124" answer="false" />
<choice id="1">
<question id="125" answer='true' />
<choice id="2">
<question id="126" answer='false' />
<question id="127" answer='false' />
</choice>
</choice>
</rule>
Isso você folhas com quatro métodos muito simples de implementar, cada um dos quais é usado pela anterior:
-
bool GetProvidedAnswer(int questionID)
-
bool IsQuestionCorrect(XmlElement question)
-
bool IsChoiceCorrect(XmlElement choice)
-
bool IsRuleSatisfied(XmlElement rule)
A estrutura do XML torna esses métodos muito simples de implementar:
bool IsRuleSatisfied(XmlElement rule)
{
bool satisfied = true;
foreach (XmlElement child in rule.SelectNodes("*"))
{
if (child.Name == "question")
{
satisfied = satisfied && IsQuestionCorrect(child);
}
if (child.Name == "choice")
{
satisfed = satisfied && IsChoiceCorrect(child);
}
if (!satisfied)
{
return false;
}
}
return true;
}
Pode valer a pena adicionar um List<XmlElement>
para os parâmetros dos métodos IsFooCorrect
. (Se o mecanismo de regras está em uma classe, você pode torná-lo um campo de classe.) Faça `todos os métodos de adicionar o elemento atual para a lista quando errada de uma resposta. Você pode então examinar o conteúdo dessa lista para saber exatamente por que uma regra falhou.