File size: 7,990 Bytes
22de727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""Generate seed media/PDF assets for the simulated file explorer (src/miniweb/filesystem/).

- A real, rendered Resume PDF (reportlab).
- Real, audible MP3s (Music/) and real, playable VP9/WebM clips (Movies/).

Dev-only asset generation (the app just serves the committed files at runtime).
Deps: pip install reportlab pillow numpy imageio imageio-ffmpeg
Re-runnable; safe to re-run. Run:
    ~/.conda/envs/miniweb/bin/python src/miniweb/scripts/gen_filesystem_assets.py
"""
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent / "filesystem"


# ── Resume PDF (real, rendered) ──────────────────────────────────────────────
def make_resume_pdf(path: Path):
    from reportlab.lib.pagesizes import LETTER
    from reportlab.lib.units import inch
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.enums import TA_CENTER
    from reportlab.lib import colors
    from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer,
                                    HRFlowable)

    styles = getSampleStyleSheet()
    name = ParagraphStyle("name", parent=styles["Title"], fontSize=22,
                          spaceAfter=2, textColor=colors.HexColor("#1a2b4a"))
    contact = ParagraphStyle("contact", parent=styles["Normal"], fontSize=9.5,
                             alignment=TA_CENTER, textColor=colors.HexColor("#555"))
    head = ParagraphStyle("head", parent=styles["Heading2"], fontSize=12,
                          spaceBefore=12, spaceAfter=4,
                          textColor=colors.HexColor("#2a6"))
    body = ParagraphStyle("body", parent=styles["Normal"], fontSize=10, leading=14)
    role = ParagraphStyle("role", parent=body, fontName="Helvetica-Bold", spaceBefore=6)

    doc = SimpleDocTemplate(str(path), pagesize=LETTER,
                            leftMargin=0.9 * inch, rightMargin=0.9 * inch,
                            topMargin=0.8 * inch, bottomMargin=0.8 * inch)
    E = []
    E.append(Paragraph("Jordan Avery", ParagraphStyle("n", parent=name, alignment=TA_CENTER)))
    E.append(Paragraph("Lakeport, WA  Β·  jordan.avery@lakemail.com  Β·  (555) 018-2245", contact))
    E.append(Spacer(1, 6))
    E.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor("#2a6")))

    E.append(Paragraph("Summary", head))
    E.append(Paragraph(
        "Product-minded software engineer with 6 years building web platforms and "
        "data tooling. Comfortable across the stack; happiest turning fuzzy problems "
        "into shipped, measurable features.", body))

    E.append(Paragraph("Experience", head))
    E.append(Paragraph("Senior Software Engineer β€” Meridian Systems (2022–present)", role))
    E.append(Paragraph("β€’ Led the checkout re-architecture that cut payment errors 38%.<br/>"
                       "β€’ Mentored 4 engineers; owned the internal design-system migration.", body))
    E.append(Paragraph("Software Engineer β€” Northlake Labs (2019–2022)", role))
    E.append(Paragraph("β€’ Built the analytics ingestion pipeline (2B events/day).<br/>"
                       "β€’ Cut p95 dashboard load from 4.1s to 900ms.", body))

    E.append(Paragraph("Education", head))
    E.append(Paragraph("B.S. Computer Science β€” Cascadia University, 2019", body))

    E.append(Paragraph("Skills", head))
    E.append(Paragraph("Python Β· TypeScript Β· SQL Β· Flask Β· React Β· Playwright Β· PostgreSQL", body))

    doc.build(E)
    print("wrote", path, f"({path.stat().st_size} B)")


# ── Real, audible MP3 (bundled ffmpeg + libmp3lame) ──────────────────────────
def make_mp3(path: Path, seconds=6, freq=220.0, wobble=0.0):
    import subprocess
    import imageio_ffmpeg
    ff = imageio_ffmpeg.get_ffmpeg_exe()
    # A soft sine (optionally vibrato'd) at low volume β€” real audio, not silence.
    src = f"sine=frequency={freq}:duration={seconds}"
    flt = "tremolo=f=5:d=0.3,volume=0.35" if wobble else "volume=0.35"
    subprocess.run([ff, "-y", "-f", "lavfi", "-i", src, "-af", flt,
                    "-c:a", "libmp3lame", "-b:a", "128k", str(path)],
                   check=True, capture_output=True)
    print("wrote", path, f"({path.stat().st_size} B)")


# ── Real, playable VP9/WebM video (themed animated frames via imageio) ───────
def _gradient(w, h, c1, c2):
    import numpy as np
    ys = np.linspace(0, 1, h)[:, None, None]
    g = (np.array(c1) * (1 - ys) + np.array(c2) * ys)   # (h,1,3)
    return np.repeat(g, w, axis=1).astype("uint8")       # (h,w,3)


def _video_frames(title, c1, c2, motif, n=30, w=320, h=240):
    import numpy as np
    from PIL import Image, ImageDraw, ImageFont
    try:
        font = ImageFont.load_default(size=24)
        small = ImageFont.load_default(size=13)
    except TypeError:                                    # older Pillow
        font = small = ImageFont.load_default()
    frames = []
    for i in range(n):
        t = i / (n - 1)
        img = Image.fromarray(_gradient(w, h, c1, c2))
        d = ImageDraw.Draw(img, "RGBA")
        if motif == "sun":
            d.ellipse([w - 90, 24 + int(t * 120), w - 30, 84 + int(t * 120)], fill=(255, 236, 150))
        elif motif == "mountains":
            d.polygon([(0, h), (110, 120), (200, h)], fill=(0, 0, 0, 60))
            d.polygon([(120, h), (230, 90), (w, h)], fill=(0, 0, 0, 90))
        elif motif == "buildings":
            for bx, bh in [(30, 120), (80, 80), (140, 150), (210, 100), (270, 130)]:
                d.rectangle([bx, h - bh, bx + 36, h], fill=(0, 0, 0, 90))
        elif motif == "confetti":
            rng = np.random.RandomState(7)
            for _ in range(40):
                cx = int(rng.rand() * w); cy = int((rng.rand() + t) % 1 * h)
                col = tuple(int(c) for c in rng.randint(120, 255, 3))
                d.ellipse([cx, cy, cx + 6, cy + 6], fill=col + (220,))
        # title with a translucent bar
        d.rectangle([0, h - 40, w, h], fill=(0, 0, 0, 110))
        d.text((12, h - 32), title, font=font, fill=(255, 255, 255))
        d.text((12, 10), "● REC  0:%02d" % int(t * 6), font=small, fill=(255, 90, 90))
        frames.append(np.asarray(img))
    return frames


def make_video(path: Path, title, c1, c2, motif):
    # VP9/WebM, not H.264/MP4: the open-source Chromium that browser agents run in
    # omits the proprietary H.264 codec, so an .mp4 won't decode there β€” WebM plays
    # in Chromium AND in every modern user browser.
    import imageio
    frames = _video_frames(title, c1, c2, motif)
    imageio.mimwrite(str(path), frames, fps=12, codec="libvpx-vp9",
                     macro_block_size=8, output_params=["-pix_fmt", "yuv420p", "-b:v", "400k"])
    print("wrote", path, f"({path.stat().st_size} B)")


if __name__ == "__main__":
    (ROOT / "Documents").mkdir(parents=True, exist_ok=True)
    (ROOT / "Music").mkdir(parents=True, exist_ok=True)
    (ROOT / "Movies").mkdir(parents=True, exist_ok=True)

    make_resume_pdf(ROOT / "Documents" / "Resume.pdf")

    for name, secs, freq, wob in [("Summer Vibes.mp3", 7, 330, 1), ("Acoustic Morning.mp3", 6, 262, 0),
                                  ("Focus Flow.mp3", 8, 196, 0), ("Late Night Drive.mp3", 7, 147, 1),
                                  ("Coffee Shop Jazz.mp3", 6, 294, 1)]:
        make_mp3(ROOT / "Music" / name, secs, freq, wob)

    for name, c1, c2, motif in [
        ("Beach Sunset.webm", (255, 140, 60), (120, 40, 110), "sun"),
        ("Birthday Party.webm", (90, 40, 160), (230, 90, 150), "confetti"),
        ("Product Demo.webm", (30, 60, 120), (10, 20, 45), "plain"),
        ("City Timelapse.webm", (40, 55, 90), (10, 12, 28), "buildings"),
        ("Hiking Trip.webm", (120, 200, 120), (30, 90, 60), "mountains"),
    ]:
        make_video(ROOT / "Movies" / name, name[:-5], c1, c2, motif)