horrors from the depths of ucsd schedule of classes

programming ucsd school html5

For whatever reason, lately, I’ve been wasting hours of my life manually writing a 2600-line glorified DFA that takes over 2.5 seconds just to type check1, all just to parse the Schedule of Classes. The timing is because I’m expecting it to go offline within a few days as part of UCSD’s migration to SAP slop, but I’m also doing it because it’s a trove of course schedule data that goes back to Winter 1995.

What’s the scraped data going to be used for? I’m not sure. I’m thinking of making my classrooms website an archive for this data since the TSS migration will break my scraper. But again, it’s mainly just a waste of time.

A few decades ago, Schedule of Classes started out as a physical booklet that you’d have to buy from the bookstore each quarter—at least from what I can gather from the General Catalog2—and the first and only enrollment pass was done over the phone. This 1991 UCSD Guardian archive mentions that the system is called “T-REG,” which like WebReg was plagued with busy lines as students hunted for open sections with the phone menu. The booklets themselves allegedly contain more information about the old enrollment process, but it seems the UCSD Library hasn’t publicly archived them.

Interestingly, the 1991 Guardian article mentions ISIS. ISIS is the student database mainframe that is still in use today, at least until it gets replaced by TSS. It stores practically everything: course schedules and enrollment, grades, admissions. Its name is probably part of the reason why UCSD wanted to get rid of it, but it’s also almost 40 years old.

Owing to its age, ISIS has a pretty cool-looking retro interface. Here’s a screenshot from UCSD’s staff pages:

A terminal-looking interface with bright cyan and green text on a black background. Arrows point at various lines on the screen.

And here’s one of the screenshots they include when you request your admissions file. I assume this is what admissions officers see:

A terminal-looking interface with blue and bright green text on a black background. Some text is blacked out.

Just imagine what UCSD staff had to contend with the past 30-plus years.

Anyways, at a glance, you can tell ISIS’s UI makes it relatively easy for humans to make data entry errors. That’s why I made my scraper’s HTML parser a state machine, to see how complex course schedule data really is.

Quick background: What to expect

Fall 2021 CSE 11 course schedule, with three blocks: A0x, B0x, C0x. Each block has a lecture and several discussions and a final exam. All are full with waitlists.

Above is a screenshot of CSE 11 in Fall 2021 on the Schedule of Classes. After looking at several courses on the Schedule of Classes, one starts developing a mental model for its hierarchy.

At the top level are departments, and departments contain subjects. For CSE, they’re named the same, but a department like Linguistics might have multiple subjects, like LIGM for German and LISP for Spanish.

Subjects have courses, like CSE 11 and CSE 12. Courses have meetings, which can have a 6-digit section ID, a meeting type, section code (e.g. A01), days and time, building and room, instructors, and enrollment quantity and capacity.

But there’s also an intermediate structure between courses and meetings. I’m not really sure if there are names for this. “Section” seems to be an ambiguous term; I’ve heard it refer to a particular meeting (e.g. “discussion section”), or a group of students with the same professor (e.g. “section A00”).

In the CSE 11 example, you can see that meetings are grouped by letter. Within each letter, students can enroll in a discussion section (e.g. A01 to A04), and they only need to attend that discussion. This is also the group of students they see the grade distribution for in Academic History after the quarter ends. All students enrolled under the same letter attend the lecture for that letter (e.g. A01 students attend lecture A00), and they share the same exam times. The letters can go up to Z00.

Some courses (like seminars) instead use numbers, like 001, 002, and so on. These courses are usually just one meeting, and all students enrolled under that number attend it. I’m guessing this format is for courses that’re expected to have many seminars: the numbers can go up to 379.

With that out of the way, let’s get on to the quirks! Also, you might notice that many examples come from 2004–2006. That’s because I started running my parser from Summer 2004 to fix issues as they came up, so the first instances of any quirks I found came from then.

Exam scheduled three years later

MU 11/09/2009 M 4:00p-4:50p EBU3B 2109; CSE 290 F00 class meetings are cancelled on two dates, 10/31/06 and 11/06/06.

In Fall 2006, CSE 290 has a make-up session scheduled three years later, in 2009. Therefore, you cannot assume that all meetings for a course occur in the same year, much less the same term.

At least they got the day of the week correct: November 9, 2009 is indeed a Monday (November 9, 2006 is a Thursday).

The exam day can be wrong

