# Project export: SlugCredits

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: CruzHacks 2024
- Tagline: Need credit for a UCSC course but for whatever reason you'd like to take it at a community college? With SlugCredits, you can find every transferrable CC course for a given UCSC course.
- Devpost: https://devpost.com/software/slugcredits
- GitHub: https://github.com/akash-pandit/CruzHacks24
- Team: 4 GitHub contributor(s) — Akash Pandit (12 commits), Shreya Handa (5 commits), KevinISun (3 commits), Jasmine (1 commits)

## Devpost submission (written by the team)

### Inspiration

Some of our team members have had reasons for taking classes outside of UCSC and to transfer them over. These reasons can range from financial reasons to scheduling conflicts, and making sure that each course will articulate can often be a pain. Tools like link make finding articulation agreements easy, however only for comparing degree programs. If only something like that existed to browse for a given course equivalency instead...

### What it does

SlugCredits provides an intuitive interface to search for any course equivalency for a UCSC course shown on ASSIST.org. Search for a UCSC course with drop-down menus for a UCSC department and course number, and SlugCredits will return a list of every course offered by the California Community College system that has course equivalency to the given UCSC course.

### How we built it

We housed our frontend in a classic HTML/CSS interface, brought to life with JavaScript. Our frontend interacts with a SQLite database built with a variety of scripts in several programming languages that provides the information on course equivalencies. Data was scraped using Node's headless web client puppeteer, collecting dynamically loaded course data to be parsed for our database.

### Challenges we ran into

Despite having various skills from past classes or hackathons, our idea pretty much threw our entire team into unexplored areas. Jasmine and Shreya tackled UI, frontend, and database integration (all new skills), while Kevin and Akash explored JavaScript, TypeScript, and databases for the first time. We also had to make some cuts on the technologies we used, such as struggles with MongoDB causing us to have to switch our database of choice halfway through the competition.

### Accomplishments we're proud of

All four of us learned a whole new programming language and how to work with a SQLite database, a feat we all feel proud of for spending under 24 hours of working time on this project. This is also the first time any of us are building a full stack application,

### What we learned

