2008-10-29 17 views
2

J'ai essentiellement un sondage qui est montré, et les gens répondent à des questions beaucoup comme un test, et il y a des chemins différents, c'est assez facile jusqu'à présent, mais je voulais le rendre plus dynamique, donc que je peux avoir une règle générique qui est pour le test avec tous les chemins, pour rendre l'évaluateur plus facile de travailler avec actuellement je permets juste ET, et chaque OU devient essentiellement une autre règle dans l'ensemble,Boolean logique règle évaluateur

QuestionID, alors je former un tas de règles ET comme

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

cette règle 1 dit si la question 123, et 124 sont répondu vrai, et 127, 128 sont faux, ils passent. OU (règle 2) est que si 123 et 125 sont vrais et 127 est faux, ils passent aussi bien. Cela devient fastidieux s'il y a beaucoup de combinaisons, donc je veux implémenter OU dans la logique, je ne suis juste pas sûr de la meilleure approche pour ce problème.

Je pense que moteur de règles est trop compliqué, il doit y avoir un moyen plus facile, peut-être construire un graphique comme dans LINQ, puis évaluer pour voir si elles passent,

merci!

- pas un composant majeur.

Répondre

2

Cela n'a pas besoin d'être compliqué: vous en êtes déjà à l'essentiel puisque vos éléments implémentent efficacement une règle de type ET. Je voudrais introduire un élément qui peut contenir et des éléments.

Dans votre pourrait, vous pourriez avoir:

  • Une classe RuleBase, avec une méthode "public abstract bool evaluate()"
  • TrueRule, les classes FalseRule et OrRule, qui contiennent des listes d'objets RuleBase
  • une classe QuestionRule, qui fait référence à une question spécifique

Vous mettrait en œuvre la méthode Evaluate sur chacun d'entre eux comme suit:

  • TrueRule: renvoie true que si toutes les règles contenues renvoient vrai de Évaluer
  • FalseRule: renvoie true que si toutes les règles contenues return false de Évaluer
  • OrRule: retourne true si Au moins une des règles contenues renvoie true à partir de Evaluer
  • QuestionRule: retourne la réponse à la question d'origine

Cette hiérarchie de classes implémente un arbre de syntaxe abstraite simple (AST). LINQ, sous la forme de la classe System.Expressions.Expression, fait à peu près la même chose, mais il est utile d'écrire le vôtre si ce n'est pas évident de voir comment tout va bien ensemble.

0

Je ne suis pas sûr que je comprends tout à fait le problème que vous essayez de résoudre, mais vous pouvez utiliser un simple XPath pour obtenir chez le ID:

Cela vous donne tous les ID « vrais » de là où la règle ID = 1: /règle [@ id = "1"]/true // @ ID

comme ci-dessus ne vous donne de faux ID: /règle [@ id = "1"]/faux// @ ID

Enfin un lien vers une introduction à XPath dans .NET http://www.developer.com/xml/article.php/3383961

Bonne chance

0

Je vous suggère de mettre les réponses aux questions, plutôt que d'utiliser true et false pour regrouper les questions. Je pense que cela rend XML plus facile à lire, ce qui est discutable. Ce qui n'est pas discutable, c'est qu'il permet d'évaluer indépendamment un élément question, c'est-à-dire sans aucune connaissance du contexte dans lequel vous essayez de l'évaluer. Cela rend le code plus simple.

Je prendrais également une page de XML Schema et implémenterais votre logique OU en tant qu'élément choice. Un élément choice est vrai si l'un de ses enfants est vrai. Vous pouvez, bien sûr, les imbriquer:

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

Cela vous laisse avec quatre méthodes assez simples à mettre en œuvre, dont chacun est utilisé par celui qui le précède:

  • bool GetProvidedAnswer(int questionID)
  • bool IsQuestionCorrect(XmlElement question)
  • bool IsChoiceCorrect(XmlElement choice)
  • bool IsRuleSatisfied(XmlElement rule)

La structure du XML rend ces méthodes assez simples à mettre en œuvre:

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; 
} 

Il pourrait être intéressant d'ajouter un List<XmlElement> aux paramètres des méthodes IsFooCorrect. (Si le moteur de règles est dans une classe, vous pouvez en faire un champ de classe.) Faire `toutes les méthodes ajoutent l'élément courant à la liste lorsqu'une réponse est fausse. Vous pouvez ensuite examiner le contenu de cette liste pour savoir exactement pourquoi une règle a échoué.

1

Si vous utilisez un moteur de règles approprié prenant en charge l'inférence, il serait plus efficace et plus extensible.

Jetez un oeil à http://www.flexrule.com qui est un moteur de règles flexible et extensible qui prend en charge trois types de règles. Les règles de procédure, d'inférence et de flux de règles peuvent être externalisées à partir de votre application et être exécutées à l'aide de cette structure.

+0

Vous auriez pu élaborer un peu plus par un exemple de code. –