206 lines
6.2 KiB
Python
206 lines
6.2 KiB
Python
from pathlib import Path
|
|
from typing import Literal, Sequence
|
|
|
|
import fitz # type: ignore
|
|
|
|
|
|
def make_geometry_pdf(path: Path) -> Path:
|
|
"""Create the same non-empty geometry fixture used for the legacy golden."""
|
|
|
|
doc = fitz.open()
|
|
page = doc.new_page(width=792, height=612)
|
|
page.draw_rect(page.rect, color=(1, 1, 1), fill=(1, 1, 1), width=0)
|
|
page.draw_rect(
|
|
fitz.Rect(0, 0, 96, 48),
|
|
color=(1, 0, 0),
|
|
fill=(1, 0, 0),
|
|
width=0,
|
|
)
|
|
page.draw_rect(
|
|
fitz.Rect(696, 564, 792, 612),
|
|
color=(0, 0, 1),
|
|
fill=(0, 0, 1),
|
|
width=0,
|
|
)
|
|
page.draw_line(
|
|
fitz.Point(0, 306),
|
|
fitz.Point(792, 306),
|
|
color=(0, 0, 0),
|
|
width=2,
|
|
)
|
|
page.insert_text(
|
|
(310, 320),
|
|
"GEOMETRY FIXTURE",
|
|
fontsize=20,
|
|
color=(0, 0, 0),
|
|
)
|
|
doc.save(path)
|
|
doc.close()
|
|
return path
|
|
|
|
|
|
def _make_subsplash_roster_pdf(
|
|
path: Path,
|
|
roster_type: Literal["main", "nursery_only"],
|
|
dates: Sequence[str],
|
|
) -> Path:
|
|
"""Create a realistic one-page, vector Subsplash-style roster fixture.
|
|
|
|
The fixture deliberately resembles the structure of ``input/original.pdf``:
|
|
dates run across the top, role headings and assignment labels run down the
|
|
left, and the cells contain volunteer names. It is not used by the legacy
|
|
geometry golden, so changes here cannot mask a single-roster regression.
|
|
"""
|
|
|
|
if not dates:
|
|
raise ValueError("at least one date is required")
|
|
|
|
document = fitz.open()
|
|
page = document.new_page(width=792, height=612)
|
|
page.draw_rect(page.rect, color=None, fill=(1, 1, 1), width=0)
|
|
|
|
if roster_type == "main":
|
|
table = fitz.Rect(34, 48, 758, 446)
|
|
roles = (
|
|
("MEDIA", "Sound", "Alex Morgan"),
|
|
("NURSERY", "Nursery Workers", "Jamie Rivera"),
|
|
("LITTLE WADERS", "Teacher", "Taylor Brooks"),
|
|
("RIVER KID", "Teacher", "Jordan Lee"),
|
|
("GREETERS", "Greet", "Morgan Reed"),
|
|
("USHERS", "Usher", "Casey Miller"),
|
|
("OFFERING MESSAGE", "Speaker", "Riley Davis"),
|
|
("PRAYER", "Prayer", "Avery Wilson"),
|
|
)
|
|
else:
|
|
# Mirrors the compact real nursery strip: roughly 36 points of date
|
|
# header plus about 66 points for the band and worker row.
|
|
table = fitz.Rect(14, 188, 778, 290)
|
|
roles = (("NURSERY WORKERS", "Nursery Workers", "Jamie Rivera"),)
|
|
|
|
first_column_width = 154
|
|
header_height = 42 if roster_type == "main" else 36
|
|
date_width = (table.width - first_column_width) / len(dates)
|
|
role_height = (table.height - header_height) / len(roles)
|
|
navy = (0.06, 0.18, 0.25)
|
|
pale_blue = (0.90, 0.95, 0.97)
|
|
grid = (0.36, 0.43, 0.47)
|
|
|
|
page.draw_rect(table, color=grid, fill=(1, 1, 1), width=0.8)
|
|
page.draw_rect(
|
|
fitz.Rect(table.x0, table.y0, table.x1, table.y0 + header_height),
|
|
color=grid,
|
|
fill=navy,
|
|
width=0.8,
|
|
)
|
|
page.insert_text(
|
|
(table.x0 + 8, table.y0 + 26),
|
|
"SERVING SCHEDULE",
|
|
fontname="helv",
|
|
fontsize=10,
|
|
color=(1, 1, 1),
|
|
)
|
|
|
|
first_date_x = table.x0 + first_column_width
|
|
page.draw_line(
|
|
fitz.Point(first_date_x, table.y0),
|
|
fitz.Point(first_date_x, table.y1),
|
|
color=grid,
|
|
width=0.8,
|
|
)
|
|
for index, date_label in enumerate(dates):
|
|
x = first_date_x + index * date_width
|
|
if index:
|
|
page.draw_line(
|
|
fitz.Point(x, table.y0),
|
|
fitz.Point(x, table.y1),
|
|
color=grid,
|
|
width=0.6,
|
|
)
|
|
page.insert_text(
|
|
(x + 8, table.y0 + 18),
|
|
date_label,
|
|
fontname="hebo",
|
|
fontsize=9,
|
|
color=(1, 1, 1),
|
|
)
|
|
page.insert_text(
|
|
(x + 8, table.y0 + 32),
|
|
"7:00pm" if date_label.lower().startswith(("wed", "thu")) else "10:00am",
|
|
fontname="helv",
|
|
fontsize=8,
|
|
color=(1, 1, 1),
|
|
)
|
|
|
|
for role_index, (heading, assignment, volunteer) in enumerate(roles):
|
|
y0 = table.y0 + header_height + role_index * role_height
|
|
y1 = y0 + role_height
|
|
if role_index:
|
|
page.draw_line(
|
|
fitz.Point(table.x0, y0),
|
|
fitz.Point(table.x1, y0),
|
|
color=grid,
|
|
width=0.6,
|
|
)
|
|
page.draw_rect(
|
|
fitz.Rect(table.x0, y0, first_date_x, y1),
|
|
color=None,
|
|
fill=pale_blue,
|
|
width=0,
|
|
)
|
|
page.insert_text(
|
|
(table.x0 + 7, y0 + 15),
|
|
heading,
|
|
fontname="hebo",
|
|
fontsize=7.5,
|
|
color=navy,
|
|
)
|
|
page.insert_text(
|
|
(
|
|
table.x0 + 7,
|
|
min(y1 - 5, y0 + (31 if roster_type == "main" else 43)),
|
|
),
|
|
assignment,
|
|
fontname="helv",
|
|
fontsize=7.5,
|
|
color=(0.12, 0.12, 0.12),
|
|
)
|
|
for date_index in range(len(dates)):
|
|
x = first_date_x + date_index * date_width + 7
|
|
name = volunteer if date_index % 2 == 0 else f"{volunteer.split()[0]} Kim"
|
|
page.insert_text(
|
|
(
|
|
x,
|
|
y0
|
|
+ min(
|
|
27 if roster_type == "main" else 41,
|
|
role_height * 0.72,
|
|
),
|
|
),
|
|
name,
|
|
fontname="helv",
|
|
fontsize=7.5,
|
|
color=(0.08, 0.08, 0.08),
|
|
)
|
|
|
|
document.save(path)
|
|
document.close()
|
|
return path
|
|
|
|
|
|
def make_main_roster_pdf(
|
|
path: Path,
|
|
dates: Sequence[str] = ("Sun 6 Sep", "Sun 13 Sep", "Sun 20 Sep", "Sun 27 Sep"),
|
|
) -> Path:
|
|
"""Create a full roster with several broad ministry-role headings."""
|
|
|
|
return _make_subsplash_roster_pdf(path, "main", dates)
|
|
|
|
|
|
def make_nursery_only_roster_pdf(
|
|
path: Path,
|
|
dates: Sequence[str] = ("Wed 2 Sep", "Wed 9 Sep", "Wed 16 Sep", "Wed 23 Sep"),
|
|
) -> Path:
|
|
"""Create a roster whose only ministry role is Nursery Workers."""
|
|
|
|
return _make_subsplash_roster_pdf(path, "nursery_only", dates)
|