Commit 41de8043 authored by Vacaliuc, Bogdan's avatar Vacaliuc, Bogdan
Browse files

slides: PPTX builder + packaged deck



gen_pptx.py assembles every live slide PNG into a single 16:9
PowerPoint (13.333 x 7.5 inches) at slides/Hack-A-Thon-Scientist-
Assessment.pptx.  Each slide has its title + a pointer to the
companion .md as speaker notes.

13 slides, 3.5 MB.  Order matches the README's live-deck table.

Build: /tmp/slides-venv/bin/python gen_pptx.py.
Idempotent — overwrites the .pptx every run.

Co-Authored-By: default avatarClaude Opus 4.7 (1M context) <noreply@anthropic.com>
parent 6ef7f4ad
Loading
Loading
Loading
Loading
+3.46 MiB

File added.

No diff preview for this file type.

+81 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
"""Assemble every live slide PNG into a single .pptx file.

Run inside `/tmp/slides-venv`:

    /tmp/slides-venv/bin/python gen_pptx.py

Writes `Hack-A-Thon-Scientist-Assessment.pptx` next to this script.
The script is idempotent — it overwrites the pptx every time.

The order comes from the live deck listed in README.md.  Archived
slides (archive/) are not included.
"""
from __future__ import annotations

from pathlib import Path

from pptx import Presentation
from pptx.util import Emu, Inches

HERE = Path(__file__).parent

# Order is deliberate; matches the README reading order.
DECK = [
    ("slide-0-opening.png",                     "Opening — Battle of the Robots"),
    ("slide-1-current-vs-ideal.png",            "From Today's Coupling to a Modular Back-End"),
    ("slide-2-api-mapping.png",                 "Functional API Mapping — mr_reduction ↔ lr_reduction"),
    ("slide-3-silent-defaults.png",             "Five Silent Default Disagreements"),
    ("slide-3a-errorweighted-background.png",   "ErrorWeightedBackground — detail"),
    ("slide-3b-crop-first-and-last-points.png", "CropFirstAndLastPoints — detail"),
    ("slide-3c-round-up-pixel.png",             "RoundUpPixel — detail"),
    ("slide-3d-accept-null-reflectivity.png",   "AcceptNullReflectivity — detail"),
    ("slide-3e-use-sangle.png",                 "UseSANGLE — detail"),
    ("slide-4-curves-disagree.png",             "What Scientists See Today — Real Reductions"),
    ("slide-5-peak-drag-sequence.png",          "A Peak Drag, Traced from Click to Plot"),
    ("slide-5a-debt-accumulation.png",          "Where the Debt Accumulates"),
    ("slide-end-closing.png",                   "End of Round One — Now for the Real Work"),
]

OUT_PPTX = HERE / "Hack-A-Thon-Scientist-Assessment.pptx"


def main():
    pres = Presentation()
    # 16:9 (standard for 1920x1080).  python-pptx default is 10 x 7.5 inches (4:3).
    pres.slide_width  = Inches(13.333)  # 1920 px @ 144 dpi = 13.333 in
    pres.slide_height = Inches(7.5)     # 1080 px @ 144 dpi = 7.5 in

    blank_layout = pres.slide_layouts[6]  # blank layout

    missing = []
    for fname, title in DECK:
        path = HERE / fname
        if not path.exists():
            missing.append(fname)
            continue
        slide = pres.slides.add_slide(blank_layout)
        slide.shapes.add_picture(
            str(path),
            left=Emu(0), top=Emu(0),
            width=pres.slide_width, height=pres.slide_height,
        )
        # Speaker notes: pull the title + optional companion .md
        notes_md = HERE / (fname.replace(".png", ".md"))
        notes_text = f"[{title}]"
        if notes_md.exists():
            notes_text += "\n\nSee companion: " + notes_md.name
        slide.notes_slide.notes_text_frame.text = notes_text

    if missing:
        print("WARNING: missing PNGs (not added to deck):")
        for m in missing:
            print(f"  - {m}")

    pres.save(str(OUT_PPTX))
    size_kb = OUT_PPTX.stat().st_size // 1024
    print(f"wrote {OUT_PPTX}  ({size_kb} KB, {len(pres.slides)} slides)")


if __name__ == "__main__":
    main()