Files
3yearplan/templates/build_template.py
Joseph Doherty ebc76e9315 Seed UNS hierarchy across 6 sites; rebrand outputs to SCADA IT/OT with ZB template
Lands per-site UNS subtree files (Warsaw West/North, Shannon, Galway, TMT,
Ponce) seeded from OpenText facility docs — Warsaw split confirmed as
numbered = legacy Zimmer = West, lettered = legacy Biomet = North. Renames
project framing from "Shopfloor IT/OT" to "SCADA IT/OT" for accuracy.
Extracts a ZB-branded PowerPoint template from example_powerpoint.pptx and
wires it into the outputs pipeline. Trims deck from 18 to 16 slides
(BOBJ->Power BI transferred to another team, Non-Goals and Asks dropped);
goal-state BOBJ analysis pruned to a stub.
2026-04-30 10:54:49 -04:00

134 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Build the Zimmer Biomet PowerPoint template from extracted assets.
Reads `assets/cover-background.jpeg` and `assets/bottom-border.jpg`,
emits `zb-template.pptx` with two slides demonstrating the cover and
content layouts. Re-run this script whenever assets change.
"""
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
import os
HERE = os.path.dirname(os.path.abspath(__file__))
ASSET = os.path.join(HERE, "assets")
OUT = os.path.join(HERE, "zb-template.pptx")
# Slide-size constants in EMU (English Metric Units; 914400 EMU = 1 inch)
SLIDE_W = Inches(13.33)
SLIDE_H = Inches(7.5)
# Brand colors from the example deck's slideLayout22 / slideLayout33 XML
COVER_TITLE_COLOR = RGBColor(0xF4, 0xF4, 0xF4) # near-white for cover title over dark bg
CONTENT_TITLE_COLOR = RGBColor(0x00, 0x66, 0xB3) # Zimmer blue
SLIDE_NUMBER_COLOR = RGBColor(0x2B, 0x2A, 0x80) # dark navy/purple
CONFIDENTIAL_COLOR = RGBColor(0x40, 0x40, 0x40) # dark gray on the white margin above the border
CONFIDENTIAL_TEXT = "CONFIDENTIAL FOR ZIMMER BIOMET INTERNAL USE ONLY"
def add_textbox(slide, left, top, width, height, text, *, font_size=12,
color=None, bold=False, align=None, font_name="Arial"):
tx = slide.shapes.add_textbox(left, top, width, height)
tf = tx.text_frame
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
if align is not None:
p.alignment = align
r = p.add_run()
r.text = text
r.font.name = font_name
r.font.size = Pt(font_size)
r.font.bold = bold
if color is not None:
r.font.color.rgb = color
return tx
def build_cover(slide):
"""Cover slide: full-bleed background image + title in upper-left, white text."""
slide.shapes.add_picture(
os.path.join(ASSET, "cover-background.jpeg"),
left=0, top=0, width=SLIDE_W, height=SLIDE_H,
)
add_textbox(
slide,
left=Inches(0.92), top=Inches(1.38),
width=Inches(6.0), height=Inches(1.89),
text="Deck Title",
font_size=28, bold=True, color=COVER_TITLE_COLOR,
)
add_textbox(
slide,
left=Inches(0.92), top=Inches(3.30),
width=Inches(6.0), height=Inches(0.5),
text="Subtitle / date / author",
font_size=14, color=COVER_TITLE_COLOR,
)
def build_content(slide, *, title="Section title", page_number="2"):
"""Content slide: title at top, content area, bottom border + slide number + confidentiality text."""
add_textbox(
slide,
left=Inches(0.92), top=Inches(0.40),
width=Inches(11.5), height=Inches(0.85),
text=title,
font_size=28, bold=True, color=CONTENT_TITLE_COLOR,
)
placeholder = add_textbox(
slide,
left=Inches(0.92), top=Inches(1.50),
width=Inches(11.5), height=Inches(4.80),
text=("Body content goes here.\n"
"• Bullet one\n"
"• Bullet two\n"
"• Bullet three"),
font_size=18, color=RGBColor(0x33, 0x33, 0x33),
)
placeholder.text_frame.word_wrap = True
slide.shapes.add_picture(
os.path.join(ASSET, "bottom-border.jpg"),
left=Inches(0.01), top=Inches(6.76),
width=Inches(13.32), height=Inches(0.74),
)
add_textbox(
slide,
left=Inches(0.29), top=Inches(6.55),
width=Inches(8.0), height=Inches(0.20),
text=CONFIDENTIAL_TEXT,
font_size=8, color=CONFIDENTIAL_COLOR,
)
add_textbox(
slide,
left=Inches(12.85), top=Inches(6.55),
width=Inches(0.40), height=Inches(0.20),
text=page_number,
font_size=10, color=SLIDE_NUMBER_COLOR, align=PP_ALIGN.RIGHT,
)
def main():
prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H
blank = prs.slide_layouts[6]
cover = prs.slides.add_slide(blank)
build_cover(cover)
content = prs.slides.add_slide(blank)
build_content(content, title="Content slide example", page_number="2")
second_content = prs.slides.add_slide(blank)
build_content(second_content, title="Another content slide", page_number="3")
prs.save(OUT)
print(f"Wrote {OUT}")
if __name__ == "__main__":
main()