Coverage for src/countdown/digits.py: 100%
37 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 17:56 -0800
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 17:56 -0800
1"""Utilities for generating large digits."""
3from importlib.resources import files
4from itertools import zip_longest
6DIGIT_SIZES = []
7CHARS_BY_SIZE = {}
10def paragraphs(lines):
11 """Return groups of non-blank lines."""
12 group = []
13 for line in lines:
14 if line.strip():
15 group.append(line)
16 elif group:
17 yield group
18 group = []
19 yield group
22def transpose(lines):
23 """Transpose a list of strings (columns become rows)."""
24 return ("".join(column) for column in zip_longest(*lines, fillvalue=" "))
27def center(text, width):
28 """Center text so that each line will have the given width."""
29 return "\n".join(f"{line:^{width}}" for line in text.splitlines())
32def populate_constants():
33 """Populate CHARS_BY_SIZE and DIGIT_SIZES to contain the numbers in numbers.txt."""
34 lines = files("countdown").joinpath("numbers.txt").read_text().splitlines()
35 number_types = list(paragraphs(lines))
36 for group in number_types:
37 columns = transpose(group)
38 numbers = ["\n".join(transpose(p)) for p in paragraphs(columns)]
39 print("group")
40 heights = [len(n.splitlines()) for n in numbers]
41 widths = [max(len(line) for line in n.splitlines()) for n in numbers]
42 max_width = max(widths)
43 [height] = set(heights)
44 DIGIT_SIZES.append(height)
45 chars = CHARS_BY_SIZE[height] = {}
46 for digit, text in enumerate(numbers, start=-1):
47 if digit == -1:
48 colon_width = max(len(line) for line in text.splitlines())
49 chars[":"] = (
50 center(text, colon_width + 2) # 2 spaces around :
51 if len(text) > 1
52 else text
53 )
54 else:
55 chars[str(digit)] = center(text, max_width)
56 DIGIT_SIZES.sort(reverse=True)
59populate_constants()