LIIT 1BX: FI 03/21/1997 S 8:00a-10:59a APM 2301; FI 03/22/1997 S 8:00a-10:59a APM 2301

Winter 1997’s LIIT 1BX has two finals on Saturday, one on March 21, and another on March 22. Clearly, they can’t both be right (March 21 is on Friday), but this is surprising to me because I would’ve assumed the Schedule of Classes just calculates the day of an exam on the fly, rather than storing it as a separate, hand-edited column in its database.

Professor Error

ERTH 40 The Biosphere (4 Units); 567132 LE A00 MWF 1:00p-1:50p WLH 2111 Error, 243

Fall 2006’s ERTH 40 is taught by 243 Error.

Section code typos

As mentioned above, section codes usually look like A00 or 001. However, I’ve encountered a variety of section codes that don’t match this format. My guess is that these are typos, and ISIS doesn’t have any validation to prevent this.

Screenshot Section code Notes
IRGN 499 sections are sorted 022, 024, 025, 23 23 (trailing space) Spring 2006’s IRGN 499 has a trailing space in its section code. Without the leading zero, it gets lexicographically sorted out of order.
BISP 190 has a cancelled section A0 and regular section A00 A0 (trailing space) They must’ve realized they forgot a zero in Fall 2008’s BISP 190, so they cancelled it and recreated the section.
MED 296 has sections J00, K00, L00, M00, N00, OOO, POO, QOO, ROO OOO, POO, QOO, ROO Starting at O, Fall 2008’s MED 296 started using the letter O instead of zero, resulting in section codes like POO. This has happened several times to other courses.
NEU 296 has sections 00?, 010, 011 00? Spring 2019’s NEU 296 has a cancelled 00? section, which got sorted between 009 and 010.
Sections 10, 001, 002, 003 10 (leading space) The leading space in Fall 2014’s NANO 299’s section 10 places it before all other section codes.
Sections 001, 002, A00, 6, 7, 001, 002, 003, 004, 005, A01 6, 7 (leading space) Summer 2001’s PSYC 199 is, generally speaking, quite an oddball, but it also has sections 6 and 7 with two leading spaces, each with one student enrolled.
Section AA0, time and location TBA AA0 Winter 2002’s ANPR 195 did not cancel its AA0 section, but also didn’t make it enrollable.
Sections 035, 036, 037, 038, 039, 040, A00 (cancelled), AAA AAA Spring 2002’s BGGN 271 must’ve tried to switch from letter to number sections but in doing so accidentally created a screaming section code.
Section XXX, time and location TBA XXX Spring 2002’s COGS 190C, like AA0 above, was not cancelled, but also remained indefinitely unenrollable.
DSC 500 and 599 each have sections 0AC (cancelled) and A00 0AC Spring 2020’s DSC 500 and 599 accidentally created an 0AC section, cancelled it, and replaced it with A00. And they did this twice.
Sections :00 (cancelled), A00, B00 :00 Winter 2025’s COGS 190B has an accidental, cancelled :00 section code, which made it listed above all the normal sections.

Section IDs overflowed in 2020

CSE 299 with sections 999997 (001), 999998 (002), 1 (004), 2 (005)

Every course in the schedule of classes has a 6-digit section ID. My guess is that this originates from when course enrollment was performed over the telephone and students would dial the section ID on the keypad to select a section to enroll in.

Starting around Fall 2019 into 2020, sections started getting IDs with fewer than 6 digits. I initially thought this was malformed data entry, but it turned out that the section IDs overflowed in Winter 2020’s CSE 299, with its section 004 having ID 1. One must assume that section 003 was 999999, but they deleted it. Perhaps 999999 had traditionally been used and treated as a placeholder, so a real section with ID 999999 caused issues.

The overflow was mentioned in Angie Gozum’s post advocating for the replacement of ISIS:

As a basic example, the system is running out of numerals to create section identification numbers (section IDs). The system simply was not conceived to be running this long, and therefore the creators did not account for more than a million section IDs. Imagine what would happen if we did reach a point where we could not create any new section IDs. The university would not be able to function effectively because section IDs are at the center of many necessary operations, such as creating a class, course enrollments, student payments, faculty assignments, and more.

Interestingly, by 2026, section IDs have already reached 281474, even though Winter 1995 started with section ID 210365. My scraper did not detect any duplicate section IDs, so I wonder if they’re carefully reusing IDs from previously deleted sections, or if they started deleting old sections to reclaim their IDs.

