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