Вычислитель правил булевой логики
У меня есть по существу опрос, который показан, и люди отвечают на вопросы очень похоже на тест, и есть разные пути, это довольно легко до сих пор, но я хотел сделать его более динамичным, чтобы у меня было общее правило, которое предназначено для теста со всеми путями, чтобы облегчить работу с оценщиком в настоящее время я просто разрешаю и, и каждое или по существу становится другим правилом в наборе,
QuestionID, то я формирую кучу правил и так
{[0]}
Это правило 1 гласит: если ответы на вопросы 123 и 124 истинны, а 127 и 128 ложны, они проходят. Или (Правило 2), если 123 и 125 истинны, а 127 ложны, они также проходят. Это становится утомительным, если есть много комбинаций, поэтому я хочу реализовать или в логике, я просто не уверен, какой лучший подход для этой проблемы.
Я думаю, что механизм правил слишком сложен, должен быть более простой способ, возможно, построение графа, как в LINQ, а затем оценка, чтобы увидеть, проходят ли они,
Спасибо!
-- не compsci major.
4 ответа:
Это не должно быть сложно: вы уже прошли большую часть пути, так как ваши элементы и эффективно реализуют правило типа И. Я бы ввел элемент, который может содержать и элементы.
В вашем could, вы могли бы иметь:
- класс базы правил с методом "public abstract bool Evaluate ()"
- классы TrueRule, FalseRule и OrRule, содержащие списки объектов базы правил
- класс QuestionRule, который относится к определенному классу вопрос
Вы бы реализовали метод оценки на каждом из них следующим образом:
- TrueRule: возвращает true только в том случае, если все содержащиеся правила возвращают true из Evaluate
- FalseRule: возвращает true только в том случае, если все содержащиеся правила возвращают false из Evaluate
- OrRule: возвращает true, если хотя бы одно из содержащихся правил возвращает true из Evaluate
- QuestionRule: возвращает ответ к оригиналу вопрос
Эта иерархия классов реализует простое абстрактное синтаксическое дерево (AST). LINQ, в виде системы.Выражения.Класс Expression делает почти то же самое, но полезно написать свой собственный, если не очевидно, как все сходится.
Если вы используете правильный механизм правил, поддерживающий вывод, он будет более эффективным и расширяемым.
Взгляните на http://www.flexrule.com который является гибким, расширяемым механизмом правил, поддерживающим три типа правил. Процедурные правила, правила вывода и правила потока могут быть экстернализованы из вашего приложения и выполняться с помощью этой платформы.
Я не уверен, что полностью понимаю проблему, которую вы пытаетесь решить, но вы можете использовать простой XPath, чтобы получить идентификатор:
Это даст вам все" истинные " ID, где правило ID = 1: / rule[@id= "1"] / true / / @ID
То же, что и выше, только это дает вам ложные идентификаторы.: / rule[@id= "1"] / false / / @ID
Наконец, ссылка на введение в XPath в .NET http://www.developer.com/xml/article.php/3383961
Удачи
Я бы предложил поместить ответы на вопросы, а не использовать
true
иfalse
для группирования вопросов. Я думаю, что это делает XML более легким для чтения, что является спорным. Что не подлежит обсуждению, так это то, что он позволяет оценивать элементquestion
независимо, то есть без какого-либо знания контекста, в котором вы пытаетесь его оценить. Это делает код проще.Я бы также взял страницу из XML-схемы и реализовал вашу логику OR как элемент
choice
. Один Элемент истинен, если любой из его потомков истинен. Вы можете, конечно, вложить их:Это оставляет вам четыре довольно простых метода для реализации, каждый из которых используется предыдущим:<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>
bool GetProvidedAnswer(int questionID)
bool IsQuestionCorrect(XmlElement question)
bool IsChoiceCorrect(XmlElement choice)
bool IsRuleSatisfied(XmlElement rule)
Структура XML делает эти методы довольно простыми для реализации:
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; }
Возможно, стоит добавить
List<XmlElement>
к параметрам методовIsFooCorrect
. (Если правило движок находится в классе, вы можете сделать его полем класса.) Сделайте так, чтобы все методы добавляли текущий элемент в список, когда ответ неверен. Затем вы можете изучить содержимое этого списка, чтобы точно знать, почему правило не удалось выполнить.