Domanda

Ho essenzialmente un sondaggio che viene mostrato e le persone rispondono molto alle domande come un test, e ci sono diversi percorsi, è abbastanza semplice finora, ma volevo renderlo più dinamico, in modo da poter avere una regola generica che sia per il test con tutti i percorsi, per rendere il valutatore più facile da lavorare con i consenti semplicemente gli AND, e ogni OR diventa essenzialmente un'altra Regola nel set,

QuestionID, quindi forma un mucchio di regole AND in questo modo

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

questa regola 1 dice che se le domande 123 e 124 hanno una risposta vera e 127, 128 sono false, passano. O (regola 2) è se 123 e 125 sono veri e 127 è falso, anche loro passano. Questo diventa noioso se ci sono molte combinazioni, quindi voglio implementare OR nella logica, non sono sicuro di quale sia l'approccio migliore per questo problema.

Penso che il motore delle regole sia troppo complicato, ci deve essere un modo più semplice, magari costruendo un grafico come in LINQ e quindi valutando per vedere se passano,

grazie!

--non un compsci major.

È stato utile?

Soluzione

Questo non deve essere complicato: lo sei già quasi del tutto, dal momento che your e gli elementi implementano efficacemente una regola di tipo AND. Vorrei introdurre un elemento che può contenere ed elementi.

Nel tuo potere, potresti avere:

  • Una classe RuleBase, con un " public abstract bool Evaluate () " Metodo
  • Classi TrueRule, FalseRule e OrRule, che contengono elenchi di oggetti RuleBase
  • Una classe QuestionRule, che fa riferimento a una domanda specifica

Dovresti implementare il metodo di valutazione su ciascuno di questi come segue:

  • TrueRule: restituisce true solo se tutte le regole contenute restituiscono true da Valuta
  • FalseRule: restituisce true solo se tutte le regole contenute restituiscono false da Evaluate
  • OrRule: restituisce true se almeno una delle regole contenute restituisce true da Valuta
  • QuestionRule: restituisce la risposta alla domanda originale

Questa gerarchia di classi implementa un semplice albero di sintassi astratto (AST). LINQ, nella forma della classe System.Expressions.Expression, fa praticamente la stessa cosa, ma è utile scriverne uno tuo se non è ovvio come tutto combacia.

Altri suggerimenti

Se si utilizza un motore di regole appropriato che supporta inferenze sarebbe più efficiente ed estensibile.

Dai un'occhiata a http://www.flexrule.com che è un motore di regole flessibile ed estensibile che supporta tre tipi di regole. Le regole procedurali, di inferenza e di flusso di regole possono essere esternalizzate dall'applicazione e eseguite mediante questo framework.

Non sono sicuro di aver compreso appieno il problema che si sta tentando di risolvere, ma è possibile utilizzare un semplice XPath per accedere all'ID:

Questo ti darebbe tutto il " true " ID dove l'ID regola = 1: / Regola [@ id = quot &; & 1 quot;] / true // @ ID

Come sopra, ti dà solo i falsi ID: / Regola [@ id = quot &; & 1 quot;] / false // @ ID

Infine un collegamento a un'introduzione a XPath in .NET http://www.developer.com/xml/article.php/3383961

Buona fortuna

Suggerirei di inserire le risposte alle domande, anziché utilizzare true e false per raggruppare le domande. Penso che renda XML più facile da leggere, il che è discutibile. Ciò che non è discutibile è che rende possibile valutare un elemento question in modo indipendente, cioè senza alcuna conoscenza del contesto in cui si sta tentando di valutarlo. Questo rende il codice più semplice.

Prenderei anche una pagina dallo schema XML e implementerei la tua logica OR come elemento choice. Un elemento bool GetProvidedAnswer(int questionID) è vero se qualcuno dei suoi figli è vero. Puoi ovviamente nidificarli:

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

Questo ti lascia con quattro metodi piuttosto semplici da implementare, ognuno dei quali è usato da quello precedente:

  • bool IsQuestionCorrect(XmlElement question)
  • bool IsChoiceCorrect(XmlElement choice)
  • bool IsRuleSatisfied(XmlElement rule)
  • List<XmlElement>

La struttura dell'XML rende questi metodi abbastanza semplici da implementare:

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

Potrebbe valere la pena aggiungere un IsFooCorrect ai parametri dei metodi <=>. (Se il motore delle regole è in una classe, potresti renderlo un campo di classe.) Rendi `tutti i metodi aggiungono l'elemento corrente all'elenco quando una risposta è sbagliata. Puoi quindi esaminare il contenuto di tale elenco per sapere esattamente perché una regola non è riuscita.

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