Project_WL/Assets/WL/Data/WLTableValue.cs

68 lines
3.7 KiB
C#

// ─────────────────────────────────────────────────────────────────────────────
// WLTableValue.cs — 표의 문자형 값(s_Value) 해석 (PD #898 · 2026-10-17)
//
// PD 원문: 「장비 옵션의 value는 문형으로 읽되, 숫자는 정수로, 소수점이 있으면 실수로,
// 60.25%와 같이 %를 입력하면 해당 확률에 맞게 지정되도록 구현할 것.」
//
// ■ 규칙 — "20" → 정수 20 · "1.5" → 실수 1.5 · "60.25%" → 확률(비율) 0.6025 · 빈칸 → 없음
// 앞뒤 공백 무시 · 앞의 '+' 허용("+20" = 20) · 소수점은 '.' 만(문화권 무관) · 읽지 못하면 없음(raw 는 남김)
// ■ 쓰임 — 장비 옵션 표 s_Value · 스킬 표 s_Value1~5 · s_TriggerValue (같은 규칙)
// ─────────────────────────────────────────────────────────────────────────────
using System.Globalization;
using UnityEngine;
namespace WL.Data
{
public enum eTableValueKind { None, Int, Float, Percent }
public struct WLTableValue
{
public eTableValueKind kind;
public int intValue; // kind Int
public float floatValue; // kind Float = 그 수 · kind Percent = 비율(60.25% → 0.6025)
public string raw;
public bool IsNone { get { return kind == eTableValueKind.None; } }
/// <summary>실수로 쓸 때 — 정수 · 실수는 그 수, 확률은 비율(0~1).</summary>
public float AsFloat { get { return kind == eTableValueKind.Int ? intValue : floatValue; } }
/// <summary>정수로 쓸 때 — 실수 · 확률은 반올림.</summary>
public int AsInt { get { return kind == eTableValueKind.Int ? intValue : Mathf.RoundToInt(floatValue); } }
public static WLTableValue Parse(string s)
{
var v = new WLTableValue { raw = s };
if (string.IsNullOrEmpty(s)) return v;
s = s.Trim();
bool percent = s.EndsWith("%");
if (percent) s = s.Substring(0, s.Length - 1).Trim();
if (s.StartsWith("+")) s = s.Substring(1).Trim();
if (s.Length == 0) return v;
const NumberStyles kDecimal = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint; // 지수 표기(1e3) 받지 않음
if (percent)
{
float p;
if (float.TryParse(s, kDecimal, CultureInfo.InvariantCulture, out p)) { v.kind = eTableValueKind.Percent; v.floatValue = p / 100f; }
return v;
}
int n;
if (s.IndexOf('.') < 0 && int.TryParse(s, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out n)) { v.kind = eTableValueKind.Int; v.intValue = n; return v; }
float f;
if (float.TryParse(s, kDecimal, CultureInfo.InvariantCulture, out f)) { v.kind = eTableValueKind.Float; v.floatValue = f; }
return v;
}
public override string ToString()
{
switch (kind)
{
case eTableValueKind.Int: return "정수 " + intValue;
case eTableValueKind.Float: return "실수 " + floatValue.ToString("0.####", CultureInfo.InvariantCulture);
case eTableValueKind.Percent: return "확률 " + floatValue.ToString("0.######", CultureInfo.InvariantCulture);
default: return "없음" + (string.IsNullOrEmpty(raw) ? "" : "(읽지 못함: " + raw + ")");
}
}
}
}