249 lines
7.7 KiB
Python
249 lines
7.7 KiB
Python
"""
|
|
Tests for path utilities — walk interpolation.
|
|
"""
|
|
|
|
import unittest
|
|
import sys
|
|
import os
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from src.engine.types import Position
|
|
from src.engine.path_utils import WalkPath, WalkState, WalkManager, PathSegment
|
|
|
|
|
|
class TestPathSegment(unittest.TestCase):
|
|
"""Tests for PathSegment."""
|
|
|
|
def test_interpolate_start(self):
|
|
segment = PathSegment(
|
|
start=Position(x=0, y=0),
|
|
end=Position(x=100, y=0),
|
|
distance=100,
|
|
cumulative_distance=100
|
|
)
|
|
pos = segment.interpolate(0.0)
|
|
self.assertEqual(pos.x, 0)
|
|
self.assertEqual(pos.y, 0)
|
|
|
|
def test_interpolate_end(self):
|
|
segment = PathSegment(
|
|
start=Position(x=0, y=0),
|
|
end=Position(x=100, y=0),
|
|
distance=100,
|
|
cumulative_distance=100
|
|
)
|
|
pos = segment.interpolate(1.0)
|
|
self.assertEqual(pos.x, 100)
|
|
self.assertEqual(pos.y, 0)
|
|
|
|
def test_interpolate_middle(self):
|
|
segment = PathSegment(
|
|
start=Position(x=0, y=0),
|
|
end=Position(x=100, y=0),
|
|
distance=100,
|
|
cumulative_distance=100
|
|
)
|
|
pos = segment.interpolate(0.5)
|
|
self.assertAlmostEqual(pos.x, 50)
|
|
self.assertAlmostEqual(pos.y, 0)
|
|
|
|
|
|
class TestWalkPath(unittest.TestCase):
|
|
"""Tests for WalkPath."""
|
|
|
|
def test_straight_line_distance(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
self.assertAlmostEqual(path.total_distance, 100.0)
|
|
|
|
def test_multi_segment_distance(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0),
|
|
Position(x=100, y=100)
|
|
])
|
|
self.assertAlmostEqual(path.total_distance, 200.0)
|
|
|
|
def test_position_at_distance_start(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
pos = path.position_at_distance(0)
|
|
self.assertEqual(pos.x, 0)
|
|
|
|
def test_position_at_distance_end(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
pos = path.position_at_distance(100)
|
|
self.assertEqual(pos.x, 100)
|
|
|
|
def test_position_at_distance_middle(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
pos = path.position_at_distance(50)
|
|
self.assertAlmostEqual(pos.x, 50)
|
|
|
|
def test_position_at_distance_multi_segment(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0),
|
|
Position(x=100, y=100)
|
|
])
|
|
# At 150 pixels: first 100 to (100,0), then 50 down
|
|
pos = path.position_at_distance(150)
|
|
self.assertAlmostEqual(pos.x, 100)
|
|
self.assertAlmostEqual(pos.y, 50)
|
|
|
|
def test_position_at_time(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
# Speed 50 px/sec, after 1 sec = 50 px traveled
|
|
pos = path.position_at_time(elapsed=1.0, speed=50.0)
|
|
self.assertAlmostEqual(pos.x, 50)
|
|
|
|
def test_time_to_complete(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
# 100 pixels at 50 px/sec = 2 seconds
|
|
self.assertAlmostEqual(path.time_to_complete(50.0), 2.0)
|
|
|
|
def test_is_complete(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
self.assertFalse(path.is_complete(elapsed=1.0, speed=50.0))
|
|
self.assertTrue(path.is_complete(elapsed=3.0, speed=50.0))
|
|
|
|
def test_progress(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
self.assertAlmostEqual(path.progress(elapsed=1.0, speed=50.0), 0.5)
|
|
self.assertAlmostEqual(path.progress(elapsed=2.0, speed=50.0), 1.0)
|
|
|
|
def test_direct_path(self):
|
|
path = WalkPath.direct(Position(x=0, y=0), Position(x=100, y=100))
|
|
self.assertAlmostEqual(path.total_distance, 141.42, places=1)
|
|
|
|
|
|
class TestWalkState(unittest.TestCase):
|
|
"""Tests for WalkState."""
|
|
|
|
def test_current_position(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
state = WalkState(
|
|
player_id="p1",
|
|
path=path,
|
|
start_time=10.0,
|
|
speed=50.0
|
|
)
|
|
# At time 11.0 (1 sec elapsed), should be at x=50
|
|
pos = state.current_position(11.0)
|
|
self.assertAlmostEqual(pos.x, 50)
|
|
|
|
def test_is_complete(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
state = WalkState(
|
|
player_id="p1",
|
|
path=path,
|
|
start_time=10.0,
|
|
speed=50.0
|
|
)
|
|
self.assertFalse(state.is_complete(11.0))
|
|
self.assertTrue(state.is_complete(13.0))
|
|
|
|
def test_arrival_time(self):
|
|
path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
state = WalkState(
|
|
player_id="p1",
|
|
path=path,
|
|
start_time=10.0,
|
|
speed=50.0
|
|
)
|
|
self.assertAlmostEqual(state.arrival_time(), 12.0)
|
|
|
|
|
|
class TestWalkManager(unittest.TestCase):
|
|
"""Tests for WalkManager."""
|
|
|
|
def setUp(self):
|
|
self.manager = WalkManager()
|
|
self.path = WalkPath(waypoints=[
|
|
Position(x=0, y=0),
|
|
Position(x=100, y=0)
|
|
])
|
|
|
|
def test_start_walk(self):
|
|
state = self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
self.assertEqual(state.player_id, "p1")
|
|
self.assertIsNotNone(self.manager.get_walk_state("p1"))
|
|
|
|
def test_get_position(self):
|
|
self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
pos = self.manager.get_position("p1", 1.0)
|
|
self.assertIsNotNone(pos)
|
|
self.assertAlmostEqual(pos.x, 50)
|
|
|
|
def test_get_position_no_walk(self):
|
|
pos = self.manager.get_position("nonexistent", 1.0)
|
|
self.assertIsNone(pos)
|
|
|
|
def test_is_walking(self):
|
|
self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
self.assertTrue(self.manager.is_walking("p1", 1.0))
|
|
self.assertFalse(self.manager.is_walking("p1", 3.0))
|
|
|
|
def test_cancel_walk(self):
|
|
self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
self.manager.cancel_walk("p1")
|
|
self.assertIsNone(self.manager.get_walk_state("p1"))
|
|
|
|
def test_cleanup_completed(self):
|
|
self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
self.manager.start_walk("p2", self.path, 0.0, 100.0)
|
|
|
|
# p2 finishes at t=1, p1 at t=2
|
|
completed = self.manager.cleanup_completed(1.5)
|
|
|
|
self.assertEqual(len(completed), 1)
|
|
self.assertEqual(completed[0].player_id, "p2")
|
|
self.assertIsNone(self.manager.get_walk_state("p2"))
|
|
self.assertIsNotNone(self.manager.get_walk_state("p1"))
|
|
|
|
def test_get_all_positions(self):
|
|
self.manager.start_walk("p1", self.path, 0.0, 50.0)
|
|
self.manager.start_walk("p2", self.path, 0.0, 100.0)
|
|
|
|
positions = self.manager.get_all_positions(1.0)
|
|
|
|
self.assertEqual(len(positions), 2)
|
|
self.assertAlmostEqual(positions["p1"].x, 50)
|
|
self.assertAlmostEqual(positions["p2"].x, 100)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|