using System; using System.IO; using Newtonsoft.Json; using PathLogic.Models; namespace PathLogic.Core { /// /// 맵 파일 로더 클래스 /// 기존 AGV 맵 에디터에서 생성한 JSON 파일을 로드 /// public class MapLoader { /// /// 파일에서 맵 데이터 로드 /// /// 맵 파일 경로 /// 로드된 맵 데이터 public MapData LoadFromFile(string filePath) { if (!File.Exists(filePath)) { throw new FileNotFoundException($"맵 파일을 찾을 수 없습니다: {filePath}"); } try { string jsonContent = File.ReadAllText(filePath); return LoadFromJson(jsonContent); } catch (Exception ex) { throw new Exception($"맵 파일 로드 중 오류 발생: {ex.Message}", ex); } } /// /// JSON 문자열에서 맵 데이터 로드 /// /// JSON 문자열 /// 로드된 맵 데이터 public MapData LoadFromJson(string jsonContent) { if (string.IsNullOrEmpty(jsonContent)) { throw new ArgumentException("JSON 내용이 비어있습니다."); } try { // JSON 역직렬화 설정 var settings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat, NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore }; // JSON 파일 구조 분석 var jsonObject = JsonConvert.DeserializeObject(jsonContent, settings); var mapData = new MapData(); // 메타데이터 로드 if (jsonObject.CreatedDate != null) { mapData.CreatedDate = jsonObject.CreatedDate; } if (jsonObject.Version != null) { mapData.Version = jsonObject.Version; } // 노드 데이터 로드 if (jsonObject.Nodes != null) { foreach (var nodeJson in jsonObject.Nodes) { var node = LoadNodeFromJson(nodeJson); if (node != null) { mapData.Nodes.Add(node); } } } // 맵 데이터 유효성 검증 var validationIssues = mapData.ValidateMap(); if (validationIssues.Count > 0) { Console.WriteLine("맵 데이터 검증 경고:"); foreach (var issue in validationIssues) { Console.WriteLine($" - {issue}"); } } Console.WriteLine($"맵 로드 완료: {mapData.GetStatistics()}"); return mapData; } catch (JsonException ex) { throw new Exception($"JSON 파싱 오류: {ex.Message}", ex); } catch (Exception ex) { throw new Exception($"맵 데이터 로드 중 오류: {ex.Message}", ex); } } /// /// JSON 객체에서 노드 데이터 로드 /// /// 노드 JSON 객체 /// 로드된 노드 private MapNode LoadNodeFromJson(dynamic nodeJson) { try { var node = new MapNode(); // 필수 필드 node.NodeId = nodeJson.NodeId ?? string.Empty; node.Name = nodeJson.Name ?? string.Empty; // 위치 정보 파싱 if (nodeJson.Position != null) { var position = nodeJson.Position.ToString(); node.Position = ParsePosition(position); } // 노드 타입 if (nodeJson.Type != null) { if (Enum.TryParse(nodeJson.Type.ToString(), out NodeType nodeType)) { node.Type = nodeType; } } // 도킹 방향 if (nodeJson.DockDirection != null) { if (Enum.TryParse(nodeJson.DockDirection.ToString(), out DockingDirection dockDirection)) { node.DockDirection = dockDirection; } } // 연결된 노드들 if (nodeJson.ConnectedNodes != null) { foreach (var connectedNodeId in nodeJson.ConnectedNodes) { if (connectedNodeId != null) { node.ConnectedNodes.Add(connectedNodeId.ToString()); } } } // 기타 속성들 if (nodeJson.CanRotate != null) node.CanRotate = nodeJson.CanRotate; if (nodeJson.StationId != null) node.StationId = nodeJson.StationId; if (nodeJson.StationType != null && Enum.TryParse(nodeJson.StationType.ToString(), out StationType stationType)) node.StationType = stationType; if (nodeJson.CreatedDate != null) node.CreatedDate = nodeJson.CreatedDate; if (nodeJson.ModifiedDate != null) node.ModifiedDate = nodeJson.ModifiedDate; if (nodeJson.IsActive != null) node.IsActive = nodeJson.IsActive; // RFID 정보 if (nodeJson.RfidId != null) node.RfidId = nodeJson.RfidId; if (nodeJson.RfidStatus != null) node.RfidStatus = nodeJson.RfidStatus; if (nodeJson.RfidDescription != null) node.RfidDescription = nodeJson.RfidDescription; // UI 관련 속성들 (맵 에디터 호환성을 위해) LoadUIProperties(node, nodeJson); // 기본 색상 설정 node.SetDefaultColorByType(node.Type); return node; } catch (Exception ex) { Console.WriteLine($"노드 로드 오류: {ex.Message}"); return null; } } /// /// UI 관련 속성 로드 /// /// 대상 노드 /// 노드 JSON 객체 private void LoadUIProperties(MapNode node, dynamic nodeJson) { try { if (nodeJson.LabelText != null) node.LabelText = nodeJson.LabelText; if (nodeJson.FontFamily != null) node.FontFamily = nodeJson.FontFamily; if (nodeJson.FontSize != null) node.FontSize = (float)nodeJson.FontSize; if (nodeJson.ImagePath != null) node.ImagePath = nodeJson.ImagePath; if (nodeJson.Opacity != null) node.Opacity = (float)nodeJson.Opacity; if (nodeJson.Rotation != null) node.Rotation = (float)nodeJson.Rotation; if (nodeJson.ShowBackground != null) node.ShowBackground = nodeJson.ShowBackground; // Scale 파싱 if (nodeJson.Scale != null) { var scale = nodeJson.Scale.ToString(); node.Scale = ParseScale(scale); } } catch (Exception ex) { Console.WriteLine($"UI 속성 로드 오류: {ex.Message}"); } } /// /// 위치 문자열을 Point로 파싱 /// 예: "65, 229" -> Point(65, 229) /// /// 위치 문자열 /// 파싱된 Point private System.Drawing.Point ParsePosition(string positionString) { try { if (string.IsNullOrEmpty(positionString)) return System.Drawing.Point.Empty; var parts = positionString.Split(','); if (parts.Length >= 2) { int x = int.Parse(parts[0].Trim()); int y = int.Parse(parts[1].Trim()); return new System.Drawing.Point(x, y); } } catch (Exception ex) { Console.WriteLine($"위치 파싱 오류: {positionString}, {ex.Message}"); } return System.Drawing.Point.Empty; } /// /// 스케일 문자열을 SizeF로 파싱 /// 예: "1, 1" -> SizeF(1.0f, 1.0f) /// /// 스케일 문자열 /// 파싱된 SizeF private System.Drawing.SizeF ParseScale(string scaleString) { try { if (string.IsNullOrEmpty(scaleString)) return new System.Drawing.SizeF(1.0f, 1.0f); var parts = scaleString.Split(','); if (parts.Length >= 2) { float width = float.Parse(parts[0].Trim()); float height = float.Parse(parts[1].Trim()); return new System.Drawing.SizeF(width, height); } } catch (Exception ex) { Console.WriteLine($"스케일 파싱 오류: {scaleString}, {ex.Message}"); } return new System.Drawing.SizeF(1.0f, 1.0f); } /// /// 맵 데이터를 JSON 파일로 저장 /// /// 저장할 맵 데이터 /// 저장할 파일 경로 public void SaveToFile(MapData mapData, string filePath) { try { var settings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat, NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented }; string jsonContent = JsonConvert.SerializeObject(mapData, settings); File.WriteAllText(filePath, jsonContent); Console.WriteLine($"맵 데이터 저장 완료: {filePath}"); } catch (Exception ex) { throw new Exception($"맵 파일 저장 중 오류: {ex.Message}", ex); } } } }