using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using UnityEngine; using UnityEngine.Rendering.Universal; [Serializable] public abstract class Policy_Base { public string type; [JsonIgnore] public abstract SpawnPolicy policy { get; } } [Serializable] public class Policy_Constant : Policy_Base { public float value; public override SpawnPolicy policy => SpawnPolicy.Constant; } [Serializable] public class Policy_Normal : Policy_Base { public float mean; public float stddev; public override SpawnPolicy policy => SpawnPolicy.Normal; } [Serializable] public class Policy_Uniform : Policy_Base { public float min_val; public float max_val; public override SpawnPolicy policy => SpawnPolicy.Uniform; } [Serializable] public class Policy_Exponential : Policy_Base { public float mean; public override SpawnPolicy policy => SpawnPolicy.Exponential; } [Serializable] public class Policy_Triangular : Policy_Base { public float min_val; public float mode; public float max_val; public override SpawnPolicy policy => SpawnPolicy.Triangular; } public sealed class PolicyConverter : JsonConverter { public override bool CanConvert(Type objectType) => objectType == typeof(Policy_Base); public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jo = JObject.Load(reader); var typeStr = (jo["type"]?.ToString() ?? "").Trim().ToLowerInvariant(); Policy_Base target = typeStr switch { "constant" => new Policy_Constant(), "normal" => new Policy_Normal(), "uniform" => new Policy_Uniform(), "exponential" => new Policy_Exponential(), "triangular" => new Policy_Triangular(), _ => new Policy_Constant() }; // jo 내용을 target에 채워 넣음 serializer.Populate(jo.CreateReader(), target); return target; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 필요 시 구현 (서버로 다시 보낼 때) serializer.Serialize(writer, value); } } public static class PolicyFactory { public static Policy_Base Create(string typeLower) { switch (typeLower) { case "Constant": return new Policy_Constant { type = "constant", value = 0f }; case "Normal": return new Policy_Normal { type = "normal", mean = 0f, stddev = 0f }; case "Uniform": return new Policy_Uniform { type = "uniform", min_val = 0f, max_val = 0f }; case "Exponential": return new Policy_Exponential { type = "exponential", mean = 0f }; case "Triangular": return new Policy_Triangular { type = "triangular", min_val = 0f, mode = 0f, max_val = 0f }; default: throw new ArgumentException($"Unknown policy type: {typeLower}"); } } public static Policy_Base ChangeType(Policy_Base oldPolicy, string newTypeLower) { var next = Create(newTypeLower); // 의미 있는 값 일부 이관(원하시는 정책 변환 규칙으로 조정) // “대표값”을 mean 계열로 최대한 유지하는 예시입니다. float representative = oldPolicy switch { Policy_Exponential e => e.mean, Policy_Normal n => n.mean, Policy_Constant c => c.value, Policy_Triangular t => t.mode, Policy_Uniform u => (u.min_val + u.max_val) * 0.5f, _ => 0f }; switch (next) { case Policy_Exponential e: e.mean = representative; break; case Policy_Normal n: n.mean = representative; n.stddev = 1f; break; case Policy_Constant c: c.value = representative; break; case Policy_Uniform u: u.min_val = Mathf.Max(0f, representative - 0.5f); u.max_val = representative + 0.5f; break; case Policy_Triangular t: t.mode = representative; t.min_val = Mathf.Max(0f, representative - 1f); t.max_val = representative + 1f; break; } return next; } }