We learned what it takes to pull together a full stack application. The interaction of frontend, backend, and databases is something completely new to all of us. For instance, Akash learned not only how to program in JavaScript/TypeScript, but web scraping with headless clients (Node.js' puppeteer package) as well.

### What's next

This is a project that earlier could have had a lot of personal utility to members of this team, so it's something we care about greatly. Next steps for SlugCredits involve sprucing up the UI and user experience to feel like a fully polished application, moving to a full web application with React, and eventually dynamically generating the database with current data from ASSIST as it changes.

## README (from the GitHub repository)

# SlugCredits

### Welcome to your solution for finding the perfect alternative to a UCSC course.

This is a non-profit tool based on scraped data from [link](https://assist.org) to find all course equivalencies to any UCSC course listed on ASSIST.

## Detected evidence (automated analysis)

Indexed codebase: 12 recognized source files, 29 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- MongoDB (technology) — detected in the code
- PHP (language) — detected in the code
- Python (language) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (120 of 131)

```
.gitignore
action_page.php
class_selection.html
data/agreementIDs.json
data/ccs/10.json
data/ccs/100.json
data/ccs/101.json
data/ccs/102.json
data/ccs/103.json
data/ccs/104.json
data/ccs/105.json
data/ccs/106.json
data/ccs/107.json
data/ccs/108.json
data/ccs/109.json
data/ccs/110.json
data/ccs/111.json
data/ccs/112.json
data/ccs/113.json
data/ccs/114.json
data/ccs/118.json
data/ccs/119.json
data/ccs/121.json
data/ccs/122.json
data/ccs/123.json
data/ccs/124.json
data/ccs/125.json
data/ccs/126.json
data/ccs/127.json
data/ccs/13.json
data/ccs/130.json
data/ccs/131.json
data/ccs/133.json
data/ccs/134.json
data/ccs/135.json
data/ccs/136.json
data/ccs/137.json
data/ccs/138.json
data/ccs/139.json
data/ccs/14.json
data/ccs/140.json
data/ccs/142.json
data/ccs/145.json
data/ccs/146.json
data/ccs/147.json
data/ccs/148.json
data/ccs/149.json
data/ccs/150.json
data/ccs/16.json
data/ccs/17.json
data/ccs/18.json
data/ccs/19.json
data/ccs/2.json
data/ccs/20.json
data/ccs/25.json
data/ccs/27.json
data/ccs/28.json
data/ccs/3.json
data/ccs/30.json
data/ccs/31.json
data/ccs/32.json
data/ccs/33.json
data/ccs/35.json
data/ccs/36.json
data/ccs/38.json
data/ccs/4.json
data/ccs/40.json
data/ccs/41.json
data/ccs/43.json
data/ccs/44.json
data/ccs/45.json
data/ccs/47.json
data/ccs/48.json
data/ccs/49.json
data/ccs/5.json
data/ccs/51.json
data/ccs/52.json
data/ccs/53.json
data/ccs/54.json
data/ccs/55.json
data/ccs/56.json
data/ccs/57.json
data/ccs/58.json
data/ccs/6.json
data/ccs/61.json
data/ccs/62.json
data/ccs/63.json
data/ccs/64.json
data/ccs/65.json
data/ccs/66.json
data/ccs/67.json
data/ccs/68.json
data/ccs/69.json
data/ccs/70.json
data/ccs/71.json
data/ccs/72.json
data/ccs/73.json
data/ccs/74.json
data/ccs/77.json
data/ccs/78.json
data/ccs/8.json
data/ccs/80.json
data/ccs/82.json
data/ccs/83.json
data/ccs/84.json
data/ccs/86.json
data/ccs/87.json
data/ccs/9.json
data/ccs/90.json
data/ccs/91.json
data/ccs/92.json
data/ccs/93.json
data/ccs/94.json
data/ccs/95.json
data/ccs/96.json
data/ccs/97.json
data/ccs/99.json
data/courses.sqlite
data/getAgreementIDs.ts
data/getCourses.ts
[11 more files omitted for size]
```

### Dependencies

- package.json: sqlite3@^5.1.7
- server/package.json: cors@^2.8.5, dotenv@^16.3.2, express@^4.18.2, mongodb@^6.3.0, sqlite3@^5.1.7

### Recent commits (newest first)

- get up to dateMerge branch 'main' of github.com:akash-pandit/CruzHacks24
- finished db work, updated json files, finished scripts i can finally sleep
- updated dropdown and logos
- updated dropdown and logos
- updated readme
- raw scraped data + scripts to do so
- sync to main
- updated ucsc dept: [course nums] json + script
- add
- add frame1 & results files
- Merge branch 'main' of github.com:akash-pandit/CruzHacks24
- all articulated ucsc courses by dept in json
- update frame1.html
- rewriting the stack
- Adding prereqs for sqlite3 db
- test
- gerge branch 'main' of github.com:akash-pandit/CruzHacks24
- setting up node as mongodb tut recommends
- init stack
- testing key

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "dependencies": {
    "sqlite3": "^5.1.7"
  }
}

```

### server/package.json

```
{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^16.3.2",
    "express": "^4.18.2",
    "mongodb": "^6.3.0",
    "sqlite3": "^5.1.7"
  }
}

```

### server/server.js

```javascript
const express = require("express");
const app = express();
const cors = require("cors");
require("dotenv").config({ path: "./config.env" });
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.use(require("./routes/record"));
// get driver connection
const dbo = require("./db/conn");
app.listen(port, () => {
  // perform a database connection when server starts
  dbo.connectToServer(function (err) {
    if (err) console.error(err);
   });
  console.log(`Server is running on port: ${port}`);
});

```

### action_page.php

```php
<?php
// Check if the form is submitted
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Retrieve form data
    $selectedSubject = $_POST["course"];
    $selectedTopic = $_POST["course number"];

    // Process the data (you can perform database operations or other actions here)

    // Redirect or generate a response as needed
    header("Location: /success_page.php"); // Redirect to a success page
    exit();
}
?>

```

### results.html

```html
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">

    <title>Results</title>
    <link rel="stylesheet" href="./results.css">
  </head>

  <body>
    <main>
        <div>
            <div class="frame1-container">
            <div class="frame1-frame1">
                <span class="slugcredits"><span>SlugCredits</span></span>

                <img
                    src="https://www.ucsc.edu/wp-content/uploads/2023/08/fiat-slug.png"
                    alt="image13234"
                    class="logo"
                />

                <span class="back">
                    <span><a href="frame1.html">
                        <button class="button">Search For Another Class?</button>
                    </a>
                    </span>
                </span>
                
            </div>
            </div>
        </div> 
    </main>
	<script src="index.js"></script>
  </body>
