using System;
using System.Collections.Generic;
namespace AGVMapEditor.Models
{
///
/// A* 알고리즘에서 사용되는 경로 노드
///
public class PathNode : IComparable
{
///
/// 맵 노드 ID
///
public string NodeId { get; set; } = string.Empty;
///
/// AGV의 현재 방향 (이 노드에 도달했을 때의 방향)
///
public AgvDirection Direction { get; set; } = AgvDirection.Forward;
///
/// 시작점에서 이 노드까지의 실제 비용 (G)
///
public float GCost { get; set; } = float.MaxValue;
///
/// 이 노드에서 목표까지의 추정 비용 (H)
///
public float HCost { get; set; } = 0;
///
/// 총 비용 (F = G + H)
///
public float FCost => GCost + HCost;
///
/// 이전 노드 (경로 추적용)
///
public PathNode Parent { get; set; } = null;
///
/// 회전 횟수 (방향 전환 비용 계산용)
///
public int RotationCount { get; set; } = 0;
///
/// 이 노드에 도달하기 위한 이동 명령 시퀀스
///
public List MovementSequence { get; set; } = new List();
///
/// 기본 생성자
///
public PathNode()
{
}
///
/// 매개변수 생성자
///
/// 노드 ID
/// AGV 방향
public PathNode(string nodeId, AgvDirection direction)
{
NodeId = nodeId;
Direction = direction;
}
///
/// 우선순위 큐를 위한 비교 (FCost 기준)
///
public int CompareTo(PathNode other)
{
if (other == null) return 1;
int compare = FCost.CompareTo(other.FCost);
if (compare == 0)
{
// FCost가 같으면 HCost가 낮은 것을 우선
compare = HCost.CompareTo(other.HCost);
}
if (compare == 0)
{
// 그것도 같으면 회전 횟수가 적은 것을 우선
compare = RotationCount.CompareTo(other.RotationCount);
}
return compare;
}
///
/// 노드 상태 복사
///
public PathNode Clone()
{
return new PathNode
{
NodeId = NodeId,
Direction = Direction,
GCost = GCost,
HCost = HCost,
Parent = Parent,
RotationCount = RotationCount,
MovementSequence = new List(MovementSequence)
};
}
///
/// 고유 키 생성 (노드ID + 방향)
///
public string GetKey()
{
return $"{NodeId}_{Direction}";
}
///
/// 문자열 표현
///
public override string ToString()
{
return $"{NodeId}({Direction}) F:{FCost:F1} G:{GCost:F1} H:{HCost:F1} R:{RotationCount}";
}
///
/// 해시코드 (딕셔너리 키용)
///
public override int GetHashCode()
{
return GetKey().GetHashCode();
}
///
/// 동등성 비교
///
public override bool Equals(object obj)
{
if (obj is PathNode other)
{
return NodeId == other.NodeId && Direction == other.Direction;
}
return false;
}
}
}