| using System; | 
| using System.Collections; | 
| using System.Collections.Generic; | 
| using System.Text; | 
| using System.Text.RegularExpressions; | 
| using UnityEngine; | 
|   | 
|   | 
| public class Equation : Singleton<Equation> | 
| { | 
|     public static readonly List<char> operatorList = new List<char>() { '*', '-', '+', '/', '^', '!', '@', '%', ';', '#', '$', '~', '&' }; | 
|   | 
|     public static StringBuilder textBuilder = new StringBuilder(); | 
|   | 
|     private List<KeyValuePair<string, string>> keyValueDic = new List<KeyValuePair<string, string>>(); | 
|   | 
|     public readonly Regex replaecRegex = new Regex(@"[a-zA-Z]{2,50}"); | 
|   | 
|     public T Eval<T>(string equation) where T : struct | 
|     { | 
|         keyValueDic.Sort(Compare); | 
|         equation = GetEquation(equation); | 
|         T val = default(T); | 
|         try | 
|         { | 
|             EquationParse equationParse = new EquationParse(equation); | 
|             val = (T)Convert.ChangeType(equationParse.result, typeof(T)); | 
|             equationParse = null; | 
|         } | 
|         catch (Exception e) | 
|         { | 
|             Debug.LogError(e.Message); | 
|         } | 
|         return val; | 
|     } | 
|   | 
|     private string GetEquation(string equation) | 
|     { | 
|         try | 
|         { | 
|             MatchCollection matchArray = replaecRegex.Matches(equation); | 
|             textBuilder.Length = 0; | 
|             int length = 0; | 
|             if (matchArray != null) | 
|             { | 
|                 for (int i = 0; i < matchArray.Count; i++) | 
|                 { | 
|                     Match match = matchArray[i]; | 
|                     textBuilder.Append(equation.Substring(length, match.Index - length)); | 
|                     length = match.Index + match.Length; | 
|                     bool _replace = false; | 
|                     for (int j = 0; j < keyValueDic.Count; j++) | 
|                     { | 
|                         if (match.Value.Equals(keyValueDic[j].Key)) | 
|                         { | 
|                             textBuilder.Append(keyValueDic[j].Value); | 
|                             _replace = true; | 
|                             break; | 
|                         } | 
|                     } | 
|                     if (!_replace) | 
|                     { | 
|                         textBuilder.Append(0); | 
|                     } | 
|                 } | 
|             } | 
|             textBuilder.Append(equation.Substring(length, equation.Length - length)); | 
|         } | 
|         catch (Exception e) | 
|         { | 
|             Debug.Log(e.Message); | 
|         } | 
|         return textBuilder.ToString(); | 
|     } | 
|   | 
|     public void AddKeyValue(string key, object val) | 
|     { | 
|         int index = keyValueDic.FindIndex((x) => { | 
|             return x.Key == key; | 
|         }); | 
|         if (index == -1) | 
|         { | 
|             KeyValuePair<string, string> keyValuePair = new KeyValuePair<string, string>(key, val.ToString()); | 
|             keyValueDic.Add(keyValuePair); | 
|         } | 
|     } | 
|   | 
|     public void Clear() | 
|     { | 
|         keyValueDic.Clear(); | 
|     } | 
|   | 
|     int Compare(KeyValuePair<string, string> x, KeyValuePair<string, string> y) | 
|     { | 
|         return -x.Key.Length.CompareTo(y.Key.Length); | 
|     } | 
|   | 
|     public class EquationParse | 
|     { | 
|         public string equation { get; private set; } | 
|         public string result { get; private set; } | 
|         private StringBuilder equationBuilder = new StringBuilder(); | 
|         private List<EquationParse> subEquations = new List<EquationParse>(); | 
|         private List<OperatorType> operatorTypeList = new List<OperatorType>(); | 
|         private List<string> values = new List<string>(); | 
|         public EquationParse(string _equation) | 
|         { | 
|             this.equation = _equation; | 
|             this.result = string.Empty; | 
|             equationBuilder.Length = 0; | 
|             if (CheckSplit()) | 
|             { | 
|                 return; | 
|             } | 
|             Subsection(); | 
|             GetResult(); | 
|         } | 
|         private bool CheckSplit() | 
|         { | 
|             var _left = string.Empty; | 
|             var _right = string.Empty; | 
|             OperatorType _operatorType; | 
|             if (Split(equation, out _left, out _right, out _operatorType)) | 
|             { | 
|                 var _leftResult = new EquationParse(_left); | 
|                 var _rightResult = new EquationParse(_right); | 
|                 result = GetResult(_leftResult.result, _rightResult.result, _operatorType).ToString(); | 
|                 return true; | 
|             } | 
|             return false; | 
|         } | 
|         private void Subsection() | 
|         { | 
|             try | 
|             { | 
|                 int bracketCnt = 0; | 
|                 int startIndex = 0; | 
|                 int length = 0; | 
|                 int index = 0; | 
|                 for (int i = 0; i < equation.Length; i++) | 
|                 { | 
|                     if (equation[i] == '(') | 
|                     { | 
|                         i = i + 1; | 
|                         startIndex = i; | 
|                         while (i < equation.Length && (equation[i] != ')' || bracketCnt > 0)) | 
|                         { | 
|                             if (equation[i] == '(') | 
|                             { | 
|                                 bracketCnt++; | 
|                             } | 
|                             else if (equation[i] == ')') | 
|                             { | 
|                                 bracketCnt--; | 
|                             } | 
|                             length++; | 
|                             i = i + 1; | 
|                         } | 
|                         subEquations.Add(new EquationParse(equation.Substring(startIndex, length))); | 
|                         length = 0; | 
|                         equationBuilder.Append('='); | 
|                         equationBuilder.Append(index); | 
|                         equationBuilder.Append('='); | 
|                         index++; | 
|                         continue; | 
|                     } | 
|                     equationBuilder.Append(equation[i]); | 
|                 } | 
|             } | 
|             catch (Exception e) | 
|             { | 
|                 Debug.Log(e.Message); | 
|             } | 
|         } | 
|   | 
|         private void AnalysisEquation() | 
|         { | 
|             try | 
|             { | 
|                 textBuilder.Length = 0; | 
|                 for (int i = 0; i < subEquations.Count; i++) | 
|                 { | 
|                     equationBuilder.Replace(string.Format("={0}=", i), subEquations[i].result); | 
|                     subEquations[i] = null; | 
|                 } | 
|                 subEquations.Clear(); | 
|                 var _result = equationBuilder.ToString(); | 
|                 char _lastChar = default(char); | 
|                 for (int i = 0; i < _result.Length; i++) | 
|                 { | 
|                     if (i - 1 > 0 && _result[i - 1] == 'E') | 
|                     {//过滤超大数值后的符号 | 
|                         textBuilder.Append(_result[i]); | 
|                         continue; | 
|                     } | 
|                     int index = operatorList.IndexOf(_result[i]); | 
|                     if (index != -1 && _lastChar >= '0' && _lastChar <= '9') | 
|                     { | 
|                         values.Add(textBuilder.ToString()); | 
|                         textBuilder.Length = 0; | 
|                         operatorTypeList.Add(GetOperatorType(_result[i])); | 
|                     } | 
|                     else | 
|                     { | 
|                         textBuilder.Append(_result[i]); | 
|                     } | 
|                     _lastChar = _result[i]; | 
|                 } | 
|                 values.Add(textBuilder.ToString()); | 
|             } | 
|             catch (Exception e) | 
|             { | 
|                 Debug.Log(e.Message); | 
|             } | 
|         } | 
|   | 
|         public void GetResult() | 
|         { | 
|             AnalysisEquation(); | 
|             try | 
|             { | 
|                 for (int i = 0; i < operatorTypeList.Count; i++) | 
|                 { | 
|                     if (IsPriorityOperator(operatorTypeList[i])) | 
|                     { | 
|                         double _result = 0; | 
|                         if (IsUnaryOperator(operatorTypeList[i])) | 
|                         { | 
|                             _result = GetResult(values[i], string.Empty, operatorTypeList[i]); | 
|                         } | 
|                         else | 
|                         { | 
|                             _result = GetResult(values[i], values[i + 1], operatorTypeList[i]); | 
|                             values.RemoveAt(i); | 
|                         } | 
|                         values.RemoveAt(i); | 
|                         values.Insert(i, _result.ToString()); | 
|                         operatorTypeList.RemoveAt(i); | 
|                         i--; | 
|                     } | 
|                 } | 
|                 while (values.Count > 1 && operatorTypeList.Count > 0) | 
|                 { | 
|                     double _result = 0; | 
|                     if (IsUnaryOperator(operatorTypeList[0])) | 
|                     { | 
|                         _result = GetResult(values[0], string.Empty, operatorTypeList[0]); | 
|                     } | 
|                     else | 
|                     { | 
|                         _result = GetResult(values[0], values[1], operatorTypeList[0]); | 
|                         values.RemoveAt(0); | 
|                     } | 
|                     values.RemoveAt(0); | 
|                     values.Insert(0, _result.ToString()); | 
|                     operatorTypeList.RemoveAt(0); | 
|                 } | 
|                 if (operatorTypeList.Count == 1 && IsUnaryOperator(operatorTypeList[0])) | 
|                 { | 
|                     result = GetResult(values[0], string.Empty, operatorTypeList[0]).ToString(); | 
|                 } | 
|                 else | 
|                 { | 
|                     result = values[0]; | 
|                 } | 
|             } | 
|             catch (Exception e) | 
|             { | 
|                 Debug.Log(e.Message); | 
|             } | 
|         } | 
|   | 
|         public static double GetResult(string leftValue, string rightValue, OperatorType operatorType) | 
|         { | 
|             double _leftValue = 0, _rightValue = 0; | 
|             try | 
|             { | 
|                 double.TryParse(leftValue, out _leftValue); | 
|                 double.TryParse(rightValue, out _rightValue); | 
|             } | 
|             catch (Exception) | 
|             { | 
|                 Debug.LogErrorFormat("字符串不能转为数值{0}   {1}", leftValue, rightValue); | 
|             } | 
|             switch (operatorType) | 
|             { | 
|                 case OperatorType.Plus: | 
|                     return _leftValue + _rightValue; | 
|                 case OperatorType.Subtract: | 
|                     return _leftValue - _rightValue; | 
|                 case OperatorType.Ride: | 
|                     return _leftValue * _rightValue; | 
|                 case OperatorType.Divide: | 
|                     if (_rightValue == 0) | 
|                     { | 
|                         _rightValue = 1; | 
|                     } | 
|                     return _leftValue / _rightValue; | 
|                 case OperatorType.Pow: | 
|                     return Math.Pow(_leftValue, _rightValue); | 
|                 case OperatorType.Min: | 
|                     return Math.Min(_leftValue, _rightValue); | 
|                 case OperatorType.Max: | 
|                     return Math.Max(_leftValue, _rightValue); | 
|                 case OperatorType.Remain: | 
|                     return _leftValue % _rightValue; | 
|                 case OperatorType.Random: | 
|                     { | 
|                         return UnityEngine.Random.Range((float)_leftValue, (float)_rightValue); | 
|                     } | 
|                 case OperatorType.Floor: | 
|                     return Math.Floor(_leftValue); | 
|                 case OperatorType.Ceil: | 
|                     return Math.Ceiling((float)_leftValue); | 
|                 case OperatorType.RandomInt: | 
|                     { | 
|                         return UnityEngine.Random.Range((int)_leftValue, (int)_rightValue); | 
|                     } | 
|                 case OperatorType.Sqrt: | 
|                     return Math.Sqrt(_leftValue); | 
|   | 
|             } | 
|             return 0; | 
|         } | 
|         public static OperatorType GetOperatorType(char _operator) | 
|         { | 
|             switch (_operator) | 
|             { | 
|                 case '+': | 
|                     return OperatorType.Plus; | 
|                 case '-': | 
|                     return OperatorType.Subtract; | 
|                 case '*': | 
|                     return OperatorType.Ride; | 
|                 case '/': | 
|                     return OperatorType.Divide; | 
|                 case '^': | 
|                     return OperatorType.Pow; | 
|                 case '!': | 
|                     return OperatorType.Min; | 
|                 case '@': | 
|                     return OperatorType.Max; | 
|                 case '%': | 
|                     return OperatorType.Remain; | 
|                 case ';': | 
|                     return OperatorType.Random; | 
|                 case '#': | 
|                     return OperatorType.Floor; | 
|                 case '$': | 
|                     return OperatorType.Ceil; | 
|                 case '~': | 
|                     return OperatorType.RandomInt; | 
|                 case '&': | 
|                     return OperatorType.Sqrt; | 
|             } | 
|             return OperatorType.Plus; | 
|         } | 
|         public static bool IsPriorityOperator(OperatorType operatorType) | 
|         { | 
|             if (operatorType == OperatorType.Plus || operatorType == OperatorType.Subtract) | 
|             { | 
|                 return false; | 
|             } | 
|             return true; | 
|         } | 
|         public static bool IsUnaryOperator(OperatorType operatorType) | 
|         { | 
|             if (operatorType == OperatorType.Floor || operatorType == OperatorType.Ceil | 
|                 || operatorType == OperatorType.Sqrt) | 
|             { | 
|                 return true; | 
|             } | 
|             return false; | 
|         } | 
|   | 
|         private static bool Split(string _source, out string _left, out string _right, out OperatorType _type) | 
|         { | 
|             _left = _right = string.Empty; | 
|             _type = OperatorType.Plus; | 
|             try | 
|             { | 
|                 var _index = 0; | 
|                 for (int i = _source.Length - 1; i >= 0; i--) | 
|                 { | 
|                     if (_source[i] == ')') | 
|                     { | 
|                         _index++; | 
|                         continue; | 
|                     } | 
|                     else if (_source[i] == '(') | 
|                     { | 
|                         _index--; | 
|                         continue; | 
|                     } | 
|                     if (IsSplitOperator(_source[i], out _type) && _index == 0) | 
|                     { | 
|                         _left = _source.Substring(0, i); | 
|                         if (i + 1 < _source.Length) | 
|                         { | 
|                             _right = _source.Substring(i + 1); | 
|                         } | 
|                         return true; | 
|                     } | 
|                 } | 
|             } | 
|             catch (Exception e) | 
|             { | 
|                 Debug.Log(e.Message); | 
|             } | 
|             return false; | 
|         } | 
|   | 
|         public static bool IsSplitOperator(char _char, out OperatorType _type) | 
|         { | 
|             var _index = operatorList.FindIndex((x) => | 
|             { | 
|                 return x == _char; | 
|             }); | 
|             _type = OperatorType.Plus; | 
|             if (_index == -1) | 
|             { | 
|                 return false; | 
|             } | 
|             _type = GetOperatorType(_char); | 
|             switch (_type) | 
|             { | 
|                 case OperatorType.Floor: | 
|                 case OperatorType.Ceil: | 
|                 case OperatorType.Min: | 
|                 case OperatorType.Max: | 
|                 case OperatorType.Remain: | 
|                 case OperatorType.Pow: | 
|                 case OperatorType.Random: | 
|                 case OperatorType.RandomInt: | 
|                 case OperatorType.Sqrt: | 
|                     return true; | 
|             } | 
|             return false; | 
|         } | 
|     } | 
|   | 
|     public enum OperatorType | 
|     { | 
|         Plus,//+ | 
|         Subtract,//- | 
|         Ride,//* | 
|         Divide,// / | 
|         Pow,// ^ | 
|         Min,// ! | 
|         Max,// @ | 
|         Remain,// % | 
|         Random, | 
|         Floor, | 
|         Ceil, | 
|         RandomInt, | 
|         Sqrt | 
|     } | 
| } |