</html>
```

### results.css

```css
.frame1-container {
    width: 100%;
    display: flex;
    overflow: auto;
    min-height: 100vh;
    align-items: center;
    flex-direction: column;
  }
  .frame1-frame1 {
    width: 100%;
    height: 1261px;
    display: flex;
    overflow: hidden;
    position: relative;
    align-items: flex-start;
    flex-shrink: 0;
    background-color: rgba(255, 255, 255, 1);
  }
  .slugcredits {
    top: 10px;
    left: 10px;
    color: rgba(65, 88, 211, 1);
    height: auto;
    position: absolute;
    font-size: 96px;
    font-style: Medium;
    text-align: center;
    font-family: Roboto;
    font-weight: 500;
    line-height: normal;
    font-stretch: normal;
    text-decoration: none;
  }

  .logo {
    top: 7px;
    left: 500px;
    width: 10%;
    height: 10%;
    position: absolute;
  }

  .back {
    top: 1054px;
    left: 50px;
    color: rgba(0, 0, 0, 1);
    height: auto;
    position: absolute;
    font-size: 35px;
    font-style: SemiBold;
    text-align: center;
    font-family: Roboto;
    font-weight: 600;
    line-height: normal;
    font-stretch: normal;
    text-decoration: none;
      
  }

  .button {
    background-color: #9ab4f2; 
    border: black;
    color: white;
    padding: 15px 30px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 35px;
    font-family: Roboto;
    border-radius: 12px;
  }

  .button:hover {
    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
  }
```

### frame1.html

```html
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>SlugCredits</title>
        <link href="./frame1.css" rel="stylesheet" />
        <script src="class_selection.html" defer></script>
    </head>
    
    <body>
        <main>
            <div>
                <div class="frame1-container">
                <div class="frame1-frame1">
                    <span class="slugcredits"><span>SlugCredits</span></span>
                    <span class="description">
                    <span>
                        SlugCredits is a website designed to help students find classes from
                        any California community college that can transfer over to fulfill a
                        UCSC course. To get started, select the desired department, then
                        choose a class from UCSC!
                    </span>
                    </span>
                    <img
                    src="https://www.ucsc.edu/wp-content/uploads/2023/08/fiat-slug.png"
                    alt="image13234"
                    class="logo"
                    />


                    <span class="submit">
                        <span><a href="results.html">
                            <button class="button">Submit</button>
                        </a>
                        </span>
                    </span>
                    
                    
                    <span class="searchHere"><span>Search here!</span></span>
                    
                    <img
                    src="https://d112y698adiu2z.cloudfront.net/photos/production/software_photos/002/369/651/datas/original.png"
                    alt="image32060"
                    class="smallSlug"
                    />
                    
                    <iframe src="class_selection.html" width="600" height="400" frameborder="0"></iframe>


                    <div class="image-container">
                      <img src="https://communications.ucsc.edu/wp-content/uploads/2022/12/SAMMY_RELAXING_RGB_300dpi.png" alt="Image 1">
                      <img src="https://communications.ucsc.edu/wp-content/uploads/2022/12/SAMMY-CLASSROOM_RGB_300dpi.png" alt="Image 2">
                      <img src="https://communications.ucsc.edu/wp-content/uploads/2022/12/SAMMY-GRADUATE_RGB_300dpi.png" alt="Image 3">
                      <img src="https://communications.ucsc.edu/wp-content/uploads/2022/12/SAMMY-BIKING_RGB_300dpi.png" alt="Image 4">
                      <img src="https://communications.ucsc.edu/wp-content/uploads/2022/12/SAMMY-LAPTOP_RGB_300dpi.png" alt="Image 5">


                  </div>

                </div>
            </div>
        </main>
    </body>
