Automatic class scheduler for Texas A&M written with Python+Django and React+Typescript

Overview

Rev Registration

Backend CI Frontend CI

project-demo

Description

Rev Registration is an automatic class scheduler for Texas A&M, aimed at easing the process of course registration by generating compatible schedules given the courses a student would like to take and what preferences they have. Simply select a term, pick your courses, mark off when you're not available, and we'll generate schedules for you!

For instance, imagine you've settled on 3 sections of a course you are fine with having and are having trouble finding a schedule without conflicts. Select all 3 under the Section customization level, add in your other classes, and let the schedule generator create schedules for you without time conflicts!

Features:

  • Automatic schedule generation
  • Block off busy times (availabilities)
  • Displays grade distribution
  • Shows current seats remaining
  • Search by course number or title
  • Filter for only honors or online sections
  • Visual display of schedules
  • Remembers preferences for easy access during registration
  • Login with Google
  • Save, rename, and delete generated schedules
  • Filter out full sections

Installation

Follow these steps to start a local Django server using a PostgreSQL database:

  1. For Windows, use powershell instead of command prompt.

    • Some commands don't always work on command prompt.
  2. If you don’t have it already, download Python from here.

  3. Clone the current project: git clone https://github.com/aggie-coding-club/Rev-Registration.git

    • This will clone the project into the current directory
  4. Make a virtual Python environment: python3 -m venv env

    • It is recommended to put the virtual environment in the root directory: ./Rev-Registration
    • Help us ensure that our libraries & Python versions are unified.
      • This creates a virtual environment in the env/ folder.
      • In here you'll see a directory containing the libraries that will be installed in the next step(Lib/ on Windows)
      • You'll also see a folder(Scripts/ on Windows & bin/ on Unix systems) that contains the scripts that you need to start the virtual environment.
      • Depending on your Python version, you may have to replace the python3 in all commands with either python or py. (aliases)
        • Error: The term 'python3' is not recognized as the name of a cmdlet, function, script file, or operable program.
    • Next, for Unix systems run: source env/bin/activate
    • And for Windows, in Powershell run: ./env/Scripts/activate
      • If you get a permissions error that says: execution of scripts is disabled on this system, then open another PowerShell as Administrator and run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned.
        • Alternatively, you can just run the original script as Administrator.
    • You will need to do source env/bin/activate or ./env/Scripts/activate anytime you want to interact with the server(i.e. to run it with python manage.py runserver)
  5. Now, run pip install -r autoscheduler/requirements.txt to install the necessary packages for the project.

  6. Set up a PostgresQL server by following one of these guides, and make sure you set the name of the database to dbautoscheduler when prompted:

    • Windows
    • Mac
    • Linux
    • You may also want to download pgAdmin 4 for ease of database management (it can be installed alongside PostgreSQL if you used the above Windows guide). It can be downloaded from here.
  7. (Only if using pgAdmin) Create a new server by opening pgAdmin and right-click “Servers->Create->Server…”. Set a name pgAdmin will use (it can be anything), then change to the Connection tab. Ensure the following settings are being used:

Host name/address: localhost
Port: 5432
Maintenance database: postgres
Username: postgres
Password: (not necessary)
  1. Ensure the database dbautoscheduler has been created: Using psql: Type \l in the psql prompt and see if dbautoscheduler is in the list. Using pgAdmin: Click the name of the server you created, and see if dbautoscheduler is in the tree menu.

  2. Navigate to the frontend directory: ./autoscheduler/frontend/src/ and run npm install to install our frontend dependencies

  3. Before making code changes, please go to the Github project wiki and follow the Project Setup and Install section.

Running

Before running any commands, if you're not running in the virtual environment(you should see (env) somewhere in your current terminal line), run source env/bin/activate or ./env/Scripts/activate.

Backend:

  • You will have to make and apply migrations before running the server (and whenever our models are changed). To apply migrations to your database, run python3 ./manage.py migrate

    • manage.py can be found in the ./autoscheduler/ directory.
  • You'll also need to make a .env file in autoscheduler/autoscheduler/settings/ which contains our client ID and secret for Google OAuth. As these are private values, you'll need to ask one of the members for it.

  • After migrating, you can run the server with python3 ./manage.py runserver. When running for the first time, you will have to configure autoscheduler/autoscheduler/config/postgres-info.json with your postgres username and password. This file will be automatically created if you run python3 ./manage.py runserver.

    • This starts a webserver that's listening on port 8000, so you can navigate to localhost:8000/ and you should see the landing page
      • Note: you must have run npm run dev from below
  • If python3 ./manage.py isn't working, try to use python manage.py ... or py ./manage.py ... or ./manage.py ... in place of it.

    • See python aliases above

