#nullable enable using System; using System.Collections.Generic; using UVC.Core; namespace UVC.Factory.Component { /// /// 씬에 존재하는 모든 FactoryObject 인스턴스를 관리하는 싱글톤 클래스입니다. /// 이 매니저를 통해 팩토리 객체를 등록, 등록 해제 및 검색할 수 있습니다. /// /// /// SingletonScene을 상속받아 구현되었으므로, `FactoryObjectManager.Instance`를 통해 씬의 어디에서든 쉽게 접근할 수 있습니다. /// FactoryObject는 Info 속성이 설정될 때 자동으로 이 매니저에 등록되며, 파괴될 때 자동으로 등록 해제됩니다. /// 따라서 개발자가 직접 Register/Unregister 메서드를 호출할 일은 거의 없습니다. /// /// /// 다음은 FactoryObjectManager를 사용하여 씬에 있는 특정 기계를 찾고 제어하는 예제입니다. /// /// using UnityEngine; /// using UVC.Factory.Component; /// using UVC.Data; /// /// public class ControlPanel : MonoBehaviour /// { /// void Start() /// { /// // 가정: 씬 어딘가에 이미 FactoryObject(예: MachineObject)가 생성되어 있고, /// // Info 속성이 설정되어 FactoryObjectManager에 등록된 상태입니다. /// // /// // var machine = new MachineObject(); /// // machine.Info = new FactoryObjectInfo("Drill-01", "MC-1024", ...); /// } /// /// // UI 버튼 클릭 시 호출될 함수 /// public void OnFindAndStartMachineButtonClick() /// { /// // 1. ID를 사용하여 FactoryObjectManager에서 특정 기계를 찾습니다. /// FactoryObject machine = FactoryObjectManager.Instance.FindById("MC-1024"); /// /// if (machine != null) /// { /// Debug.Log($"기계를 찾았습니다: {machine.Info.Name}"); /// /// // 2. 찾은 기계의 데이터를 업데이트하여 가동시킵니다. /// var command = new DataObject { { "status", "running" } }; /// machine.UpdateData(command); /// } /// else /// { /// Debug.LogWarning("ID 'MC-1024'에 해당하는 기계를 찾을 수 없습니다."); /// } /// } /// /// // 특정 구역의 모든 객체를 찾는 예시 /// public void OnFindAllObjectsInArea_A_ButtonClick() /// { /// // "Area-A" 구역에 있는 모든 객체를 찾습니다. /// List objectsInArea = FactoryObjectManager.Instance.FindByArea("Area-A"); /// /// Debug.Log($"'Area-A' 구역에서 {objectsInArea.Count}개의 객체를 찾았습니다."); /// /// foreach (var obj in objectsInArea) /// { /// Debug.Log($"- 객체 이름: {obj.Info.Name}, ID: {obj.Info.Id}"); /// } /// } /// } /// /// public class FactoryObjectManager : SingletonScene { /// /// 등록된 모든 FactoryObject를 저장하는 딕셔너리입니다. /// Key는 객체의 식별 정보인 FactoryObjectInfo이고, Value는 FactoryObject 인스턴스입니다. /// public Dictionary FactoryObjects { get; private set; } = new Dictionary(); /// /// 새로운 FactoryObject를 매니저에 등록합니다. /// 일반적으로 FactoryObject의 Info 속성이 설정될 때 자동으로 호출됩니다. /// /// 등록할 FactoryObject 인스턴스입니다. /// factoryObject 또는 factoryObject.Info가 null일 때 발생합니다. public void RegisterFactoryObject(FactoryObject factoryObject) { if (factoryObject == null || factoryObject.Info == null) { throw new ArgumentNullException(nameof(factoryObject), "FactoryObject cannot be null."); } if (!FactoryObjects.ContainsKey(factoryObject.Info!)) { FactoryObjects.Add(factoryObject.Info!, factoryObject); } } /// /// 매니저에서 FactoryObject의 등록을 해제합니다. /// 일반적으로 FactoryObject가 파괴될 때(OnDestroy) 자동으로 호출됩니다. /// /// 등록 해제할 객체의 FactoryObjectInfo입니다. public void UnregisterFactoryObject(FactoryObjectInfo factoryObjectInfo) { if (factoryObjectInfo == null) { //throw new ArgumentNullException(nameof(factoryObjectInfo), "factoryObjectInfo cannot be null."); return; // Do not throw exception, just return if null } FactoryObjects.Remove(factoryObjectInfo); } /// /// FactoryObjectInfo를 사용하여 등록된 FactoryObject 인스턴스를 가져옵니다. /// /// 찾고자 하는 객체의 FactoryObjectInfo입니다. /// 발견된 FactoryObject 인스턴스. 없으면 null을 반환합니다. /// factoryObjectInfo가 null일 때 발생합니다. public FactoryObject? GetFactoryObject(FactoryObjectInfo factoryObjectInfo) { if (factoryObjectInfo == null) { throw new ArgumentNullException(nameof(factoryObjectInfo), "factoryObjectInfo cannot be null."); } FactoryObjects.TryGetValue(factoryObjectInfo, out var factoryObject); return factoryObject; } /// /// 객체의 이름(Name)으로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다. /// /// 찾고자 하는 객체의 이름입니다. /// 처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다. public FactoryObject? FindByName(string name) { foreach (var kvp in FactoryObjects) { if (kvp.Key.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) { return kvp.Value; } } return null; } /// /// 객체의 고유 ID로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다. /// /// 찾고자 하는 객체의 ID입니다. /// 처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다. public FactoryObject? FindById(string id) { foreach (var kvp in FactoryObjects) { if (kvp.Key.Id.Equals(id, StringComparison.OrdinalIgnoreCase)) { return kvp.Value; } } return null; } /// /// 객체의 위치(Position) 정보로 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다. /// /// 찾고자 하는 객체의 위치 정보입니다. /// 처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다. public FactoryObject? FindByPosition(string position) { foreach (var kvp in FactoryObjects) { if (kvp.Key.Position.Equals(position, StringComparison.OrdinalIgnoreCase)) { return kvp.Value; } } return null; } /// /// 특정 구역(Area)에 속한 모든 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다. /// /// 찾고자 하는 구역의 이름입니다. /// 발견된 모든 FactoryObject의 리스트. 없으면 빈 리스트를 반환합니다. public List FindByArea(string area) { List foundObjects = new List(); foreach (var kvp in FactoryObjects) { if (kvp.Key.Area.Equals(area, StringComparison.OrdinalIgnoreCase)) { foundObjects.Add(kvp.Value); } } return foundObjects; } /// /// 특정 층(Floor)에 속한 모든 FactoryObject를 검색합니다. 대소문자를 구분하지 않습니다. /// /// 찾고자 하는 층의 이름입니다. /// 발견된 모든 FactoryObject의 리스트. 없으면 빈 리스트를 반환합니다. public List FindByFloor(string floor) { List foundObjects = new List(); foreach (var kvp in FactoryObjects) { if (kvp.Key.Floor.Equals(floor, StringComparison.OrdinalIgnoreCase)) { foundObjects.Add(kvp.Value); } } return foundObjects; } /// /// 전체 FactoryObjectInfo를 반환합니다. /// /// public List GetAllFactoryObjectInfos() { List infos = new List(); foreach (var kvp in FactoryObjects) { infos.Add(kvp.Key); } return infos; } /// /// FactoryObject 인스턴스의 리스트를 반환합니다. /// /// public List GetAllFactoryObjects() { List objects = new List(); foreach (var kvp in FactoryObjects) { objects.Add(kvp.Value); } return objects; } /// /// category 이름을 key, FactoryObjectInfo 리스트가 value인 딕셔너리를 반환합니다. /// /// public SortedDictionary> GetFactoryObjectInfosByCategory() { SortedDictionary> categoryDict = new SortedDictionary>(); foreach (var kvp in FactoryObjects) { var info = kvp.Key; if (!categoryDict.ContainsKey(info.Category)) { categoryDict[info.Category] = new List(); } categoryDict[info.Category].Add(info); } //key 순 정렬 //name 순 정렬 foreach (var key in categoryDict.Keys) { categoryDict[key].Sort((a, b) => a.Name.CompareTo(b.Name)); } return categoryDict; } } }