javascript:openNewWindow('http://www.ucsd.edu/catalog/courses/EXCULDE.html#rmas199')

In a few cases, it seems scheduling staff must’ve tried to hide or delete the course catalog link (perhaps the course was too new for the catalog) by writing EXCLUDE in place of where the department name typically goes in course catalog URLs. This clearly didn’t work. Curiously, in every instance of this, they never spelled it correctly:

It’s possible that EXCLUDE is indeed the correct special keyword to use to indicate no course catalog link and make the software hide the link on the website, which could explain why only the misspellings show up on the website.

Meanwhile, Summer 2010’s HIEU 106GS links to SP18, which looks like the term code for Spring 2018. My hypothesis is that they meant to type the term code in a different field but accidentally typed it into the catalog URL slot, but it’s beyond me why anyone from 2010 would be thinking about 2018.

Mojibake

Some courses with variable topics will include the topic as a subtitle for the course. Perhaps because they were submitted directly by professors, they probably saw less oversight, and non-ASCII characters snuck through.

Who knows what text encoding ISIS uses—it might not even care, and just treats them all as C strings—but while the Schedule of Classes claims, through its HTTP headers, that it’s serving UTF-8, the non-ASCII characters have ended up as mojibake.

Screenshot Title (padded length) Notes
Seventeenth Century French Lit ( 4 Units) MoliÛre et les conflits MoliÛre et les conflits (30) Winter 2011’s LTFR 122 probably meant Molière.
Spanish Writing after 1939 ( 4 Units) El cine de Pedro Almodìvar El cine de Pedro Almodìvar (30) There is no Pedro “Almodìvar,” so Winter 2011’s LISP 129 probably meant Pedro Almodóvar.
Latin American Poetry ( 4 Units) Poes¥a reciente Poes¥a reciente (30) Winter 2011’s LISP 141 probably meant poesía reciente.
Themes/Intellect&Literary Hist (4 Units) Du Moyen-Age ë 1789 Du Moyen-Age ë 1789 (30) The topic for Fall 2012’s LTFR 115 potentially had à instead of ë.
Topics/Literatures in French ( 4 Units) La Litt©rature fantastique La Litt©rature fantastique (30) The é in Littérature got replaced with the copyright symbol in Winter 2013’s LTFR 141.
Topics in Algebraic Geometry ( 4 Units) Hyperk\"ahler manifolds Hyperk\“ahler manifolds (30) Fall 2018’s MATH 206A is probably referring to hyperkähler manifolds. That said, instead of mojibake, I wonder if the \"a sequence was intentionally written because the professor couldn’t type the umlaut properly.
Top/Computer Sci & Engineering ( 1 -4 Units) Machine Learning forÿRobotics Machine Learning forÿRobotics (30) I am not sure how Spring 2022’s CSE 291 achieved this. It’s possible they accidentally typed a non-breaking space, maybe by holding shift too early before “Robotics.” The non-breaking space’s Unicode code point is U+00A0, so it’s possible that other extended ASCII encodings also support the non-breaking space.

How?

I wonder what text encoding caused this to happen. ISIS likely uses fixed-length strings, which is why you’ll often see course names crushed to fit a character limit, and in HTTP responses, the server often right-pads strings with spaces. In the HTML, the topics are right-padded to exactly 30 characters long3. Interestingly, when looking at the raw bytes served from the server, the non-ASCII characters are rendered in UTF-8. For example, the Û in MoliÛre was encoded as two bytes. This means that the mojibake occurred upstream on the server side, rather than being a decoding issue in the browser.

Because all topics—normal and weird—have the same length of 30 characters, my hypothesis is that the topics were encoded and stored in ISIS with one text encoding, and read and decoded as another text encoding. The storage encoding could not have been UTF-8 because the non-ASCII character would’ve taken multiple bytes, and we would’ve seen the total length be less than 30 characters. The decoder could not have used UTF-8 either because the non-ASCII character should’ve been decoded as the replacement character � (U+FFFD), or merged with the following character and brought the total length down. Both text encodings thus likely have fixed length encoding and have incompatible extended ASCII sets. The string was then re-encoded as UTF-8, perhaps by the HTTP server, and served to me.

