Skip to content

Commit 3169a03

Browse files
authored
Merge pull request #391 from DataScience-GT/fix/restore-bootcamp-curriculum
Restore the twelve-week bootcamp syllabus, and pin its shape
2 parents 26d900f + 2a4b97c commit 3169a03

3 files changed

Lines changed: 144 additions & 6 deletions

File tree

‎docs/operations/testing.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Tests use `src/test/create-mock-context.ts` and `.internal-tests/_db-tx-mock.ts`
4343

4444
## Mainweb
4545

46-
`sites/mainweb/lib/*.test.ts` — phone formatting, hackathon slugs, `safe-callback`.
46+
`sites/mainweb/lib/*.test.ts` — phone formatting, hackathon slugs, `safe-callback`, and the hand-edited syllabus constant (`bootcamp-schedule.test.ts` — unique, gapless week numbers and https notebook links).
4747

4848
## Hacklytics
4949

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { describe, it, expect } from "vitest";
2+
import {
3+
BOOTCAMP_CURRICULUM,
4+
BOOTCAMP_MEETING_TIME,
5+
BOOTCAMP_ROOM,
6+
BOOTCAMP_WORKSPACE_URL,
7+
weekEntry,
8+
} from "./bootcamp-schedule";
9+
10+
// A hand-edited constant published on a public page. Most of this is vacuous
11+
// while it is empty — these arm themselves the moment the real weeks are typed
12+
// in, which is the one moment nobody runs a test on purpose.
13+
14+
describe("BOOTCAMP_CURRICULUM", () => {
15+
it("numbers each week once", () => {
16+
const weeks = BOOTCAMP_CURRICULUM.map((entry) => entry.week);
17+
// A duplicate wins the `find` in weekEntry and drops the other week.
18+
expect(new Set(weeks).size).toBe(weeks.length);
19+
});
20+
21+
it("counts up", () => {
22+
const weeks = BOOTCAMP_CURRICULUM.map((entry) => entry.week);
23+
expect(weeks).toEqual([...weeks].sort((a, b) => a - b));
24+
});
25+
26+
it("starts at week 1 and leaves no gap", () => {
27+
// Sessions reference weeks by number; a gap renders with no title.
28+
BOOTCAMP_CURRICULUM.forEach((entry, index) => {
29+
expect(entry.week).toBe(index + 1);
30+
});
31+
});
32+
33+
it("gives every week something to render", () => {
34+
for (const entry of BOOTCAMP_CURRICULUM) {
35+
expect(entry.title.trim()).not.toBe("");
36+
expect(entry.desc.trim()).not.toBe("");
37+
}
38+
});
39+
40+
it("links notebooks over https, or not at all", () => {
41+
for (const entry of BOOTCAMP_CURRICULUM) {
42+
if (entry.deepnoteUrl === undefined) continue;
43+
expect(entry.deepnoteUrl).toMatch(/^https:\/\//);
44+
}
45+
});
46+
});
47+
48+
describe("the unset values", () => {
49+
it("are null rather than an empty string", () => {
50+
// Surfaces test for null; "" slips through as a blank room and a dead button.
51+
for (const value of [
52+
BOOTCAMP_ROOM,
53+
BOOTCAMP_MEETING_TIME,
54+
BOOTCAMP_WORKSPACE_URL,
55+
]) {
56+
expect(value === null || value.trim() !== "").toBe(true);
57+
}
58+
});
59+
60+
it("points the workspace button at https once it is set", () => {
61+
if (BOOTCAMP_WORKSPACE_URL === null) return;
62+
expect(BOOTCAMP_WORKSPACE_URL).toMatch(/^https:\/\//);
63+
});
64+
});
65+
66+
describe("weekEntry", () => {
67+
it("finds nothing for an event with no week on it", () => {
68+
expect(weekEntry(null)).toBeUndefined();
69+
});
70+
71+
it("finds nothing for a week the syllabus does not describe", () => {
72+
expect(weekEntry(999)).toBeUndefined();
73+
});
74+
75+
it("finds each week it does describe", () => {
76+
for (const entry of BOOTCAMP_CURRICULUM) {
77+
expect(weekEntry(entry.week)).toBe(entry);
78+
}
79+
});
80+
});

‎sites/mainweb/lib/bootcamp-schedule.ts‎

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,69 @@ export const BOOTCAMP_START_DATE: string | null = "September 22, 2026";
2929
/** The Deepnote workspace every session works out of. */
3030
export const BOOTCAMP_WORKSPACE_URL: string | null = null;
3131

32-
// Empty until the real syllabus is written. The twelve weeks that used to sit
33-
// here were placeholder copy, and a made-up curriculum on a public page is
34-
// worse than saying it is coming. Every surface renders "updating soon" while
35-
// this is empty.
36-
export const BOOTCAMP_CURRICULUM: BootcampWeek[] = [];
32+
// Restored from f515a3d9. Confirm the titles before the term starts.
33+
export const BOOTCAMP_CURRICULUM: BootcampWeek[] = [
34+
{
35+
week: 1,
36+
title: "Python Basics & Setup",
37+
desc: "Variables, data types, and environment configuration.",
38+
},
39+
{
40+
week: 2,
41+
title: "Control Flow & Structures",
42+
desc: "Loops, conditionals, lists, and dictionaries.",
43+
},
44+
{
45+
week: 3,
46+
title: "Functions & Modules",
47+
desc: "Writing reusable code and organizing projects.",
48+
},
49+
{
50+
week: 4,
51+
title: "Object-Oriented Programming",
52+
desc: "Classes, inheritance, and Pythonic design.",
53+
},
54+
{
55+
week: 5,
56+
title: "File Handling & APIs",
57+
desc: "Reading files, writing data, and making web requests.",
58+
},
59+
{
60+
week: 6,
61+
title: "Pandas & NumPy",
62+
desc: "Introduction to fast numerical computing and DataFrames.",
63+
},
64+
{
65+
week: 7,
66+
title: "Data Cleaning",
67+
desc: "Handling missing values, merging, and data transformations.",
68+
},
69+
{
70+
week: 8,
71+
title: "Exploratory Data Analysis",
72+
desc: "Extracting insights and statistical summaries from data.",
73+
},
74+
{
75+
week: 9,
76+
title: "Data Visualization",
77+
desc: "Creating stunning charts using Matplotlib and Seaborn.",
78+
},
79+
{
80+
week: 10,
81+
title: "Intro to Machine Learning",
82+
desc: "Core concepts, train/test splits, and Scikit-Learn.",
83+
},
84+
{
85+
week: 11,
86+
title: "Supervised Learning",
87+
desc: "Linear regression, logistic regression, and decision trees.",
88+
},
89+
{
90+
week: 12,
91+
title: "Capstone Project",
92+
desc: "Build an end-to-end data science portfolio piece.",
93+
},
94+
];
3795

3896
/** The curriculum entry a session's week number refers to, if there is one. */
3997
export const weekEntry = (week: number | null) =>

0 commit comments

Comments
 (0)