Click here to Skip to main content
15,891,529 members
Articles / Desktop Programming / Windows Forms

Evaluation Engine

Rate me:
Please Sign up or sign in to vote.
4.96/5 (164 votes)
1 Jun 2008CC (ASA 2.5)29 min read 305.8K   5K   376  
The Evaluation Engine is a parser and interpreter that can be used to build a Business Rules Engine. It allows for mathematical and boolean expressions, operand functions, variables, variable assignment, comments, and short-circuit evaluation. A syntax editor is also included.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace RulesCalculator
{
    public partial class RuleGroup : UserControl
    {
        #region Local Variables

        private EvaluationEngine.Parser.TokenGroup group = new EvaluationEngine.Parser.TokenGroup();

        #endregion

        #region Constructor

        public RuleGroup()
        {
            InitializeComponent();
        }

        #endregion

        #region Public Properties

        public EvaluationEngine.Parser.TokenGroup Group
        {
            get
            {
                return group;
            }
        }

        #endregion

        #region Public Methods

        public void DoEvaluation()
        {
            // do the evaluation
            group.EvaluateGroup();

            // update the interface
            int index = 0;
            foreach (EvaluationEngine.Parser.Token tk in group.Tokens)
            {
                

                if (tk.AnyErrors == true)
                {
                    listView1.Items[index].SubItems[5].Text = "";
                    listView1.Items[index].SubItems[6].Text = tk.LastErrorMessage;
                    listView1.Items[index].SubItems[6].BackColor = Color.Red;
                }
                else
                {
                    listView1.Items[index].SubItems[5].Text = tk.LastEvaluationTime.ToString("#,###.###") + " ms";
                    listView1.Items[index].SubItems[6].Text = tk.LastEvaluationResult;
                    listView1.Items[index].SubItems[6].BackColor = SystemColors.ControlLightLight;
                }

                index++;
            }

            UpdateStatictis();
        }

        public void AddFile(string Filename)
        {
            // get the file
            System.IO.FileInfo file = new System.IO.FileInfo(Filename);

            // create the token item
            EvaluationEngine.Parser.Token tk = new EvaluationEngine.Parser.Token(file);
            group.Tokens.Add(tk);

            // add the token to the list view
            ListViewItem item = new ListViewItem(file.Name.Remove(file.Name.Length - file.Extension.Length, file.Extension.Length));
            item.Tag = tk;

            item.SubItems.Add(file.DirectoryName);

            if (tk.AnyErrors == true)
            {
                item.SubItems.Add("Error: " + tk.LastErrorMessage);
                item.BackColor = Color.Red;
            }
            else
            {
                item.SubItems.Add("Ready");
                item.BackColor = SystemColors.ControlLightLight;
            }

            item.SubItems.Add(tk.Variables.Count.ToString());

            item.SubItems.Add(tk.TokenParseTime.ToString("#,###.###") + "ms");


            // evaluation
            item.SubItems.Add("");

            // results
            item.SubItems.Add("");



            listView1.Items.Add(item);

            UpdateVariables();

            grpRules.Text = "Rules, Count = " + group.Tokens.Count.ToString();

            UpdateStatictis();
        }

        public bool Save(string Filename, out string ErrorMsg)
        {
            // initialize the outgoing error message
            ErrorMsg = "";

            // create the text writer object
            System.IO.TextWriter tw = null;
            try
            {
                tw = new System.IO.StreamWriter(Filename);
            }
            catch (Exception err)
            {
                ErrorMsg = "Error saving the token group: " + err.Message;
                return false;
            }

            try
            {
                tw.WriteLine(";Filenames;");
                foreach (ListViewItem item in listView1.Items)
                {
                    string filename = item.SubItems[1].Text + "\\" + item.Text + ".txt";
                    tw.WriteLine(filename);
                }
            }
            catch (Exception err)
            {
                tw.Close();
                ErrorMsg = "Error while saving the group data: " + err.Message;
                return false;
            }

            try
            {
                tw.WriteLine("");
                tw.WriteLine(";Variables;");
                foreach (EvaluationEngine.Parser.Variable var in group.Variables)
                {
                    tw.Write(var.VariableName);
                    tw.Write("=");
                    tw.WriteLine(var.VariableValue);
                }
            }
            catch (Exception err)
            {
                tw.Close();
                ErrorMsg = "Error while saving the group data: " + err.Message;
                return false;
            }

            // all done
            tw.Close();
            return true;
        }

        public bool Load(string Filename, out string ErrorMsg)
        {
            // initialize the outgoing error message
            ErrorMsg = "";

            // create a text reader
            System.IO.TextReader tr = null;
            try
            {
                tr = new System.IO.StreamReader(Filename);
            }
            catch (Exception err)
            {
                ErrorMsg = "Error in RuleGroup.Load() while reading the file '" + Filename + "' : " + err.Message;
                return false;
            }

            // read the whole file
            string content = "";
            bool anyError = false;
            try
            {
                content = tr.ReadToEnd();
            }
            catch (Exception err)
            {
                anyError = true;
                ErrorMsg = "Error in RuleGroup.Load() while reading the file: " + err.Message;
            }
            finally
            {
                tr.Close();
            }
            if (anyError == true) return false;


            // split the filecontent by the new line
            string[] arrLines = content.Split("\n".ToCharArray());

            // create a collection to hold the variables and the values
            System.Collections.Generic.SortedList<string, string> vars = new SortedList<string, string>();

            bool foundVariables = false;
            for (int i = 0; i < arrLines.Length; i++)
            {
                if (String.IsNullOrEmpty(arrLines[i]) == false)
                {
                    string dataItem = arrLines[i].Trim().Replace("\r", "");
                    
                    if (String.IsNullOrEmpty(dataItem) == false)
                    {
                        switch (arrLines[i].Trim().ToLower())
                        {
                            case ";variables;":
                                foundVariables = true;
                                break;

                            case ";filenames;":
                                break;

                            default:
                                if (foundVariables == false)
                                {
                                    AddFile(dataItem);
                                }
                                else
                                {
                                    // we have a variable
                                    string[] arrData = dataItem.Split("=".ToCharArray());

                                    if (arrData.Length == 2)
                                    {
                                        string key = arrData[0].Trim().ToLower();
                                        string data = arrData[1];

                                        if (vars.ContainsKey(key) == false)
                                        {
                                            vars.Add(key, data);
                                        }
                                    }
                                }
                                break;
                        }
                    }
                }
            }

            // add the variable values
            if (vars.Count > 0)
            {
                for (int i = 0; i < vars.Count; i++)
                {
                    string key = vars.Keys[i];
                    string data = vars[key];

                    if (group.Variables.VariableExists(key) == true) group.Variables[key].VariableValue = data;

                }

                UpdateVariables();
            }


            UpdateStatictis();

            // all done
            return true;
        }

        public void UpdateStatictis()
        {
            double totalParse = 0;
            double totalEval = 0;

            foreach (EvaluationEngine.Parser.Token tk in this.group.Tokens)
            {
                totalParse += tk.TokenParseTime;
                totalEval += tk.LastEvaluationTime;
            }

            this.lblParse.Text = totalParse.ToString("#,###.####") + " ms";
            this.lblEval.Text = totalEval.ToString("#,###.####") + " ms";

        }

        #endregion

        #region Private Methods

        private void butRuleFile_Click(object sender, EventArgs e)
        {
            openFileDialog1.FileName = "";
            openFileDialog1.Multiselect = true;
            openFileDialog1.Filter = "Text Files (*.txt)|*.txt";

            DialogResult result = openFileDialog1.ShowDialog();

            if (result == DialogResult.OK)
            {
                for (int i = 0; i < openFileDialog1.FileNames.Length; i++)
                {
                }
            }
        }        
     
        private void UpdateVariables()
        {
            grpVariables.Text = "Variables, Count = " + group.Variables.Count.ToString();

            // clear the interface
            listView2.Items.Clear();

            // loop through all of the variables
            foreach (EvaluationEngine.Parser.Variable var in group.Variables)
            {

                ListViewItem item = new ListViewItem(var.VariableName);

                if (String.IsNullOrEmpty(var.VariableValue) == true)
                    item.SubItems.Add("Double click to set value");
                else
                    item.SubItems.Add("Value = " + var.VariableValue);

                listView2.Items.Add(item);
            }

        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {            
            if (listView1.SelectedItems.Count == 0) return;

            EvaluationEngine.Parser.Token tk = null;
            tk = listView1.SelectedItems[0].Tag as EvaluationEngine.Parser.Token;
            if (tk == null) return;

            // make all the variables the control color
            foreach (ListViewItem item in listView2.Items)
            {
                if (tk.Variables.VariableExists(item.Text) == true)
                    item.BackColor = Color.LightGreen;
                else
                    item.BackColor = SystemColors.ControlLightLight;
            }

            this.syntaxRichTextBox1.Clear();
            this.syntaxRichTextBox1.Text = tk.RuleSyntax;
            this.syntaxRichTextBox1.ProcessAllLines();


        }

        private void listView2_DoubleClick(object sender, EventArgs e)
        {
            if (listView2.SelectedItems.Count <= 0) return;

            // get the variable            
            EvaluationEngine.Parser.Variable var = group.Variables[listView2.SelectedItems[0].Text];
            if (var == null)
            {
                MessageBox.Show("Failed to get the variable");
                return;
            }

            frmVariable frm = new frmVariable();
            frm.Variable = var;

            DialogResult result = frm.ShowDialog(this);

            if (result == DialogResult.OK)
            {
                this.listView2.SelectedItems[0].SubItems[1].Text = "Single Value = " + var.VariableValue;
            }

            frm.Close();

        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Software Developer (Senior)
United States United States
Developer

Comments and Discussions