So what pair of encodings could map è to Û? Gemini Flash kept hallucinating answers, so if you can figure it out, please leave a comment below. Alternatively, it’s possible that UCSD created their own character encoding set for ISIS, but either the producer or consumer were unaware of it.

Likely original Substitution
è Û
ó ì
í ¥
à ë
é ©
(non-breaking space) ÿ

Honorable mention

Freshman Seminar ( 1 Units) God,Satan,& the Desert *$95fee; This course includes a weekend overnight trip to the desert (a $95 fee is required). The dates of the Anza-Borrego Freshmen Seminar trips will be: Saturday, October 20 or Saturday Oct. 27.

Fall 2012’s ERC 87 puts the fee for the course in the topic name, which is pretty unusual.

Accidentally enrollable discussion

BIBC 102: 536086 LE A00 TuTh 12:30p-1:50p PETER 108 Hampton, Randolph Y. FULL Waitlist(0) Limit: 400; unenrollable discussions A01–A10; 536097 DI A11 F 1:00p-1:50p HSS 2150 Available seats: 30 Limit: 30

In Fall 2005, BIBC 102 seems to have accidentally made a discussion enrollable, but interestingly, no one dared enroll in the discussion, even though the class filled up.

Typically, for these types of classes, UCSD has students select a discussion to enroll in. One possible reason for this is so that one popular discussion time doesn’t overflow with students and violate fire code. Instead, as presented, this schedule implies that all 400 students are required to attend all 10 discussions every week, in addition to the lecture.

Department with no subject

This probably is not interesting to you, but it was particularly annoying to me. I had assumed that there was a hierarchy of

  • Departments
    • Subjects
      • Courses

But then this “Sch of Med Interdisciplinary Crses” kept showing up across quarters, throwing a wrench in my state machine.

Headings: School of Medicine; School of Medicine Core Crses (SOMC ); Sch of Med Interdisciplinary (SOMI ); Sch of Med Interdisciplinary Crses

You can distinguish between a department heading, like “School of Medicine,” and a subject heading, like “School of Medicine Core Crses,” based on whether it has the subject code in parentheses at the end, and whether it has the generation date “As of” below the heading—only subjects have these.

Because a department contains one or more subjects, I assumed a department heading is always followed by a subject heading.

“Sch of Med Interdisciplinary Crses” above appears to be the sole exception. Rather, it shows that the following courses (221, 225, and so on) have the same subject (SOMI) as before the department heading (i.e. same subject as SOMI 420U), but the courses are under a different department (i.e., they’re under the School of Medicine Interdisciplinary Courses department rather than the School of Medicine—at least, that’s how it seems to be portrayed).

I ultimately changed my data structure from a department-subject-course hierarchy to a flattened list of courses and “commands,” where the department/subject headings set a current department/subject value to assign to subsequent courses.

Detached meetings

In some cases, a meeting can have additional meeting times under the same section code. This feature is often used by lower-division physics classes, where there could be lectures Monday, Wednesday, Friday, but the same lecture would have an additional meeting time one evening per week for a weekly or biweekly quiz.

PHYS 2A: enrollable lecture B00 taught by Sharma, Vivek A., additional time for lecture B00, discussion B01, followed by problem sessions; additional time for lecture C00, additional time for lecture C00, discussion C01, problem session taught by Sharma, Vivek A., followed by more problem sessions

However, these additional meeting times can occasionally be detached, like in Winter 2006’s PHYS 2A, where it seems the first lecture time for C00 was accidentally marked as additional. This consequently makes C00 unenrollable, and so this for whatever reason moves the instructor to the first problem session’s row.

That said, I am not sure if this is just a rendering issue with the Schedule of Classes website, and if students were still able to enroll normally through WebReg (which already existed since at least 20004) despite the data issue.

Conclusion

I’m only including this section to let you know that this article is finished, I have nothing else to say, and this wasn’t accidentally cut off or anything.

  1. And this is with TypeScript 7—the one they rewrote in Go! It was more than 2x slower with TypeScript 6. 

  2. The 1990–91 General Catalog mentions the Schedule of Classes on PDF page 53. 

  3. The quotation mark in Hyperk\“ahler manifolds was escaped as ", but resolving the HTML entity brings the length to 30 characters. 

  4. The 2000–01 General Catalog mentions “WebReg in StudentLink” on PDF page 57. I am not sure if it’s the first edition to mention WebReg, but this just shows that WebReg already existed since 2000. 

See source and revision history on GitHub.

Write a comment