Scraping Course Info:

The first time you run the server, you will need to scrape the course info from TAMU:

Scraping command arguments:

  • Please run these commands in the given order
  • python manage.py scrape_depts
    • -t [term] or --term [term]
      • e.g. scrape_depts -t 202031
  • python manage.py scrape_courses
    • -t [term] or --term [term]
      • e.g. scrape_courses -t 202031
    • -y [year] or --year [year]
      • e.g. scrape_courses -y 2020
      • Scrapes all semesters + locations for the given year
    • -r or --recent
      • e.g. scrape_courses -r
        • Scrapes the most recent terms. E.g. if it's October 1st 2020, it will scrape Summer + Fall 2020 for all locations
    • -t, -y, and -r are mutually exclusive
  • python manage.py scrape_grades
    • -y [year] or --year [year]
      • e.g. scrape_grades -y 2020
    • -r or --recent
    • -d or --discord
    • -c [college] or --college [college]
      • e.g. scrape_grades -c EN
    • -p [procs] or --procs [procs]
      • e.g. scrape_grades -p 5
      • scrape_grades uses multi-processing, and this changes how many processes run at a time. Defaults to the number of cores your CPU has.
    • Note that all of scrape_grades arguments can be used at the same time, except for --year and --recent

Frontend:

  • Navigate to the frontend source directory: cd ./autoscheduler/frontend/src and run npm run dev
    • This sets up a watch for file changes and compiles them
    • If you already have python manage.py runserver running, you can see the server at localhost:8000/ and refresh after you change files and npm run dev re-compiles them.
    • ctrl-c to quit

Testing:

  • The frontend has automated test suites which can be run with:
    • cd ./autoscheduler/frontend/src
    • npm run test
      • Can put filename after to test only one file: npm run test testfile.test.tsx
        • It is possible that you will need the relative filepath in front of the testfile.test.tsx, while on other systems you can't have it.
    • If that doesn't work try: npx jest <filename>