</html>   
```

### frame1.css

```css
.frame1-container {
  width: 100%;
  display: flex;
  overflow: auto;
  min-height: 100vh;
  align-items: center;
  flex-direction: column;
}
.frame1-frame1 {
  width: 100%;
  height: 1261px;
  display: flex;
  overflow: hidden;
  position: relative;
  align-items: flex-start;
  flex-shrink: 0;
  background-color: rgba(255, 255, 255, 1);
}
.slugcredits {
  top: 10px;
  left: 10px;
  color: rgba(65, 88, 211, 1);
  height: auto;
  position: absolute;
  font-size: 96px;
  font-style: Medium;
  text-align: center;
  font-family: Roboto;
  font-weight: 500;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
.description {
  top: 170px;
  left: 25px;
  color: rgba(0, 0, 0, 1);
  width: 858px;
  height: auto;
  position: absolute;
  font-size: 32px;
  font-style: Medium;
  text-align: left;
  font-family: Roboto;
  font-weight: 500;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
.logo {
  top: 32px;
  left: 920px;
  width: 430px;
  height: 358px;
  position: absolute;
}

iframe {
  top: 565px;
  left: 50px;
  width: 700px;
  height: 400px;
  position: absolute;
  font-size: 32px;
  font-style: Medium;
  text-align: left;
  font-family: Roboto;
  font-weight: 500;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
  padding: 10px; 
  background-color: #9ab4f2;
}

.submit {
  
  top: 1054px;
  left: 50px;
  color: rgba(0, 0, 0, 1);
  height: auto;
  position: absolute;
  font-size: 35px;
  font-style: SemiBold;
  text-align: center;
  font-family: Roboto;
  font-weight: 600;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
    
}

.button {
  background-color: rgba(65, 88, 211, 1); 
  border: black;
  color: white;
  padding: 15px 30px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 35px;
  font-family: Roboto;
  border-radius: 12px;
}

.button:hover {
  box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
}

.searchHere {
  top: 440px;
  left: 210px;
  color: rgba(0, 0, 0, 1);
  height: auto;
  position: absolute;
  font-size: 48px;
  font-style: Medium;
  text-align: center;
  font-family: Roboto;
  font-weight: 500;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
.smallSlug {
  top: 400px;
  left: 25px;
  width: 163px;
  height: 142px;
  position: absolute;
}

.image-container {
  display: flex;
  margin-top: 750px; 
  margin-left: 60px;
  z-index: 1;
}

.image-container img {
  height: 142px;
  width: 140px;
}

/*
.coffeeSlug {
  top: 750px;
  left: 65px;
  width: 140px;
  height: 142px;
  position: absolute;
}

.handSlug {
  top: 750px;
  right: 100;
  width: 140px;
  height: 142px;
  position: absolute;
}
*/
/*
.frame1-text10 {
  top: 611px;
  left: 346px;
  color: rgba(65, 88, 211, 1);
  height: auto;
  position: absolute;
  font-size: 32px;
  font-style: Medium;
  text-align: left;
  font-family: Roboto;
  font-weight: 500;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
.frame1-image2 {
  top: 1036px;
  left: 1472px;
  width: 142px;
  height: 142px;
  position: absolute;
}
.frame1-dropdownmenu {
  top: 788px;
  left: 698px;
  width: 346px;
  height: 54px;
  display: flex;
  position: absolute;
  align-items: flex-start;
  flex-shrink: 0;
}
.frame1-vector1 {
  top: 32.400001525878906px;
  left: 297.8453674316406px;
  width: 10px;
  height: 25px;
  position: absolute;
}
.frame1-option {
  gap: 10px;
  top: 0px;
  left: 0px;
  width: 346px;
  height: 54px;
  display: flex;
  padding: 14px 20px;
  position: absolute;
  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25) ;
  align-items: center;
  flex-shrink: 0;
  border-color: rgba(0, 0, 0, 1);
  border-style: solid;
  border-width: 0.5px;
  justify-content: center;
}
.frame1-text12 {
  color: rgba(0, 0, 0, 1);
  height: auto;
  flex-grow: 1;
  font-size: 25px;
  font-style: Regular;
  text-align: left;
  font-family: Inter;
  font-weight: 400;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
.frame1-dropdownmenu1 {
  top: 598px;
  left: 770px;
  width: 346px;
  height: 54px;
  display: flex;
  position: absolute;
  align-items: flex-start;
  flex-shrink: 0;
}
.frame1-vector11 {
  top: 32.400001525878906px;
  left: 297.8453674316406px;
  width: 10px;
  height: 25px;
  position: absolute;
}
.frame1-option1 {
  gap: 10px;
  top: 0px;
  left: 0px;
  width: 346px;
  height: 54px;
  display: flex;
  padding: 14px 20px;
  position: absolute;
  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25) ;
  align-items: center;
  flex-shrink: 0;
  border-color: rgba(0, 0, 0, 1);
  border-style: solid;
  border-width: 0.5px;
  justify-content: center;
}
.frame1-text14 {
  color: rgba(0, 0, 0, 1);
  height: auto;
  flex-grow: 1;
  font-size: 25px;
  font-style: Regular;
  text-align: left;
  font-family: Inter;
  font-weight: 400;
  line-height: normal;
  font-stretch: normal;
  text-decoration: none;
}
*/
```

### class_selection.html

```html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
var subjectObject = {
    "ENVS": [
        "23",
        "24",
        "80F",
        "25"
    ],
    "AM": [
        "3",
        "6",
        "10",
        "20",
        "30",
        "11A",
        "11B"
    ],
    "MATH": [
        "3",
        "19A",
        "19B",
        "23A",
        "23B",
        "21",
        "24",
        "11A",
        "22",
        "11B",
        "19A",
        "19B"
    ],
    "BIOE": [
        "20C",
        "20B"
    ],
    "STAT": [
        "7",
        "7",
        "17",
        "5",
        "17L",
        "7L"
    ],
    "ANTH": [
        "2",
        "1",
        "3"
    ],
    "BME": [
        "80G",
        "18",
        "21L",
        "5",
        "80H"
    ],
    "PHIL": [
        "22",
        "24",
        "28",
        "7",
        "9",
        "27",
        "11",
        "26",
        "80G"
    ],
    "SOCY": [
        "1",
        "10",
        "15",
        "3A",
        "3B"
    ],
    "ECON": [
        "1",
        "2",
        "10A",
        "10B"
    ],
    "APLX": [
        "80"
    ],
    "LING": [
        "50",
        "53"
    ],
    "CHIN": [
        "1"
    ],
    "FREN": [
        "1",
        "2",
        "3"
    ],
    "GERM": [
        "1",
        "2"
    ],
    "ITAL": [
        "1",
        "2"
    ],
    "JAPN": [
        "1"
    ],
    "PORT": [
        "1",
        "2"
    ],
    "SPAN": [
        "1",
        "2",
        "5M"
    ],
    "CSE": [
        "20",
        "13S",
        "16",
        "30",
        "12",
        "5J",
        "10",
        "80N",
        "80A"
    ],
    "ECE": [
        "13",
        "9",
        "101",
        "80B",
        "101",
        "101L",
        "10"
    ],
    "PHYS": [
        "6A",
        "6B",
        "6C",
        "5A",
        "5B",
        "5C",
        "5D",
        "5L",
        "5M",
        "5N",
        "5A",
        "5C",
        "6L",
        "6M",
        "6N",
        "6A",
        "6B",
        "6C",
        "1A",
        "1B",
        "5B",
        "7A"
    ],
    "BIOL": [
        "20A",
        "20L"
    ],
    "CHEM": [
        "3A",
        "4A",
        "1A",
        "3B",
        "3C",
        "4B",
        "8A",
        "8B",
        "8L",
        "8M",
        "1B",
        "3BL",
        "4AL",
        "1C",
        "1N",
        "3CL",
        "4BL",
        "1A",
        "3B",
        "4B",
        "1B",
        "1C",
        "4A",
        "3B",
        "3C"
    ],
    "ASTR": [
        "19",
        "2"
    ],
    "ART": [
        "10D",
        "15",
        "20G",
        "26",
        "80T",
        "10E",
        "20H",
        "10F",
        "20I",
        "20K",
        "20J",
        "20L"
    ],
    "ARTG": [
        "80G",
        "91"
    ],
    "CMPM": [
        "25",
        "26",
        "80K"
    ],
    "FILM": [
        "20P",
        "80V",
        "20A",
        "20B",
        "20C"
    ],
    "MUSC": [
        "1C",
        "2",
        "3",
        "6",
        "9",
        "13",
        "14",
        "15",
        "30A",
        "80C",
        "11A",
        "11B",
        "11D",
        "80P",
        "74",
        "75",
        "3",
        "80I",
        "80T",
        "80Y",
        "81P",
        "30B",
        "30C",
        "5A",
        "5B",
        "5C",
        "8A",
        "8B",
        "10",
        "12"
    ],
    "THEA": [
        "10",
        "20",
        "30",
        "61A",
        "33C",
        "36",
        "22",
        "31A",
        "31B",
        "31C",
        "37",
        "80R",
        "80U",
        "80Z",
        "50",
        "21",
        "50",
        "61B",
        "61C",
        "40"
   ],
    "CRES": [
        "68",
        "10"
    ],
    "TIM": [
        "50",
        "58"
    ],
    "HIS": [
        "5C",
        "50",
        "59",
        "60",
        "61",
        "62A",
        "62B",
        "40A",
        "40B",
        "2A",
        "2B",
        "10A",
        "10B",
        "11A",
        "11B",
        "12",
        "13",
        "30",
        "41",
        "44",
        "70A",
        "70B",
        "74",
        "74A",
        "74B",
        "75",
        "76",
        "78",
        "51",
        "58"
    ],
    "HAVC": [
        "50",
        "51",
        "55",
        "80"
    ],
    "LIT": [
        "61M",
        "61P",
        "61S",
        "61X",
        "80W",
        "81A",
        "81D",
        "61J",
        "1",
        "90",
        "90X",
        "91A",
        "91B"
    ],
    "PSYC": [
        "2",
        "20",
        "1",
        "10"
    ],
    "CMMU": [
        "10"
    ],
    "EART": [
        "5",
        "5L",
        "10",
        "10L",
        "20",
        "20L",
        "111"
    ],
    "EDUC": [
        "60",
        "10",
        "50B",
        "50C",
        "50A"
    ],
    "ESCI": [
        "30"
    ],
    "FMST": [
        "1",
        "10",
        "12",
        "13",
        "14",
        "15",
        "16",
        "18",
        "19",
        "20",
        "21",
        "30",
        "31",
        "40",
        "41"
    ],
    "GCH": [
        "1"
    ],
    "POLI": [
        "17",
        "61",
        "20",
        "1",
        "3",
        "4",
        "21",
        "60",
        "70"
    ],
    "HISC": [
        "1"
    ],
    "LALS": [
        "1"
    ],
    "LGST": [
        "10"
    ]
}

window.onload = function() {
  var subjectSel = document.getElementById("Course");
  var topicSel = document.getElementById("Number");
  for (var x in subjectObject) {
    subjectSel.options[subjectSel.options.length] = new Option(x, x);
  }
  subjectSel.onchange = function() {
    topicSel.length = 1;
    var z = subjectObject[this.value];
    for (var i = 0; i < z.length; i++) {
      topicSel.options[topicSel.options.length] = new Option(z[i], z[i]);
    }
  }
}


</script>
</head>   
<body>

<form name="form1" id="form1">
Course: <se
[truncated — 275 more characters]
```

### data/ucsc_by_dept.py

```python
import json

"""
short python script to isolate ucsc's courses by department

example:
CSE 20
CSE 30
CSE 40
BIOL 20A

becomes

{
    CSE: [20, 30, 40]
    BIOL: [20A]
}

outputs: ~/data/ucscByDept.json
"""

def main():
    # all raw course files have same ucsc courses
    with open('./data/ccs/2.json', 'r') as f:
        courses = json.load(f)

    ucscCourses = dict()

    firstLineSkipped = False
    for ucsc, _ in courses.items():
        # remove some invalid entries
        if not firstLineSkipped:
            firstLineSkipped = True
            continue
        if len(ucsc.split()) < 2:
            continue
        
        dept, num = ucsc.split()[:2]

        
        # remove the rest of the invalid entries
        if not num[0].isnumeric():
            continue
        
        # add valid entries
        if dept not in ucscCourses.keys():
            ucscCourses[dept] = []
        ucscCourses[dept].append(num)

    with open('./data/ucscByDept.json', 'w') as f:
        json.dump(ucscCourses, f, indent=4)

if __name__ == '__main__':
    main()
```

[3 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]