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
Duckiter will Automatically dockerize your Django projects.

Duckiter Duckiter will Automatically dockerize your Django projects. Requirements : - python version : python version 3.6 or upper version - OS :

soroush safari 23 Sep 16, 2021
Django-fast-export - Utilities for quickly streaming CSV responses to the client

django-fast-export Utilities for quickly streaming CSV responses to the client T

Matthias Kestenholz 4 Aug 24, 2022
A simple Django dev environment setup with docker for demo purposes for GalsenDev community

GalsenDEV Docker Demo This is a basic Django dev environment setup with docker and docker-compose for a GalsenDev Meetup. The main purposes was to mak

3 Jul 03, 2021
Automatically reload your browser in development.

django-browser-reload Automatically reload your browser in development. Requirements Python 3.6 to 3.10 supported. Django 2.2 to 4.0 supported. Are yo

Adam Johnson 254 Jan 04, 2023
An URL Shortener with Basic Features.

Simple Url Shortener What is that? Yet another url shortener built with Django framework. Preview HOW TO RUN? 1. Virtual Environment First create a vi

Ethem Turgut 6 Jan 25, 2022
Indonesia's negative news detection using gaussian naive bayes with Django+Scikir Learn

Introduction Indonesia's negative news detection using gaussian naive bayes build with Django and Scikit Learn. There is also any features, are: Input

Harifzi Ham 1 Dec 30, 2021
Django StatusPage - App to display statuspage for your services

Django StatusPage - App to display statuspage for your services

Gorlik 1 Oct 27, 2021
Automatic caching and invalidation for Django models through the ORM.

Cache Machine Cache Machine provides automatic caching and invalidation for Django models through the ORM. For full docs, see https://cache-machine.re

846 Nov 26, 2022
A small Django app to easily broadcast an announcement across a website.

django-site-broadcasts The site broadcast application allows users to define short messages and announcements that should be displayed across a site.

Ben Lopatin 12 Jan 21, 2020
Auth module for Django and GarpixCMS

Garpix Auth Auth module for Django/DRF projects. Part of GarpixCMS. Used packages: django rest framework social-auth-app-django django-rest-framework-

GARPIX CMS 18 Mar 14, 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
Alt1-compatible widget host for RuneScape 3

RuneKit Alt1-compatible toolbox for RuneScape 3, for Linux and macOS. Compatibility macOS installation guide Running This project use Poetry as packag

Manatsawin Hanmongkolchai 75 Nov 28, 2022
Buckshot++ is a new algorithm that finds highly stable clusters efficiently.

Buckshot++: An Outlier-Resistant and Scalable Clustering Algorithm. (Inspired by the Buckshot Algorithm.) Here, we introduce a new algorithm, which we

John Jung 1 Jul 02, 2022
Streamlining Django forms to provide all the wins of single-page-applications without the pain.

nango Streamlining Django forms to provide all the wins of single-page-applications without the pain. Key features Available to all Django deployments

Nick Farrell 107 Dec 12, 2022
Yummy Django API, it's the exclusive API used for the e-yummy-ke vue web app

Yummy Django API, it's the exclusive API used for the e-yummy-ke vue web app

Am.Chris_KE 1 Feb 14, 2022
GameStop clone with Django

GameStop clone with Django This is my side project with GameStop clone Author: HackerApe GitHub Profile: View Profile LinkedIn Profile: View Profile

Dmitriy Shin 2 Dec 26, 2021
Fast / fuzzy PostgreSQL counts for Django

Created by Stephen McDonald Introduction Up until PostgreSQL 9.2, COUNT queries generally required scanning every row in a database table. With millio

stephenmcd 85 Oct 25, 2021
https://django-storages.readthedocs.io/

Installation Installing from PyPI is as easy as doing: pip install django-storages If you'd prefer to install from source (maybe there is a bugfix in

Josh Schneier 2.3k Jan 06, 2023
A Django web application to receive, virus check and validate transfers of digital archival records, and allow archivists to appraise and accession those records.

Aurora Aurora is a Django web application that can receive, virus check and validate transfers of digital archival records, and allows archivists to a

Rockefeller Archive Center 20 Aug 30, 2022
Declarative model lifecycle hooks, an alternative to Signals.

Django Lifecycle Hooks This project provides a @hook decorator as well as a base model and mixin to add lifecycle hooks to your Django models. Django'

Robert Singer 1k Dec 31, 2022