compsci-adl / courses-api

API for getting University of Adelaide course information
MIT License
11 stars 3 forks source link

[Feature Request] Course API #3

Open jsun969 opened 1 month ago

jsun969 commented 1 month ago

Overview

Create API endpoints from scraped data using FastAPI.

Details

GET /course/:id

{
  "id": "<nanoid generated by ourself>"
  "course_id": "107592", // course ID
  "name": {
    "subject": "COMP SCI",
    "code": "2103", // catalog number aka code
    "title": "Algorithm Design & Data Structures"
    // "other_names": ["ADDS, "DSA", "Data structures and algorithms"], // case insensitive in frontend search
  },
  "class_number": 14897,
  "year": 2024,
  "term": "Semester 1",
  "campus": "North Terrace",
  "units": 3,
  "requirement": {
    "restriction": "Not available to B. Information Technology students",
    "prerequisite": ["COMP SCI 1102"], // list of codes or high school classes (can be string for now)
    "corequisite": [], // list of codes (can be string for now)
    "assumed_knowledge": [], // list of codes (can be string for now)
    "incompatible": ["COMP SCI 1103", "COMP SCI 2202", "COMP SCI 2202B"] // list of codes (can be string for now)
  },
  "class_list": [
    {
      "type": "Workshop",
      "id": "<nanoid>",
      "classes": [
        {
          "number": "11472",
          "meetings": [
            {
              "day": "Monday",
              "location": "Scott Theatre, 001, Scott Theatre",
              "date": {
                "start": "MM-DD",
                "end": "MM-DD"
              },
              "time": {
                "start": "HH:mm",
                "end": "HH:mm"
              }
            }
          ]
        }
      ]
    }
  ]
}

GET /courses?year=2024&term=sem1

Get all courses for 2024 semester 1

{
  "courses": [
    {
        "name": {
            "subject": "COMP SCI",
            "code": "2103",
            "title": "Algorithm Design & Data Structures"
        },
        "id": "<nanoid>"
    }
  ]
}

Why would this feature be useful?

So that we can export course data to other projects.

Additional Notes

No response

Sebby37 commented 1 month ago

Given the endpoints specified in this issue, as well as the CoursePlanner API URLs in #2, I developed a basic implementation of a FastAPI server that serves these two endpoints by using said CoursePlanner API. It seems to work pretty fine in my testing, although right now the /course/ route is hard coded to use semester 1 courses as I've exclusively followed this spec.

It can be found at this gist: https://gist.github.com/Sebby37/dca1bdb54e9843f182d5e8fe4ae0da80

Feel free to suggest any changes and improvements I could make, I already have some comments in the functions detailing possible additions to the output, and I wrote this code at like 11pm so it's probably not the best it could be 😅

I'm excited to continue work on this project and hope my code helps it in any way!

Sebby37 commented 1 month ago

I've just pushed an update to my gist that implements most of what I wrote in my comments, as well as most of what's described in the "Needs to do the following" section in #2.

I don't yet have a route to get class info by class number, as the CoursePlanner API doesn't seem to have such a feature, with the only way to get class info being through knowing a course number. I also edited the /courses/ route to take a multitude of parameters, those being year, semester, subject, number, name/title (called name at the moment), career, units and campus, although career and campus use the code strings that the CoursePlanner API uses (UGRD for Undergraduate, EXTOL for External-Online). I'm not sure if we want to remove some of those parameters or not, as the list specified just taking in subject, number and title/name as well as year and semester.

Once I figure out a better way of choosing terms/semesters (currently the code only supports 2024 semester 1 and 2), I'll migrate this over to the repo and make a pr.

jtong99 commented 1 month ago

Hi @Sebby37 , I saw you're struggling to add the parameters of terms & semesters for the courses API as you hardcoded the term ID. I took a look around the course planner pages and found this API that could be helpful:

Get all terms data from the uni

URL: https://courseplanner-api.adelaide.edu.au/api/course-planner-query/v1/?target=/system/TERMS/queryx&virtual=Y&year_from=2024&year_to=2024

Sample response:

{
    "status": "success",
    "data": {
        "query": {
            "num_rows": 21,
            "queryname": "TERMS",
            "rows": [
                {
                    "TERM": "4420",
                    "DESCR": "2024 Semester 2",
                    "ACAD_YEAR": "2024",
                    "CURRENT": false
                },
                {
                    "TERM": "4423",
                    "DESCR": "2024 ELC Term 3",
                    "ACAD_YEAR": "2024",
                    "CURRENT": false
                },
                {
                    "TERM": "4433",
                    "DESCR": "2024 Trimester 1",
                    "ACAD_YEAR": "2024",
                    "CURRENT": false
                },
            ]
        }
    }
}

Interestingly, we can get ALL of the terms data, even from the past, if you change the parameters year_from and year_to. For checking the semester, trimester or term, I think it's not difficult to check the field DESCR with this data.

jsun969 commented 1 month ago

Hey @Sebby37. Sounds like a good idea. I've invited you as a collaborator. You can make a PR if you want.

@jtong99 yea this is a good way to query the terms data. TY!

jsun969 commented 1 month ago

Just did some updates to the course api. Changed year field type to number, and added location field in each meeting.

jsun969 commented 1 month ago

Hey @Sebby37 . I just figured that the course id (107592 in the example) is not unique. A course can have same id for different semester (ADDS are both 107592 for sem1 and sem2). They specify the course by using class_number which is so confusing. Can we make our own id for the courses (nanoid will be the best, or uuid). Then rename their id to course_id.

Also, I need an id after class type for each class in class_list (sry mb for renaming class_list to classList before).

This is basically what I changed:

{
+   "id": "<nanoid generated by ourself>"
-   "id": "107592", // course ID
+   "course_id": "107592", // course ID
...
    "class_list": [
        "type": "Workshop",
+       "id": "<nanoid>",
        ...
    ]
}
jsun969 commented 1 month ago

btw, id in /courses api is also changed to our id instead of the course id from uni.

jsun969 commented 1 month ago

also updated the name in /courses to be an object. since it's better for searching in our app.