Comments
  • Implemented Graphic Schedule

    Implemented Graphic Schedule

    Still have some work to do to clean up the output and write tests, but I'm gonna make this draft for now so that y'all can see what's been done so far.

    Closes #49

    frontend 
    opened by firejake308 25
  • Implemented course scraping

    Implemented course scraping

    …_instructor functions

    There were some data fields I couldn't find in the JSON. I just left these as empty strings or False for now. Will add comments over the code to show where these are.

    backend 
    opened by ThatJuanGuy 23
  • Made Add Course button sticky

    Made Add Course button sticky

    A lot of our users were confused by the positioning of our Add Course button. This PR puts the Add course button right below the last course card, but makes the button "sticky" so that it can't go below the bottom of the CourseSelectColumn. Make sure that the spacing looks right to y'all

    frontend change 
    opened by firejake308 20
  • Added landing page

    Added landing page

    welcome page skeleton is done. Still needs:

    • google login redirect and logo
    • text to be centered

    later:

    • linking semester dropdown text to following page
    frontend 
    opened by f4alt 20
  • Transition and memoize course cards

    Transition and memoize course cards

    Description

    Users have commented that it feels jerky for cards to suddenly collapse and expand. Using Material-UI's Collapse component, I have added a 300ms transition between these states. I think Collapse probably uses some secret wizardry where they keep a pre-rendered copy of the collapsed card on hand so that they can rapidly add it back to the DOM during expansion.

    Although Collapse makes it fast to expand and collapse the cards, it has no effect on switching between Basic and Section modes. I tried applying useMemo to sectionSelect to speed up this second transition, but to no avail. It appears that the time-consuming portion is not actually running the React code to determine what the SectionSelect should be, but to take that result and render it to the screen. (This was fairly surprising because of how inefficiently the SectionSelect component is written.) To eliminate the expensive step of rendering HTML elements to the DOM, I switched to using display: none; to hide the customizationContent that wasn't currently being used.

    Rationale

    There is one sort of sketchy area where I manually calculate the height of the card (the fixHeight function), and this is liable to be accidentally broken in the future. Actually, it'll break as soon as Troy merges his Select All button. I'm not sure how I could add tests for it, though, so lmk if you have ideas.

    Also, the part with the MutationObserver seems pretty hacky, too. The problem was that when the initially expanded card is rendered, it only has the loading circle, which is small enough to apply expandedRowSmall. So if I try to set the height of sectionRows while the overflow: visible; from expandedRowSmall is still active, it'll tell me I have all the space in the world. Instead, I waited until CourseSelectColumn changed the class to expandedRow, and then applied fixHeight. Waiting for the class to change meantt using a mutation observer. unless y'all have any better ideas.

    How to test

    I'd like to try to get some automated tests for this, but JS DOM doesn't mock height and CSS rules IIRC, so I can't think of a way to do it.

    For manual tests, open small classes like JAPN 201, medium classes like CSCE 314, and enormous classes like KINE 199. They should all collapse and expand smoothly no matter what order you open them in and regardless of how many times you switch between Basic and Section in between.

    Screenshots

    |Before|After| |--|--| |old|transitions|

    Related tasks

    Closes #415 Closes #387

    frontend 
    opened by firejake308 19
  • Show remaining seats in SectionSelect

    Show remaining seats in SectionSelect

    SectionSelect now shows the available seats for each section. I changed the section number to show on its own line so that this can look better on low resolutions (specifically, I wanted to make it still look good on 1366x768 since some people might still have laptops with that terrible resolution), and still be self-explanatory, rather than just having it say "0/50" or something like that.

    This is a draft for now since I haven't made tests yet, and this is based off of Adel's frontend/show-honors branch.

    A couple design choices I made, but feel free to argue the other way if you feel there's a reason to do so:

    • Shows max seats instead of just available seats so that people can easily tell if a section is really full, or if it just hasn't had all of its seats opened yet
    • Seats are right-aligned which might look a little weird on high resolutions (for example, this is what it looks like on my 1440p monitor): image

    Closes #186.

    feature frontend 
    opened by rachelconn 17
  • Select by instructor

    Select by instructor

    Description

    A common request that we have received is the ability to select all sections taught by a particular professor, as this is a common way for students to pick classes. This PR adds such a checkbox next to the instructor name. From a design perspective, this makes the instructor header a little cramped on small screen sizes, but it can't really be helped imo 🤷. Maybe consider showing professor's last name only?

    Anyway, in order to provide a sense of hierarchy, the SectionInfos for the individual sections had to be indented to the right of the professor checkbox. Because of this indentation, on smaller screens, the meeting info may be wrapped onto 2 lines. If you don't like the current wrapping, we might need to look into CSS Grid rather than Flexbox (the current approach), which honestly scares me just a little bit.

    Also, I elected to use alternating colors (light maroon & white) to distinguish between mulitple meetings in the same section. Because I didn't like how this looked when there was only one meeting, I added a CSS rule to override the alternating colors for single-meeting sections. ~Someone remind me to add~ Added a comment to that line, because I'm 90% sure we're going to forget what it does in the future.

    We had previously discussed adding icons, but after trying them out, they felt like they cluttered the space to me. Since alternating colors was pretty effective at distinguishing between one meeting and the next, I honestly don't feel that icons are necessary.

    Small design bug: If a section has an odd number of meetings (e.g. ENGR 102), the mini-divider will be covered by the background of the last meeting. First fix that I thought of was throwing in a 3px margin between the last section and the divider, and I think I can use CSS selectors to limit this to the cases when the last meeting is colored. Lmk if y'all have better ideas.

    How to test

    Automated tests added for the selecting functionality. For visuals, check out KINE 199 for 1-meeting sections, BIOL 351 for 2-meeting sections, ENGR 102 for 3-meeting sections, PHYS 202 for 4-meeting sections, and any other classes you like.

    Screenshots

    |1 meeting|2 meetings|3 meetings| |--|--|--| |image|image|image|

    Related tasks

    Closes #259

    frontend change 
    opened by firejake308 16
  • Error messages for generating schedules

    Error messages for generating schedules

    Description

    Adds messages describing what went wrong when generate schedules doesn't return any schedules. I'd appreciate if everyone could try to think of other reason generating schedules might fail so we can be sure these error messages are accurate and cover everything that could possibly go wrong.

    Rationale

    There are a couple assumptions I make to avoid making extra queries just to check if sections still exist in the queryset:

    • Courses have sections for the term given (since when searching for courses it only gives courses with sections in the current term, this should be fine)
    • Web/honors filters don't result in an empty queryset (I made changes to make sure this assumption is always valid on the frontend, as before when the course changed it didn't change your existing choice for web/honors)

    With these assumptions, these are the three ways generating schedules can fail and their messages:

    _NO_SECTIONS_WITH_SEATS = (
        'None of the sections you selected for {subject} {course_num} have available seats.'
    )
    _NO_SECTIONS_MATCH_AVAILABILITIES = (
        'No sections for {subject} {course_num} are compatible with your available times. '
        'Either select more sections, or remove some of your busy times.'
    )
    _NO_SCHEDULES_POSSIBLE = 'No schedules are possible with your selected constraints.'
    

    There's also the possibility that the call fails (since the server is down or the schedules are malformatted), for this case I added another message to the frontend saying that something went wrong.

    I also refactored the section filters on the frontend to use an enum for consistency, since it's always bothered me that we use explicit values and this PR is vaguely related to section filters.

    How to test

    Try to generate schedules with various constraints that may or may not result in no schedules being generated. I think I was pretty thorough with the ways the call can fail, but there's always the possibility I missed something.

    Screenshots

    Previous error message: image

    Example new error messages: image image image

    Related tasks

    Closes #399.

    feature frontend backend change 
    opened by rachelconn 15
  • Added icon to honors sections

    Added icon to honors sections

    Added an icon for honors sections and appropriate tests. Currently, the icon is gray to match th professor's name, and there isn't a whole lot of space between the text and the icon. Seems fine to me, but if y'all don't like it, it's an easy fix. image

    Closes #230

    feature frontend 
    opened by firejake308 15
  • Added scrape_grades command

    Added scrape_grades command

    So this is mostly implemented other than the tests. I made this a PR (although probs should be a draft) just so we could discuss the testing for it, since a lot of the functions in it are kind of funky to test.

    I'm also considering adding optional --year and --college arguments to it so we can quickly scrape a small amount, rather than scraping everything from 2013 - 2019.

    I also need to figure out how to add SSL certificate creation to requests.get call in fetch_page_data, as not doing so gives a warning on the function call.

    backend 
    opened by gannonprudhomme 15
  • Implement Course Select Card

    Implement Course Select Card

    I have more or less implemented the course select card. I believe it has full functionality at this point, and all that remains is fixing some spacing issues and writing tests to ensure that multiple meetings/sections are handled properly. i'll leave it as a draft until the spacing and tests are fixed.

    Closes #109

    frontend 
    opened by firejake308 15
  • Expand grid in section info

    Expand grid in section info

    I was looking at this layout here, taken from MATH 140 - Spring 2021, when I realized that sections 500 and 501 weren't aligned with each other. This bothered me, but not enough to fix in #568, so I'm making a separate issue to remind myself to fix it later. The solution,if I'm not mistaken, is to move the root grid element up one level so that both sections are within the same grid container

    image

    change 
    opened by firejake308 0
  • questions regarding this project

    questions regarding this project

    so i know that you guys arent currently accepting contributions right now but i was wondering when you guys might be. additionally when and if you guys accept contributors, do contributors have to go through becoming a member of aggie coding club etc.?

    opened by AnnySuho 2
  • Google OAuth Redirect AuthStateMissing error

    Google OAuth Redirect AuthStateMissing error

    We've been frequently getting the following error on the /complete/google-oauth2/ route:

    "Internal Server Error: /complete/google-oauth2/
    Traceback (most recent call last):
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
        response = get_response(request)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
        response = view_func(request, *args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
        return view_func(*args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_django/utils.py", line 49, in wrapper
        return func(request, backend, *args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_django/views.py", line 33, in complete
        *args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_core/actions.py", line 45, in do_complete
        user = backend.complete(user=user, *args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_core/backends/base.py", line 40, in complete
        return self.auth_complete(*args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_core/utils.py", line 248, in wrapper
        return func(*args, **kwargs)
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_core/backends/oauth.py", line 375, in auth_complete
        state = self.validate_state()
      File "/layers/google.python.pip/pip/lib/python3.7/site-packages/social_core/backends/oauth.py", line 87, in validate_state
        raise AuthStateMissing(self, 'state')
    social_core.exceptions.AuthStateMissing: Session value state missing." 
    

    Easy way to query on GCP Logs Explorer: severity=(EMERGENCY OR ALERT OR CRITICAL OR ERROR) OR protoPayload.resource =~ "/complete/google-oauth2/.*"

    bug frontend 
    opened by gannonprudhomme 1
Releases(v0.2)
Owner
Aggie Coding Club
A place for all of the Aggie Coding Club's projects!
Aggie Coding Club
Developer-friendly asynchrony for Django

Django Channels Channels augments Django to bring WebSocket, long-poll HTTP, task offloading and other async support to your code, using familiar Djan

Django 5.5k Dec 29, 2022
Updates redisearch instance with igdb data used for kimosabe

igdb-pdt Update RediSearch with IGDB games data in the following Format: { "game_slug": { "name": "game_name", "cover": "igdb_coverart_url",

6rotoms 0 Jul 30, 2021
PEP-484 type hints bindings for the Django web framework

mypy-django Type stubs to use the mypy static type-checker with your Django projects This project includes the PEP-484 compatible "type stubs" for Dja

Machinalis 223 Jun 17, 2022
Strawberry-django-plus - Enhanced Strawberry GraphQL integration with Django

strawberry-django-plus Enhanced Strawberry integration with Django. Built on top

BLB Ventures 138 Dec 28, 2022
Coltrane - A simple content site framework that harnesses the power of Django without the hassle.

coltrane A simple content site framework that harnesses the power of Django without the hassle. Features Can be a standalone static site or added to I

Adam Hill 58 Jan 02, 2023
Hotwired/Turbo Django response helpers

This package provides helpers for server-side rendering of Hotwired/Turbo streams and frames. Disclaimer: the Hotwired/Turbo client libraries are, at

Hotwire for Django 66 Apr 07, 2022
Code coverage measurement for Python

Coverage.py Code coverage testing for Python. Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and

Ned Batchelder 2.3k Jan 05, 2023
Awesome Django Markdown Editor, supported for Bootstrap & Semantic-UI

martor Martor is a Markdown Editor plugin for Django, supported for Bootstrap & Semantic-UI. Features Live Preview Integrated with Ace Editor Supporte

659 Jan 04, 2023
Django Rest Framework + React application.

Django Rest Framework + React application.

2 Dec 19, 2022
A Powerful HTML white space remover for Django

HTML Whitespace remover for Django Introduction : A powerful tool to optimize Django rendered templates Why use "django_stip_whitespace" ? Adds line b

3 Jan 01, 2022
Utilities to make function-based views cleaner, more efficient, and better tasting.

django-fbv Utilities to make Django function-based views cleaner, more efficient, and better tasting. 💥 📖 Complete documentation: https://django-fbv

Adam Hill 49 Dec 30, 2022
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
A CBV to handle multiple forms in one view

django-shapeshifter A common problem in Django is how to have a view, especially a class-based view that can display and process multiple forms at onc

Kenneth Love 167 Nov 26, 2022
A visual indicator of what environment/system you're using in django

A visual indicator of what environment/system you're using in django

Mark Walker 4 Nov 26, 2022
A fresh approach to autocomplete implementations, specially for Django.

A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

YourLabs 1.6k Dec 22, 2022
Automated image processing for Django. Currently v4.0

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you.

Matthew Dapena-Tretter 2.1k Dec 17, 2022
Reusable workflow library for Django

django-viewflow Viewflow is a lightweight reusable workflow library that helps to organize people collaboration business logic in django applications.

Viewflow 2.3k Jan 08, 2023
Django + Next.js integration

Django Next.js Django + Next.js integration From a comment on StackOverflow: Run 2 ports on the same server. One for django (public facing) and one fo

Quera 162 Jan 03, 2023
Serve files with Django.

django-downloadview django-downloadview makes it easy to serve files with Django: you manage files with Django (permissions, filters, generation, ...)

Jazzband 328 Dec 07, 2022
A simple REST API to manage postal addresses, written in Python/Django.

A simple REST API to manage postal addresses, written in Python/Django.

Attila Bagossy 2 Feb 14, 2022