using System.Collections.Generic; using System.Text.RegularExpressions; using Superlazy; public class Evaluator { public static string Evaluate(SLEntity player, string desc) { if (desc.StartsWith('$') == false) return desc; // 변수 대체: {name} 패턴을 찾아 Global.Get으로 변환 var replacedDesc = Regex.Replace(desc.Substring(1), @"\{(\w+)\}", match => { var varName = match.Groups[1].Value; var ret = player["EventValues"].Get(varName); // 그냥 글로벌로 하면 변수 길어질듯해서 if (ret.IsValue && ret.IsNumeric == false) return $"\"{ret}\""; return ret; }); return EvaluateExpression(replacedDesc); } private static SLEntity EvaluateExpression(string expression) { var values = new Stack(); // 값을 저장하는 스택 (숫자 또는 문자열) var operators = new Stack(); // 연산자를 저장하는 스택 var i = 0; while (i < expression.Length) { if (char.IsDigit(expression[i])) // 숫자 처리 { var number = ""; while (i < expression.Length && (char.IsDigit(expression[i]) || expression[i] == '.')) { number += expression[i]; i++; } values.Push(float.Parse(number)); } else if (expression[i] == '"') // 문자열 처리 { // 문자열 리터럴 처리 (큰 따옴표로 감싸진 문자열) i++; var str = ""; while (i < expression.Length && expression[i] != '"') { str += expression[i]; i++; } i++; // 닫는 따옴표 넘기기 values.Push(str); } else if (expression[i] == '(') { operators.Push('('); i++; } else if (expression[i] == ')') { while (operators.Peek() != '(') { values.Push(ApplyOperator(values.Pop(), values.Pop(), operators.Pop())); } operators.Pop(); // '(' 제거 i++; } else if (IsOperator(expression[i])) { // 연산자 처리 while (operators.Count > 0 && GetPrecedence(operators.Peek()) >= GetPrecedence(expression[i])) { values.Push(ApplyOperator(values.Pop(), values.Pop(), operators.Pop())); } operators.Push(expression[i]); i++; } else { // 공백 등 기타 문자는 그냥 넘김 i++; } } while (operators.Count > 0) { values.Push(ApplyOperator(values.Pop(), values.Pop(), operators.Pop())); } return values.Pop(); } // 연산자 우선순위 private static int GetPrecedence(char op) { if (op == '+' || op == '-') return 1; if (op == '*' || op == '/') return 2; return 0; } // 연산자 확인 private static bool IsOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } // 연산자 적용 private static SLEntity ApplyOperator(SLEntity right, SLEntity left, char op) { return op switch { '+' => left + right, '-' => left - right, '*' => left * right, '/' => left / right, _ => SLEntity.Empty, }; } public static void ApplyEvaluate(SLEntity player, SLEntity current) { foreach (var c in current) { if (c.IsValue && c.IsNumeric == false) { current[c.ID] = Evaluate(player, c); } else if (c.IsValue == false) { ApplyEvaluate(player, c); } } } }