Setting up a course
This walks through a full term, start to finish: get your problems in, define the course, load it, check it, and manage it while it runs. For the exact options on any command, see the command reference.
Two places CS30 keeps things
It helps to know this up front, because it explains which command affects what:
- The database holds the course structure — sections, labs, which problems belong to which lab, who’s enrolled, and the TA. Commands like
addcourse,addstudent, andcancellabchange the database. - The problem pool is a git repository of the actual problem content (statement, test data). Commands like
addproblemandremoveproblemchange the pool, not the database.
A course in the database points at problems by name. The name must match a folder in the problem pool. That’s the one thing to keep straight: the pool has the problems, the course just references them by name.
Step 1 — Prepare your problems
Each problem is a folder in the standard ICPC/Kattis format (“problemtools”). At minimum:
babyshark/
problem.yaml # problem config (name, time limit, etc.)
data/
sample/ # sample cases students can see: 1.in, 1.ans, ...
secret/ # hidden cases used for grading
submissions/
accepted/ # at least one correct reference solution
The folder name (babyshark) becomes the problem name you’ll reference everywhere.
Step 2 — Add problems to the pool
Adding a problem renders its statement to HTML (this is the step that needs Docker) and commits it to the problem git repo.
One problem at a time:
java -jar cs30-1.0-SNAPSHOT.jar addproblem \
--problem-dir=./problems/babyshark \
--git-repo=/path/to/problems
A whole folder of problems at once (each subfolder is one problem):
java -jar cs30-1.0-SNAPSHOT.jar addproblems \
--problems-dir=./problems \
--git-repo=/path/to/problems
--git-repo is the problem pool path — the same path you’ll put in the course file as problemGitRepo.
Step 3 — Write the course file
A course is one YAML file. Here’s a complete example:
code: CS30
year: 2026
semester: Summer
startDate: "2026-07-01"
endDate: "2026-07-31"
studentGitRepo: /path/to/students
problemGitRepo: /path/to/problems
language: Python # default language for problems that don't set one
sections:
- number: 1
ta: ta.section1@sjsu.edu # optional
labs:
- number: 1
startDateTime: "2026-07-03T10:00:00"
endDateTime: "2026-07-03T11:15:00"
problems:
- name: "babyshark"
- name: "tenkindsofpeople"
language: Java # optional, overrides the course default
note: "Extra credit" # optional
students:
- jane.smith@sjsu.edu
- john.doe@sjsu.edu
What the fields mean:
code,year,semester— together these identify the course. You’ll pass them to most other commands.startDate,endDate—yyyy-MM-dd.studentGitRepo,problemGitRepo— filesystem paths to the two git repos. Optional, but you’ll almost always set them. If set, the tool initializes the repos and drops a copy of the course file into the student repo.language— the default problem language. A problem with nolanguageof its own uses this.sections[]— each has anumber, an optionalta, a list oflabs, and a list ofstudents(emails).labs[]— each has anumber, astartDateTimeandendDateTime(yyyy-MM-ddTHH:mm:ss), and a list ofproblems.problems[]— each has aname(must match a folder in the problem pool), and optionallanguageandnote.
A ready-to-copy template is in the repo at templates/courseTemplate.yml.
Step 4 — Load the course
java -jar cs30-1.0-SNAPSHOT.jar addcourse --course-file=./course.yaml
This creates every section, lab, problem, and enrollment from the file. It’s safe to re-run: a section that already exists (same code, year, semester, section) is updated rather than duplicated, so you can edit the file and load it again.
Step 5 — Check it before the lab
Confirm every problem your course references actually exists in the pool:
java -jar cs30-1.0-SNAPSHOT.jar validatecourse \
--course-code=CS30 --year=2026 --semester=Summer --section=all
It prints a ✓ or ✗ per problem and lists anything missing. Do this before a lab opens — a missing problem means students can’t open it.
You can also see what got loaded:
java -jar cs30-1.0-SNAPSHOT.jar findcourse \
--course-code=CS30 --year=2026 --semester=Summer --section=all
Managing the course while it runs
Add a student who enrolled late:
java -jar cs30-1.0-SNAPSHOT.jar addstudent \
--course-code=CS30 --year=2026 --semester=Summer --section=1 --email=late@sjsu.edu
Remove a student: same options with removestudent.
Find which sections a student is in:
java -jar cs30-1.0-SNAPSHOT.jar findstudent --email=jane.smith@sjsu.edu
Set or change a section’s TA:
java -jar cs30-1.0-SNAPSHOT.jar setta \
--course-code=CS30 --year=2026 --semester=Summer --section=1 --email=ta@sjsu.edu
Add another lab later — write a small lab file (templates/labTemplate.yml is the template) and load it:
java -jar cs30-1.0-SNAPSHOT.jar addlab --lab-file=./lab.yml
Extend the course end date (one section or all):
java -jar cs30-1.0-SNAPSHOT.jar changeenddate \
--course-code=CS30 --year=2026 --semester=Summer --section=all --end-date=2026-08-15
Cancel a lab (removes the lab and its problems from the course; the problem pool is untouched):
java -jar cs30-1.0-SNAPSHOT.jar cancellab \
--course-code=CS30 --year=2026 --semester=Summer --section=1 --lab=4
Fix a problem’s language in one lab (database only — doesn’t change the pool):
java -jar cs30-1.0-SNAPSHOT.jar updateproblemlanguage \
--course-code=CS30 --year=2026 --semester=Summer --section=1 --lab=1 \
--problem-name=babyshark --language=java
Full details and every option are in the command reference.