| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Diagnostics;
 
- using System.Linq;
 
- using System.Text;
 
- using System.Text.RegularExpressions;
 
- namespace iBemsDataService.Util
 
- {
 
-     public class MathCalculator
 
-     {
 
-         public enum Parameter
 
-         {
 
-             A = 0 , B , C , D , E , F , G , H , I , 
 
-             J , K , L , M , N , O , P , Q , R , 
 
-             S , T , U , V , W , X , Y , Z
 
-         }
 
-         public enum OperatorType
 
-         {
 
-             Plus,
 
-             Minus,
 
-             Multiplication,
 
-             Division,
 
-             OpenBrace
 
-         }
 
-         public delegate decimal CalculateFunctionDelegate( decimal inputValue );
 
-         public Dictionary<Parameter, MathParameterValue> Parameters = new Dictionary<Parameter , MathParameterValue>();
 
-         public Dictionary<String, CalculateFunctionDelegate> Functions = new Dictionary<String , CalculateFunctionDelegate>();
 
-         private List<String> OperationOrder = new List<string>();
 
-         private static Regex doubleRegex = new Regex( @"^-?\d+(?:\.\d+)?" , RegexOptions.Compiled );
 
-         private static Regex functionRegex = new Regex( @"^\$(.+?)\((.)\)\$" , RegexOptions.Compiled );
 
-         private String Fomula { get; set; }
 
-         Stack<FormulaItem> stack = new Stack<FormulaItem>();
 
-         List<FormulaItem> CompliedFormula = new List<FormulaItem>();
 
-         public void TracePostFormula()
 
-         {
 
-             Trace.Write( "Formula : " );
 
-             foreach( var item in this.CompliedFormula )
 
-             {
 
-                 Trace.Write( item );
 
-                 Trace.Write( " " );
 
-             }
 
-             Trace.WriteLine( "" );
 
-         }
 
-         public void  SetParameter( MathParameterValue[] parameters )
 
-         {
 
-             foreach( var p in parameters )
 
-             {
 
-                 this.Parameters.Add( p.Variable , p );
 
-             }
 
-             //var pv = new ParameterValue { Variable = p, Value = value };
 
-             //this.Parameters.Add( p , pv );
 
-             MapParameters();
 
- //            return pv;
 
-         }
 
-         public void SetFunction( string functionName, CalculateFunctionDelegate callback)
 
-         {
 
-             if( this.Functions.ContainsKey( functionName ) )
 
-             {
 
-                 this.Functions[functionName] = callback;
 
-                 return;
 
-             }
 
-             this.Functions.Add( functionName , callback );
 
-             //var pv = new ParameterValue { Variable = p, Value = value };
 
-             //this.Parameters.Add( p , pv );
 
-             MapFunctions();
 
-             //            return pv;
 
-         }
 
-         public List<FunctionItem> GetFunctions()
 
-         {
 
-             var list = new List<FunctionItem>();
 
-             foreach( var item in this.CompliedFormula )
 
-             {
 
-                 switch( item.Type )
 
-                 {
 
-                     case FormulaItem.ItemType.Function:
 
-                         list.Add( (FunctionItem)item );
 
-                         break;
 
-                 }
 
-             }
 
-             return list;
 
-         }
 
-         private void MapFunctions()
 
-         {
 
-             foreach( var item in this.CompliedFormula )
 
-             {
 
-                 switch( item.Type )
 
-                 {
 
-                     case FormulaItem.ItemType.Function:
 
-                         var f = item as FunctionItem;
 
-                         f.Function.FunctionDelegate = this.Functions[f.Function.FunctionName];
 
-                         break;
 
-                 }
 
-             }
 
-         }
 
-         private void MapParameters()
 
-         {
 
-             foreach( var item in this.CompliedFormula )
 
-             {
 
-                 switch( item.Type )
 
-                 {
 
-                     case FormulaItem.ItemType.OperandField:
 
-                         var o = item as OperandFieldItem;
 
-                         o.ParameterValue = this.Parameters[o.ParameterValue.Variable];
 
-                         break;
 
-                     case FormulaItem.ItemType.Function:
 
-                         var f = item as FunctionItem;
 
-                         switch( f.Value.Type )
 
-                         {
 
-                             case FormulaItem.ItemType.OperandField:
 
-                                 var of = (OperandFieldItem)f.Value;
 
-                                 of.ParameterValue = this.Parameters[of.ParameterValue.Variable];
 
-                                 break;
 
-                         }
 
-                         break;
 
-                 }
 
-                 
 
-             }
 
-         }
 
-         public decimal? Calculate()
 
-         {
 
-             Stack<FormulaItem> stack = new Stack<FormulaItem>();
 
-             foreach( var item in this.CompliedFormula )
 
-             {
 
-                 switch( item.Type )
 
-                 {
 
-                     case FormulaItem.ItemType.Constant:
 
-                     case FormulaItem.ItemType.OperandField:
 
-                     case FormulaItem.ItemType.Function:
 
-                         stack.Push(item);
 
-                         break;
 
-                     case FormulaItem.ItemType.Operator:
 
-                         var ci = this.CalculateOperator( stack.Pop() , stack.Pop() , ((OperatorItem)item).Operator );
 
-                         if( ci == null )
 
-                         {
 
-                             return null;
 
-                         }
 
-                         stack.Push( ci );
 
- //                        Trace.WriteLine( ci.GetValue() );
 
-                         break;
 
-                 }
 
-             }
 
-             return stack.Pop().GetValue();            
 
-         }
 
-         private ConstantItem CalculateOperator( FormulaItem item1 , FormulaItem item2 , OperatorType op )
 
-         {
 
-             decimal result = 0;
 
- //            Trace.WriteLine( item2.GetValue() + " " + op + " " + item1.GetValue() );
 
-             switch( op )
 
-             {
 
-                 case OperatorType.Plus:
 
-                     result = item2.GetValue() + item1.GetValue();
 
-                     break;
 
-                 case OperatorType.Minus:
 
-                     result = item2.GetValue() - item1.GetValue();
 
-                     break;
 
-                 case OperatorType.Multiplication:
 
-                     result = item2.GetValue() * item1.GetValue();
 
-                     break;
 
-                 case OperatorType.Division:
 
-                     if( item1.GetValue() == 0 )
 
-                         return null;
 
-                     result = item2.GetValue() / item1.GetValue();
 
-                     break;
 
-             }
 
-             return new ConstantItem { Value = result };
 
-         }
 
-         public bool Compile( string formula )
 
-         {
 
-             this.CompliedFormula.Clear();
 
-             formula = formula.Replace( " ", "" );
 
-             Stack<OperatorItem> stack = new Stack<OperatorItem>();
 
-             char[] braces = new char[] { '(' , ')' };
 
-             string operators = "+-*/";
 
-             var array = formula.ToCharArray();
 
-             for( var i = 0 ; i < array.Length ; )
 
-             {
 
-                 var item = array[i];
 
-                 switch( item )
 
-                 {
 
-                     case '(':
 
-                         stack.Push( new OperatorItem { Operator = OperatorType.OpenBrace } );
 
-                         i++;
 
-                         break;
 
-                     case ')':
 
-                         while( stack.Any() )
 
-                         {
 
-                             var stackItem = stack.Pop();
 
-                             if( stackItem.Operator == OperatorType.OpenBrace )
 
-                             {
 
-                                 break;
 
-                             }
 
-                             CompliedFormula.Add( stackItem );
 
-                             //Trace.WriteLine( stackItem.Operator );
 
-                         }
 
-                         i++;
 
-                         break;
 
-                     case '$':
 
-                         Match funcMatch = functionRegex.Match( formula.Substring( i ) );
 
-                         if( funcMatch.Success == false || funcMatch.Groups.Count != 3 )
 
-                         {
 
-                             CompliedFormula.Clear();
 
-                             return false;
 
-                         }
 
-                         Trace.WriteLine( funcMatch.Groups[0].Value );
 
-                         Trace.WriteLine( funcMatch.Groups[1].Value );
 
-                         Trace.WriteLine( funcMatch.Groups[2].Value );
 
-                         var f = new FunctionItem {
 
-                             Function = new MathFunction { FunctionName = funcMatch.Groups[1].Value }
 
-                         };
 
-                         string value = funcMatch.Groups[2].Value;
 
-                         if( 'A' <= value[0] && value[0] <= 'Z' )
 
-                         {
 
-                             if( value.Length > 1 )
 
-                             {
 
-                                 Trace.WriteLine( "function parameter wrong!" );
 
-                                 return false;
 
-                             }
 
-                             f.Value = new OperandFieldItem { ParameterValue = new MathParameterValue { Variable = (Parameter)(value[0] - 'A') } };
 
-                         }
 
-                         else
 
-                         {
 
-                             decimal outputValue;
 
-                             if( decimal.TryParse( value, out outputValue ) == false )
 
-                             {
 
-                                 return false;
 
-                             }
 
-                             f.Value = new ConstantItem { Value = outputValue };
 
-                         }                        
 
-                         CompliedFormula.Add( f );
 
-                         i += funcMatch.Length;
 
-                         break;
 
-                     default:
 
-                         int operatorIndex = operators.IndexOf(item);
 
-                         bool isProcessed = false;
 
-                         if( operatorIndex == (int)OperatorType.Minus )
 
-                         {
 
-                             if( i == 0 || array[i-1] == '(' || operators.IndexOf(array[i-1]) >= 0 )
 
-                             {
 
-                                 isProcessed = true;
 
-                             }                            
 
-                         }
 
-                         if( isProcessed == false )
 
-                         {
 
-                             if( operatorIndex >= 0 )
 
-                             {
 
-                                 //if( operatorIndex < (int)OperatorType.Multiplication )
 
-                                 {
 
-                                     while( stack.Any() )
 
-                                     {
 
-                                         var stackItem = stack.Peek();
 
-                                         if( stackItem.Operator == OperatorType.OpenBrace ) break;
 
-                                         if( (int)stackItem.Operator < operatorIndex ) break;
 
-                                         stack.Pop();
 
-                                         CompliedFormula.Add( stackItem );
 
-                                     }
 
-                                 }
 
-                                 stack.Push( new OperatorItem { Operator = (OperatorType)operatorIndex } );
 
-                                 i++;
 
-                                 break;
 
-                             }
 
-                             else if( 'A' <= item && item <= 'Z' )
 
-                             {
 
-                                 //Trace.WriteLine( item );
 
-                                 CompliedFormula.Add( new OperandFieldItem { ParameterValue = new MathParameterValue { Variable = (Parameter)(item - 'A') } } );
 
-                                 i++;
 
-                                 break;
 
-                             }
 
-                         }
 
-                         Match match = doubleRegex.Match(formula.Substring( i ));
 
-                         if( match.Success == false )
 
-                         {
 
-                             throw new Exception( "Error: Check Syntax : " + item );
 
-                         }
 
-                         decimal parseValue = decimal.Parse( match.Value );
 
-                         //Trace.WriteLine( value );
 
-                         CompliedFormula.Add( new ConstantItem { Value = parseValue } );
 
-                         i += match.Value.Length;
 
-                         break;
 
-                 }
 
-             }
 
-             while( stack.Any() )
 
-             {
 
-                 var operatorItem = stack.Pop();
 
-                 //Trace.WriteLine( operatorItem.Operator );
 
-                 CompliedFormula.Add( operatorItem );
 
-             }
 
-             return true;
 
-         }
 
-         public bool ExtractDouble( string inputValue, out decimal output )
 
-         {
 
-             return decimal.TryParse( inputValue, out output);
 
-         }
 
-         public abstract class FormulaItem
 
-         {
 
-             public enum ItemType
 
-             {
 
-                 Operator,
 
-                 Constant,
 
-                 OperandField,
 
-                 Function
 
-             }
 
-             public ItemType Type { get; set; }
 
-             public abstract decimal GetValue();
 
-         }
 
-         public class OperatorItem : FormulaItem
 
-         {
 
-             public OperatorType Operator { get; set; }
 
-             public OperatorItem()
 
-             {
 
-                 this.Type = FormulaItem.ItemType.Operator;
 
-             }
 
-             public override string ToString()
 
-             {
 
-                 switch( this.Operator )
 
-                 {
 
-                     case OperatorType.Plus:
 
-                         return "+";
 
-                     case OperatorType.Minus:
 
-                         return "-";
 
-                     case OperatorType.Multiplication:
 
-                         return "*";
 
-                     case OperatorType.Division:
 
-                         return "/";
 
-                 }
 
-                 return "Unknown";
 
-             }
 
-             public override decimal GetValue()
 
-             {
 
-                 throw new Exception( "OperatorItem.GetValue() Called!" );
 
-                 //return 0;
 
-             }
 
-         }
 
-         public class ConstantItem : FormulaItem
 
-         {
 
-             public decimal Value { get; set; }
 
-             public ConstantItem()
 
-             {
 
-                 this.Type = FormulaItem.ItemType.Constant;
 
-             }
 
-             public override string ToString()
 
-             {
 
-                 return this.Value.ToString();
 
-             }
 
-             public override decimal GetValue()
 
-             {
 
-                 return this.Value;
 
-             }
 
-         }
 
-         public class OperandFieldItem : FormulaItem
 
-         {
 
-             public MathParameterValue ParameterValue { get; set; }
 
-             public OperandFieldItem()
 
-             {
 
-                 this.Type = FormulaItem.ItemType.OperandField;
 
-             }
 
-             public override string ToString()
 
-             {
 
-                 return this.ParameterValue.Variable.ToString();
 
-             }
 
-         
 
-             public override decimal GetValue()
 
-             {
 
-                 return this.ParameterValue.Value;
 
-             }
 
-         }
 
-         public class FunctionItem : FormulaItem
 
-         {
 
-             public MathFunction Function { get; set; }
 
-             public FormulaItem Value { get; set; }
 
-             public FunctionItem()
 
-             {
 
-                 this.Type = FormulaItem.ItemType.Function;
 
-             }
 
-             public override string ToString()
 
-             {
 
-                 return string.Format( "Function({0})" , this.Value.GetValue() );
 
-             }
 
-             public override decimal GetValue()
 
-             {
 
-                 return this.Function.FunctionDelegate( this.Value.GetValue() );
 
-             }
 
-         }
 
-     }
 
-     public class MathFunction
 
-     {
 
-         public String FunctionName { get; set; }
 
-         public MathCalculator.CalculateFunctionDelegate FunctionDelegate { get; set; }
 
-     }
 
-     public class MathParameterValue
 
-     {
 
-         public MathCalculator.Parameter Variable { get; set; }
 
-         public decimal Value { get; set; }
 
-     }
 
- }
 
-  
 
 
  |