""" 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()