"""Small regression tests for the dependency-free PDF generator.""" import math import random import tempfile import unittest from pathlib import Path from golf_course_generator import ( A4_HEIGHT, A4_WIDTH, CARD_HEIGHT, CARD_WIDTH, GRID_COLUMNS, GRID_ROWS, GRID_SPACING, GRID_X_OFFSET, GRID_Y_OFFSET, MIN_TEE_TO_CUP_DISTANCE, Rect, _natural_area_boundary_loops, _natural_shape, _rectangles_intersect, _start_and_finish_fairways, _tree_group_points, build_a4_pdf, build_a4_sheet, write_sheet, ) class GolfCourseGeneratorTests(unittest.TestCase): def test_sheet_is_a_nonempty_single_page_pdf(self) -> None: document = build_a4_sheet(seed=123456) self.assertTrue(document.startswith(b"%PDF-1.4")) self.assertIn(f"/MediaBox [0 0 {A4_WIDTH:.3f} {A4_HEIGHT:.3f}]".encode(), document) self.assertIn(b"/Count 1", document) self.assertIn(b"/BaseFont /Courier", document) self.assertGreater(len(document), 25_000) def test_seed_makes_output_repeatable(self) -> None: self.assertEqual(build_a4_sheet(4321), build_a4_sheet(4321)) self.assertNotEqual(build_a4_sheet(4321), build_a4_sheet(4322)) def test_36_courses_are_packed_into_nine_pages(self) -> None: document = build_a4_pdf(course_count=36, seed=36) self.assertIn(b"/Count 9", document) self.assertEqual(document.count(b"/Type /Page /Parent"), 9) self.assertIn(b"(Hole 36)", document) def test_rejects_a_non_positive_course_count(self) -> None: with self.assertRaises(ValueError): build_a4_pdf(course_count=0) def test_tee_and_cup_are_separated_fairway_grid_dots(self) -> None: board = Rect(0, 0, GRID_COLUMNS * GRID_SPACING, GRID_ROWS * GRID_SPACING) tee_fairway, tee, cup_fairway, cup = _start_and_finish_fairways(random.Random(52), board) self.assertGreaterEqual(math.dist(tee, cup), MIN_TEE_TO_CUP_DISTANCE) for point, fairway in ((tee, tee_fairway), (cup, cup_fairway)): x_index = (point[0] - (board.x + GRID_X_OFFSET)) / GRID_SPACING y_index = (point[1] - (board.y + GRID_Y_OFFSET)) / GRID_SPACING self.assertAlmostEqual(x_index, round(x_index), places=8) self.assertAlmostEqual(y_index, round(y_index), places=8) self.assertTrue(any(part.x < point[0] < part.right and part.y < point[1] < part.top for part in fairway)) def test_course_cards_and_playfields_have_the_requested_dimensions(self) -> None: self.assertEqual(CARD_WIDTH, 3 * 72) self.assertEqual(CARD_HEIGHT, 5 * 72) self.assertEqual((GRID_COLUMNS, GRID_ROWS), (16, 26)) def test_tree_groups_and_terrain_do_not_overlap(self) -> None: board = Rect(0, 0, GRID_COLUMNS * GRID_SPACING, GRID_ROWS * GRID_SPACING) rng = random.Random(19) first = _natural_shape(rng, board, cell_count=14, avoid=[], blocked=[]) second = _natural_shape(rng, board, cell_count=8, avoid=[], blocked=first) terrain = [*first, *second] for cell in first[1:]: self.assertTrue( any(abs(cell.x - earlier.x) + abs(cell.y - earlier.y) == GRID_SPACING for earlier in first) ) self.assertTrue(all(not _rectangles_intersect(part, blocked) for part in second for blocked in first)) for x, y, _ in _tree_group_points(rng, board, terrain=terrain, avoid=[]): self.assertAlmostEqual((x - (board.x + GRID_X_OFFSET)) / GRID_SPACING, round((x - (board.x + GRID_X_OFFSET)) / GRID_SPACING), places=8) self.assertAlmostEqual((y - (board.y + GRID_Y_OFFSET)) / GRID_SPACING, round((y - (board.y + GRID_Y_OFFSET)) / GRID_SPACING), places=8) self.assertTrue(all(math.dist((x, y + 10), (max(feature.x, min(x, feature.right)), max(feature.y, min(y + 10, feature.top)))) >= 13 for feature in terrain)) def test_connected_terrain_has_one_continuous_boundary_loop(self) -> None: cells = [Rect(0, 0, GRID_SPACING, GRID_SPACING), Rect(GRID_SPACING, 0, GRID_SPACING, GRID_SPACING)] loops = _natural_area_boundary_loops(cells) self.assertEqual(len(loops), 1) self.assertEqual(len(loops[0]), 6) self.assertEqual(loops[0][0][0], loops[0][-1][1]) def test_sheet_includes_each_hole_label_and_can_be_written(self) -> None: with tempfile.TemporaryDirectory() as directory: destination = write_sheet(Path(directory) / "courses.pdf", seed=9) document = destination.read_bytes() for number in range(1, 5): self.assertIn(f"Hole {number}".encode(), document) self.assertIn(b"Strokes:", document) if __name__ == "__main__": unittest.main()