using System; using System.Collections.Generic; using System.Linq; using AGVNavigationCore.Models; namespace AGVNavigationCore.PathFinding { /// /// AGV 경로 계산 결과 (방향성 및 명령어 포함) /// public class AGVPathResult { /// /// 경로 찾기 성공 여부 /// public bool Success { get; set; } /// /// 경로 노드 ID 목록 (시작 → 목적지 순서) /// public List Path { get; set; } /// /// AGV 명령어 목록 (이동 방향 시퀀스) /// public List Commands { get; set; } /// /// 노드별 모터방향 정보 목록 /// public List NodeMotorInfos { get; set; } /// /// 총 거리 /// public float TotalDistance { get; set; } /// /// 계산 소요 시간 (밀리초) /// public long CalculationTimeMs { get; set; } /// /// 예상 소요 시간 (초) /// public float EstimatedTimeSeconds { get; set; } /// /// 회전 횟수 /// public int RotationCount { get; set; } /// /// 오류 메시지 (실패시) /// public string ErrorMessage { get; set; } /// /// 기본 생성자 /// public AGVPathResult() { Success = false; Path = new List(); Commands = new List(); NodeMotorInfos = new List(); TotalDistance = 0; CalculationTimeMs = 0; EstimatedTimeSeconds = 0; RotationCount = 0; ErrorMessage = string.Empty; } /// /// 성공 결과 생성 /// /// 경로 /// AGV 명령어 목록 /// 총 거리 /// 계산 시간 /// 성공 결과 public static AGVPathResult CreateSuccess(List path, List commands, float totalDistance, long calculationTimeMs) { var result = new AGVPathResult { Success = true, Path = new List(path), Commands = new List(commands), TotalDistance = totalDistance, CalculationTimeMs = calculationTimeMs }; result.CalculateMetrics(); return result; } /// /// 성공 결과 생성 (노드별 모터방향 정보 포함) /// /// 경로 /// AGV 명령어 목록 /// 노드별 모터방향 정보 /// 총 거리 /// 계산 시간 /// 성공 결과 public static AGVPathResult CreateSuccess(List path, List commands, List nodeMotorInfos, float totalDistance, long calculationTimeMs) { var result = new AGVPathResult { Success = true, Path = new List(path), Commands = new List(commands), NodeMotorInfos = new List(nodeMotorInfos), TotalDistance = totalDistance, CalculationTimeMs = calculationTimeMs }; result.CalculateMetrics(); return result; } /// /// 실패 결과 생성 /// /// 오류 메시지 /// 계산 시간 /// 실패 결과 public static AGVPathResult CreateFailure(string errorMessage, long calculationTimeMs) { return new AGVPathResult { Success = false, ErrorMessage = errorMessage, CalculationTimeMs = calculationTimeMs }; } /// /// 경로 메트릭 계산 /// private void CalculateMetrics() { RotationCount = CountRotations(); EstimatedTimeSeconds = CalculateEstimatedTime(); } /// /// 회전 횟수 계산 /// private int CountRotations() { int count = 0; foreach (var command in Commands) { if (command == AgvDirection.Left || command == AgvDirection.Right) { count++; } } return count; } /// /// 예상 소요 시간 계산 /// /// AGV 속도 (픽셀/초, 기본값: 100) /// 회전 시간 (초, 기본값: 3) /// 예상 소요 시간 (초) private float CalculateEstimatedTime(float agvSpeed = 100.0f, float rotationTime = 3.0f) { float moveTime = TotalDistance / agvSpeed; float totalRotationTime = RotationCount * rotationTime; return moveTime + totalRotationTime; } /// /// 명령어 요약 생성 /// /// 명령어 요약 문자열 public string GetCommandSummary() { if (!Success) return "실패"; var summary = new List(); var currentCommand = AgvDirection.Stop; var count = 0; foreach (var command in Commands) { if (command == currentCommand) { count++; } else { if (count > 0) { summary.Add($"{GetCommandText(currentCommand)}×{count}"); } currentCommand = command; count = 1; } } if (count > 0) { summary.Add($"{GetCommandText(currentCommand)}×{count}"); } return string.Join(" → ", summary); } /// /// 명령어 텍스트 반환 /// private string GetCommandText(AgvDirection command) { switch (command) { case AgvDirection.Forward: return "전진"; case AgvDirection.Backward: return "후진"; case AgvDirection.Left: return "좌회전"; case AgvDirection.Right: return "우회전"; case AgvDirection.Stop: return "정지"; default: return command.ToString(); } } /// /// 상세 경로 정보 반환 /// /// 상세 정보 문자열 public string GetDetailedInfo() { if (!Success) { return $"경로 계산 실패: {ErrorMessage} (계산시간: {CalculationTimeMs}ms)"; } return $"경로: {Path.Count}개 노드, 거리: {TotalDistance:F1}px, " + $"회전: {RotationCount}회, 예상시간: {EstimatedTimeSeconds:F1}초, " + $"계산시간: {CalculationTimeMs}ms"; } /// /// PathResult로 변환 (호환성을 위해) /// /// PathResult 객체 public PathResult ToPathResult() { if (Success) { return PathResult.CreateSuccess(Path, TotalDistance, CalculationTimeMs, 0); } else { return PathResult.CreateFailure(ErrorMessage, CalculationTimeMs, 0); } } /// /// 문자열 표현 /// public override string ToString() { if (Success) { return $"Success: {Path.Count} nodes, {TotalDistance:F1}px, {RotationCount} rotations, {EstimatedTimeSeconds:F1}s"; } else { return $"Failed: {ErrorMessage}"; } } } }