import streamlit as st
import re
import pandas as pd
from streamlit_card import card
from streamlit_extras.add_vertical_space import add_vertical_space
from streamlit_extras.colored_header import colored_header
from streamlit_extras.dataframe_explorer import dataframe_explorer
from streamlit_extras.app_logo import add_logo
from streamlit_extras.faker import get_streamlit_faker
from streamlit_extras.metric_cards import style_metric_cards
from streamlit_extras.tags import tagger_component
from st_ant_tree import st_ant_tree
from streamlit.components.v1 import html, iframe
st.set_page_config(
page_title="DePaul - Course Eligibility Checker",
layout="wide",
page_icon="https://depauliaonline.com/wp-content/uploads/2017/09/Depaul.png",
initial_sidebar_state="expanded",
menu_items={
'Get Help': "https://v-alizadeh.info/",
'Report a bug': "mailto:vahid.alizadeh@depaul.edu?subject=Bug%20Report%20for%20DePaul%20Course%20Eligibility%20Checker",
'About': None
}
)
css = '''
'''
st.markdown(css, unsafe_allow_html=True)
hide_streamlit_style = """
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
# Function to load the courses data
@st.cache_data
def load_courses():
df = pd.read_excel('data/DePaul-University-Courses.xlsx')
# remove Course2 column
df = df.drop(columns=['Course2'])
df['PREREQUISITES'] = df['PREREQUISITES'].apply(
lambda x: re.sub(r"(\b[A-Za-z]+) (\d+)", r"\1 \2", str(x)) if pd.notnull(x) else "")
# if there is no prerequisites, mark as eligible
df['eligible'] = df['PREREQUISITES'].apply(lambda x: True if x is None or pd.isna(x) or x == "" else False)
# add a column to store the hyperlink to the course description page like below:
# https://www.cdm.depaul.edu/academics/pages/courseinfo.aspx?Subject={SUBJECT+}&CatalogNbr={ID}
# generate the course link based on the course code and number, if the SUBJECT+ is GAM-P, change it to GAM, otherwise keep it as is
df['Course Link'] = df.apply(
lambda
x: f"https://www.cdm.depaul.edu/academics/pages/courseinfo.aspx?Subject={'GAM' if x['SUBJECT+'] == 'GAM-P' else x['SUBJECT+']}&CatalogNbr={x['ID']}",
axis=1)
return df
# =============================================================================
# Function to parse and evaluate prerequisites
def parse_and_evaluate_prerequisites(prerequisites, all_passed_courses):
if prerequisites is None or pd.isna(prerequisites) or prerequisites == "":
return True # If no prerequisites, mark as eligible
# adds a space only where it's missing, for example changing 'CSC211' to 'CSC 211'
# prerequisites = re.sub(r"(\b[A-Za-z]+)(\d)", r"\1 \2", prerequisites)
prereq_list = prerequisites.replace('(', '').replace(')', '').replace('AND', ',').replace('OR', ',').split(',')
prereq_list = [i.strip() for i in prereq_list]
expression = prerequisites.replace("AND", "and").replace("OR", "or")
for prereq in prereq_list:
if prereq in all_passed_courses:
expression = expression.replace(prereq, "True")
else:
expression = expression.replace(prereq, "False")
try:
return eval(expression)
except Exception as e:
print(f"Error evaluating expression for prerequisites {prerequisites}: {e}")
return False
# Function to apply row-based styling
def highlight_eligibility(row):
if not row['passed'] and row['eligible']:
return ['background-color: #aeb8fe'] * len(row)
if not row['passed'] and not row['eligible']:
return ['background-color: #ffb3c1'] * len(row)
if row['passed']:
return ['background-color: #a7c957'] * len(row)
# Function to add a course to the list
def add_course(course_code):
if course_code and course_code not in st.session_state.added_courses:
if course_code in st.session_state.course_list_df['Course'].values:
st.session_state.added_courses.append(course_code)
st.session_state.course_list_df['passed'] = st.session_state.course_list_df['Course'].apply(
lambda x: 1 if x in st.session_state.added_courses else 0)
update_all_course_eligibility()
st.toast(f"'{course_code}' added successfully", icon="✅")
else:
st.toast(f"{course_code}' not found in the list of courses.", icon="⛔")
st.error(f"❌ Course code '{course_code}' not found in the list of courses.")
# Function to remove a course from the list
def remove_course(course_code):
if course_code in st.session_state.added_courses:
st.session_state.added_courses.remove(course_code)
st.session_state.course_list_df['passed'] = st.session_state.course_list_df['Course'].apply(
lambda x: 1 if x in st.session_state.added_courses else 0)
update_all_course_eligibility()
st.toast(f"'{course_code}' removed successfully", icon="❌")
def remove_all_courses():
if st.session_state.added_courses:
st.session_state.added_courses = []
st.session_state.course_list_df['passed'] = st.session_state.course_list_df['Course'].apply(lambda x: 0)
update_all_course_eligibility()
st.toast("All courses removed successfully", icon="⛔")
def update_all_course_eligibility():
passed_courses = st.session_state.course_list_df[st.session_state.course_list_df['passed'] == 1][
'Course'].tolist()
all_passed_courses = passed_courses + st.session_state.added_courses
# Update the 'eligible' column based on the evaluated prerequisites
st.session_state.course_list_df['eligible'] = st.session_state.course_list_df['PREREQUISITES'].apply(
lambda x: parse_and_evaluate_prerequisites(x, all_passed_courses))
st.session_state.update_stats_and_counts_trigger = True
# =============================================================================
# Initialize the session states
# =============================================================================
if 'added_courses' not in st.session_state:
st.session_state.added_courses = []
if 'course_list_df' not in st.session_state:
st.session_state.course_list_df = load_courses()
update_all_course_eligibility()
if 'eligible_count' not in st.session_state:
# count of eligible courses in the course_list_df
st.session_state.eligible_count = 0
if 'passed_count' not in st.session_state:
# count of passed courses in the course_list_df
st.session_state.passed_count = 0
# a dictionary to store eligible counts in different areas SE, CSC, CSE, CSEC, CST, DSC, GAM-P, HCI, HIT, IS, IT, NET
if 'eligible_counts_per_area' not in st.session_state:
st.session_state.eligible_counts_per_area = {
"SE": 0,
"CSC": 0,
"CSE": 0,
"CSEC": 0,
"CST": 0,
"DSC": 0,
"GAM-P": 0,
"HCI": 0,
"HIT": 0,
"IS": 0,
"IT": 0,
"NET": 0,
}
# =============================================================================
# Streamlit app layout
def app():
add_logo("https://depauliaonline.com/wp-content/uploads/2017/09/Depaul.png", height=300)
# =============================================================================
# Title of the app , bold, large, centered: Course Eligibility Checker
st.write('''
# :blue[DePulse]: **Heartbeat of Your Academic Path**
''')
# st.header('This is a header with a divider', divider='violet', anchor=False)
colored_header(
label="Course Eligibility Checker",
description="Check your prerequisites and eligibility for DePaul University courses",
color_name="violet-70",
)
# st.markdown(f'''
#
# ''', unsafe_allow_html=True)
sidebar = st.sidebar.container()
col1, col2, col3 = st.columns([2, 2, 4])
with col1:
colored_header(
label="🛒 Add Courses Manually",
description="",
color_name="blue-70",
)
# Input for adding a new course
with st.form("add_course_form"):
new_course = st.text_input(
"Enter course code to add (e.g., 'CSC 211') Use space between course code and number", "")
add_course_button = st.form_submit_button(label="✅ Add Course", type="primary", use_container_width=True)
if add_course_button and new_course:
# adds a space only where it's missing, for example changing 'CSC211' to 'CSC 211'
new_course = re.sub(r"(\b[A-Za-z]+)(\d)", r"\1 \2", new_course)
# check if the course_code is in the course_list_df, return true or false
add_course(new_course)
with col2:
colored_header(
label="⚙️ Program Requirements",
description="",
color_name="blue-70",
)
# filters based on ID >400 for grad courses and ID <400 for undergrad courses
grad_col, ugrad_col = st.columns(2)
grad = grad_col.toggle('📕 Grad Courses', True)
ugrad = ugrad_col.toggle('📘 UGrad Courses', False)
if not grad and not ugrad:
st.error("Please select at least one of the options above")
st.stop()
filtered_df_ID = st.session_state.course_list_df[(
(st.session_state.course_list_df['ID'] >= 400 if grad else False) |
(st.session_state.course_list_df['ID'] < 400 if ugrad else False)
)]
concentration_visibility = False
if not grad:
concentration_visibility = True
concentrations = st.radio("Select a concentration",
["MS SE - Software Development & Architecture Concentration",
"MS SE - Real-Time Software & Game Systems Concentration",
"MS SE - AI in Software Engineering Concentration",
"MS Game Programming"], index=0, disabled=concentration_visibility)
with sidebar:
colored_header(
label="📃 List Of Passed Courses",
description="",
color_name="blue-70",
)
# Display added courses as removable tags
if st.session_state.added_courses:
remove_all_button = st.button("❌ Remove all", key="remove_all", on_click=remove_all_courses, type="primary",
use_container_width=True)
# Loop through each added course and find its details from the course_list_df
for course in st.session_state.added_courses:
course_row = st.session_state.course_list_df[st.session_state.course_list_df['Course'] == course].iloc[
0]
course_title = course_row['TITLE']
tagger_component(
content="",
tags=[course, course_title],
# color_name= an array of blue with the size of st.session_state.added_courses
color_name=["#386641", "#3d5a80"]
)
# for course in st.session_state.added_courses:
# st.write(course, st.button("Remove", key=course, on_click=remove_course, args=(course,)))
else:
st.info("➖ No courses added yet")
with col3:
colored_header(
label="🔢 Stats",
description="",
color_name="blue-70",
)
# Eligible count diff and update
new_eligible_count = len(filtered_df_ID[filtered_df_ID['eligible'] == 1])
# Passed count diff and update
new_passed_count = len(st.session_state.course_list_df[st.session_state.course_list_df['passed'] == 1])
delta_passed = new_passed_count - st.session_state.passed_count
delta_eligible = new_eligible_count - st.session_state.eligible_count
# Update the session state
st.session_state.passed_count = new_passed_count
st.session_state.eligible_count = new_eligible_count
col1, col2, col3, col4 = st.columns(4)
col1.metric("✔️Passed", new_passed_count, delta=delta_passed, help="Total number of passed courses")
col2.metric("🚦Eligible", new_eligible_count, delta=delta_eligible, help="Total number of eligible courses")
col3.metric("📕Total **Grad** Courses",
len(st.session_state.course_list_df[st.session_state.course_list_df['ID'] >= 400]),
delta="ID >= 400", delta_color="off", help="Total number of graduate courses with ID >= 400")
col4.metric("📘Total **UGrad** Courses",
len(st.session_state.course_list_df[st.session_state.course_list_df['ID'] < 400]), delta="ID < 400",
delta_color="off", help="Total number of undergraduate courses with ID < 400")
# ======================================================================================================================
# Program Requirements
tree_ms_se_sda = [
{
"value": "MS-SE-SDA",
"title": """MS SE Software Development & Architecture Concentration""",
"icon": "",
"children": [
{
"value": "Introductory",
"title": "Introductory Courses",
"children": [
{"value": "CSC 400", "title": "CSC 400 Discrete Structures for Computer Science"},
{"value": "CSC 401", "title": "CSC 401 Introduction to Programming"},
{"value": "CSC 402", "title": "CSC 402 Data Structures I"},
{"value": "CSC 403", "title": "CSC 403 Data Structures II"}
]
},
{
"value": "Foundation",
"title": "Foundation Courses",
"children": [
{"value": "SE 433", "title": "SE 433 Software Testing and Quality Assurance"},
{"value": "SE 441", "title": "SE 441 Continuous Delivery and Devops"},
{
"value": "SE 450 OR SE 456",
"title": "Choose one SE 450 OR SE 456:",
"children": [
{"value": "SE 450", "title": "SE 450 Object-Oriented Software Development"},
{"value": "SE 456", "title": "SE 456 Architecture of Real-Time Systems"},
]
},
{"value": "SE 475", "title": "SE 475 Managing Globally Distributed Software Development"}
]
},
{
"value": "Advanced",
"title": "Advanced Courses",
"children": [
{"value": "SE 452 OR SE 457",
"title": "Choose one SE 452 OR SE 457:",
"children": [
{"value": "SE 452", "title": "SE 452 Distributed Software Development"},
{"value": "SE 457", "title": "SE 457 Software Testing and Quality Assurance"},
]
},
{"value": "SE 459", "title": "SE 459 Agile Software Development"},
{"value": "SE 480", "title": "SE 480 Software Architecture I"}
]
}
]
}
]
tree_ms_se_rts = [
{
"value": "MS-SE-rts",
"title": """MS SE Real-Time Software & Game Systems Concentration""",
"children": [
{
"value": "Introductory",
"title": "Introductory Courses",
"children": [
{"value": "CSC 400", "title": "CSC 400 Discrete Structures for Computer Science"},
{"value": "CSC 401", "title": "CSC 401 Introduction to Programming"},
{"value": "CSC 402", "title": "CSC 402 Data Structures I"},
{"value": "CSC 403", "title": "CSC 403 Data Structures II"},
{"value": "CSC 406", "title": "CSC 406 Systems I"},
{"value": "CSC 407", "title": "CSC 407 Systems II"}
]
},
{
"value": "Foundation",
"title": "Foundation Courses",
"children": [
{"value": "CSC 461", "title": "CSC 461 Optimized C++"},
{"value": "SE 456", "title": "SE 456 Architecture of Real-Time Systems"},
{"value": "CSC 486", "title": "CSC 486 Real-Time Networking "},
{"value": "CSC 588", "title": "CSC 588 Real-Time Multithreaded Architecture"},
{"value": "SE 485", "title": "SE 485 Real-Time Software Development I"},
{"value": "SE 585", "title": "SE 585 Real-Time Software Development II"}
]
},
{
"value": "Choose Focus",
"title": """Choose Game or Software Focus:""",
"children": [
{"value": "Game Focus",
"title": "Game Focus",
"children": [
{"value": "GAM-P 425", "title": "GAM 425 Applied 3D Geometry"},
{"value": "GAM-P 470", "title": "GAM 470 Rendering and Graphics Programming"},
{"value": "SE 576", "title": "SE 576 Gpu Architecture"},
{"value": "CSC 562", "title": "CSC 562 Optimized C++ Multithreading"}
]
},
{"value": "Software Focus",
"title": "Game Focus",
"children": [
{"value": "CSC 552", "title": "CSC 552 Concurrent Software Development"},
{"value": "CSC 463", "title": "CSC 463 Theory and Practice of Safe Systems Programming"},
{"value": "SE 576", "title": "SE 576 Gpu Architecture"},
{"value": "CSC 562", "title": "CSC 562 Optimized C++ Multithreading"}
]
}
]
},
]
}
]
tree_ms_se_ai = [
{
"value": "MS-SE-rts",
"title": """MS SE AI in Software Engineering Concentration""",
"children": [
{
"value": "Introductory",
"title": "Introductory Courses",
"children": [
{"value": "CSC 400", "title": "CSC 400 Discrete Structures for Computer Science"},
{"value": "CSC 401", "title": "CSC 401 Introduction to Programming"},
{"value": "CSC 402", "title": "CSC 402 Data Structures I"},
{"value": "CSC 403", "title": "CSC 403 Data Structures II"},
{"value": "IT 403", "title": "IT 403 Statistics and Data Analysis"}
]
},
{
"value": "Foundation",
"title": "Foundation Courses",
"children": [
{"value": "CSC 421", "title": "CSC 421 Applied Algorithms and Structures"},
{"value": "DSC 441", "title": "DSC 441 Fundamentals of Data Science"},
{"value": "CSC 480", "title": "CSC 480 Artificial Intelligence I"},
{
"value": "SE 433 OR SE 441",
"title": "Choose one SE 433 OR SE 441:",
"children": [
{"value": "SE 433", "title": "SE 433 Software Testing and Quality Assurance"},
{"value": "SE 441", "title": "SE 441 Continuous Delivery and Devops"},
]
},
{
"value": "SE 450 OR SE 456",
"title": "Choose one SE 450 OR SE 456:",
"children": [
{"value": "SE 450", "title": "SE 450 Object-Oriented Software Development"},
{"value": "SE 456", "title": "SE 456 Architecture of Real-Time Systems"},
]
},
{"value": "SE 475", "title": "SE 475 Managing Globally Distributed Software Development"},
]
},
{
"value": "Advanced",
"title": "Advanced Courses",
"children": [
{"value": "DSC 478", "title": "DSC 478 Programming Machine Learning Applications"},
{"value": "SE 488", "title": "SE 488 Ai-Driven Software Development"},
{"value": "SE 489", "title": "SE 489 Machine Learning Engineering for Production (Mlops)"}
]
}
]
}
]
tree_ms_game = [
{
"value": "MS-SE-rts",
"title": """MS Game Programming """,
"children": [
{
"value": "Introductory",
"title": "Introductory Courses",
"children": [
{"value": "CSC 400", "title": "CSC 400 Discrete Structures for Computer Science"},
{"value": "CSC 401", "title": "CSC 401 Introduction to Programming"},
{"value": "CSC 402", "title": "CSC 402 Data Structures I"},
{"value": "CSC 403", "title": "CSC 403 Data Structures II"},
{"value": "CSC 406", "title": "CSC 406 Systems I"},
{"value": "CSC 407", "title": "CSC 407 Systems II"}
]
},
{
"value": "Foundation",
"title": "Foundation Courses",
"children": [
{"value": "CSC 461", "title": "CSC 461 Optimized C++"},
{"value": "GAM-P 425", "title": "GAM 425 Applied 3D Geometry"},
{
"value": "GPH 469 OR GAM 470",
"title": "Choose one GPH 469 OR GAM 470:",
"children": [
{"value": "GPH 469", "title": "GPH 469 Computer Graphics Development"},
{"value": "GAM-P 470", "title": "GAM 470 Rendering and Graphics Programming"},
]
},
{"value": "SE 456", "title": "SE 456 Architecture of Real-Time Systems"},
]
},
{
"value": "Advanced",
"title": "Advanced Courses",
"children": [
{"value": "CSC 486", "title": "CSC 486 Real-Time Networking"},
{"value": "CSC 588", "title": "CSC 588 Real-Time Multithreaded Architecture"},
{"value": "GAM-P 475", "title": "GAM 475 Real - Time Software Development I"},
{
"value": "GAM 476 OR GAM 450",
"title": "Choose one GAM 476 OR GAM 450:",
"children": [
{"value": "GAM-P 476", "title": "GAM 476 Artificial Intelligence for Computer Games"},
{"value": "GAM-P 450", "title": "GAM 450 Physics for Game Developers"},
]
},
{"value": "GAM-P 575", "title": "GAM 575 Real-Time Software Development II"},
{"value": "GAM-P 576", "title": "GAM 576 Gpu Architecture"}
]
}
]
}
]
# ======================================================================================================================
requirements_tables_container = st.container()
def render_requirements_tables_container(header, requirements):
with requirements_tables_container:
colored_header(
label=header,
description="List of courses in Intro, Foundation, and Advanced categories | **:green[Passed Courses] | :red[Ineligible Courses] | :blue[Eligible Courses]**",
color_name="red-70",
)
col1, col2 = st.columns([3, 1])
with col1:
selected_courses = st_ant_tree(treeData=requirements, allowClear=True, bordered=True,
treeDefaultExpandAll=True,
treeLine=True, status="warning",
filterTreeNode=True, min_height_dropdown="150px",
multiple=True,
placeholder="Type to Filter ot Choose Your Courses >> Then Hit The Button To Add",
showArrow=True, showSearch=True,
treeCheckable=True,
width_dropdown="100%", disabled=False, maxTagCount=20)
with col2:
st.button("✅ Add selected courses",
on_click=lambda: [add_course(course) for course in selected_courses if
course not in st.session_state.added_courses],
key="add-all-selected-button", type="primary", use_container_width=True)
# ======================================================================================================================
if concentrations == "MS SE - Software Development & Architecture Concentration":
program_header = "Software Development & Architecture Concentration Requirements"
program_requirements = tree_ms_se_sda
render_requirements_tables_container(program_header, program_requirements)
# multiselect_sda = st.multiselect("Select courses",
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "SE 433", "SE 441", "SE 450",
# "SE 456", "SE 452", "SE 457", "SE 459", "SE 480"],
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403"], key="concentration1-select")
col1, col2, col3 = st.columns(3)
with col1:
st.write("##### Intro: \n")
# show a table of Intro courses (CSC 400, CSC 401, CSC 402, CSC 403) highlighted based on the eligibility
intro_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["CSC 400", "CSC 401", "CSC 402", "CSC 403"])]
intro_courses = intro_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(intro_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col2:
st.write("##### Foundation: \n")
# show a table of Foundation courses (SE 433, SE 441, SE 450, SE 456) highlighted based on the eligibility
foundation_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["SE 433", "SE 441", "SE 450", "SE 456", "SE 475"])]
foundation_courses = foundation_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(foundation_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col3:
st.write("##### Advanced: \n")
# show a table of advanced courses (SE 452, SE 457, SE 459, SE 480) highlighted based on the eligibility
advanced_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["SE 452", "SE 457", "SE 459", "SE 480"])]
advanced_courses = advanced_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(advanced_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
if concentrations == "MS SE - Real-Time Software & Game Systems Concentration":
program_header = "Real-Time Software & Game Systems Concentration Requirements"
program_requirements = tree_ms_se_rts
render_requirements_tables_container(program_header, program_requirements)
# multiselect_sda = st.multiselect("Select courses",
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407",
# "CSC 461", "SE 456", "CSC 486", "CSC 588", "SE 485", "SE 585",
# "GAM-P 425", "GAM-P 470", "SE 576", "CSC 562",
# "CSC 552", "CSC 463", "SE 576", "CSC 562"],
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407"],
# key="concentration2-select")
col1, col2, col3 = st.columns(3)
with col1:
st.write("##### Intro: \n")
# show a table of Intro courses (CSC 400, CSC 401, CSC 402, CSC 403) highlighted based on the eligibility
intro_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(
["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407"])]
intro_courses = intro_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(intro_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col2:
st.write("##### Foundation: \n")
# show a table of Foundation courses (SE 433, SE 441, SE 450, SE 456) highlighted based on the eligibility
foundation_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(
["CSC 461", "SE 456", "CSC 486", "CSC 588", "SE 485", "SE 585"])]
foundation_courses = foundation_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(foundation_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col3:
st.write("##### Game Focus: \n")
# show a table of advanced courses (SE 452, SE 457, SE 459, SE 480) highlighted based on the eligibility
game_focus_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["GAM-P 425", "GAM-P 470", "SE 576", "CSC 562"])]
game_focus_courses = game_focus_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(game_focus_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
st.write("##### Software Focus: \n")
# show a table of advanced courses (SE 452, SE 457, SE 459, SE 480) highlighted based on the eligibility
software_focus_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["CSC 552", "CSC 463", "SE 576", "CSC 562"])]
software_focus_courses = software_focus_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(software_focus_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
if concentrations == "MS SE - AI in Software Engineering Concentration":
program_header = "AI in Software Engineering Concentration Requirements"
program_requirements = tree_ms_se_ai
render_requirements_tables_container(program_header, program_requirements)
# multiselect_ai = st.multiselect("Select courses",
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "IT 403", "CSC 421", "DSC 441",
# "CSC 480", "SE 433", "SE 441", "SE 450", "SE 456", "DSC 478", "SE 488",
# "SE 489"], ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "IT 403"],
# key="concentration3-select")
# a button to add the selected courses, but do not add the courses that are already added
col1, col2, col3 = st.columns(3)
with col1:
st.write("##### Intro: \n")
# show a table of Intro courses
intro_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["CSC 400", "CSC 401", "CSC 402", "CSC 403", "IT 403"])]
intro_courses = intro_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(intro_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col2:
st.write("##### Foundation: \n")
# show a table of Foundation courses (
foundation_courses = st.session_state.course_list_df[st.session_state.course_list_df['Course'].isin(
["CSC 421", "DSC 441", "CSC 480", "SE 433", "SE 441", "SE 450", "SE 456"])]
foundation_courses = foundation_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(foundation_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col3:
st.write("##### Advanced: \n")
# show a table of advanced courses
advanced_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(["DSC 478", "SE 488", "SE 489"])]
advanced_courses = advanced_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(advanced_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
if concentrations == "MS Game Programming":
program_header = "MS Game Programming Requirements Requirements"
program_requirements = tree_ms_game
render_requirements_tables_container(program_header, program_requirements)
# multiselect_ai = st.multiselect("Select courses",
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407",
# "CSC 461", "GAM-P 425", "GPH 469", "GAM-P 470", "SE 456",
# "CSC 486", "CSC 588", "GAM-P 475", "GAM-P 476", "GAM-P 450", "GAM-P 575",
# "GAM-P 576"],
# ["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407"],
# key="concentration4-select")
# a button to add the selected courses, but do not add the courses that are already added
col1, col2, col3 = st.columns(3)
with col1:
st.write("##### Intro: \n")
# show a table of Intro courses
intro_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(
["CSC 400", "CSC 401", "CSC 402", "CSC 403", "CSC 406", "CSC 407"])]
intro_courses = intro_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(intro_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col2:
st.write("##### Foundation: \n")
# show a table of Foundation courses (
foundation_courses = st.session_state.course_list_df[st.session_state.course_list_df['Course'].isin(
["CSC 461", "GAM-P 425", "GPH 469", "GAM-P 470", "SE 456"])]
foundation_courses = foundation_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(foundation_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
with col3:
st.write("##### Advanced: \n")
# show a table of advanced courses
advanced_courses = st.session_state.course_list_df[
st.session_state.course_list_df['Course'].isin(
["CSC 486", "CSC 588", "GAM-P 475", "GAM-P 476", "GAM-P 450", "GAM-P 575", "GAM-P 576"])]
advanced_courses = advanced_courses[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(advanced_courses.style.apply(highlight_eligibility, axis=1), use_container_width=True,
hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
})
# ======================================================================================================================
colored_header(
label="🎯 List of Courses Per Area",
description="Expand the list to see the courses that you are eligible for",
color_name="red-70",
)
# count eligibility for each subject and update the count only if there is a change in the list of added courses
new_eligible_counts_per_area = {'CSC': len(
filtered_df_ID[(filtered_df_ID['SUBJECT+'].str.contains(r"\bCSC\b") & filtered_df_ID['eligible'] == 1)]),
'SE': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bSE\b") & filtered_df_ID[
'eligible'] == 1)]),
'GAM-P': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bGAM-P\b") & filtered_df_ID[
'eligible'] == 1)]),
'DSC': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bDSC\b") & filtered_df_ID[
'eligible'] == 1)]),
'NET': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bNET\b") & filtered_df_ID[
'eligible'] == 1)]),
'CSE': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bCSE\b") & filtered_df_ID[
'eligible'] == 1)]),
'CSEC': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bCSEC\b") & filtered_df_ID[
'eligible'] == 1)]),
'CST': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bCST\b") & filtered_df_ID[
'eligible'] == 1)]),
'HCI': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bHCI\b") & filtered_df_ID[
'eligible'] == 1)]),
'HIT': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bHIT\b") & filtered_df_ID[
'eligible'] == 1)]),
'IS': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bIS\b") & filtered_df_ID[
'eligible'] == 1)]),
'IT': len(filtered_df_ID[(
filtered_df_ID['SUBJECT+'].str.contains(r"\bIT\b") & filtered_df_ID[
'eligible'] == 1)])}
st.session_state.update_stats_and_counts_trigger = False
# create 12 columns
col1, col2, col3, col4, col5 = st.columns([5, 1, 1, 1, 1])
# Display the total number of courses for ech subject that student is eligible for
# SE, CSC, CSE, CSEC, CST, DSC, GAM-P, HCI, HIT, IS, IT, NET
with col2:
add_vertical_space(4)
st.metric(label="Eligible :blue[**CSC**]", value=new_eligible_counts_per_area['CSC'],
delta=new_eligible_counts_per_area['CSC'] - st.session_state.eligible_counts_per_area['CSC'],
help="Number of CSC courses you are eligible to take")
st.metric(label="Eligible :blue[**NET**]", value=new_eligible_counts_per_area['NET'],
delta=new_eligible_counts_per_area['NET'] - st.session_state.eligible_counts_per_area['NET'],
help="Number of NET courses you are eligible to take")
st.metric(label="Eligible :blue[**CSE**]", value=new_eligible_counts_per_area['CSE'],
delta=new_eligible_counts_per_area['CSE'] - st.session_state.eligible_counts_per_area['CSE'],
help="Number of CSE courses you are eligible to take")
with col3:
add_vertical_space(4)
st.metric(label="Eligible :blue[**SE**]", value=new_eligible_counts_per_area['SE'],
delta=new_eligible_counts_per_area['SE'] - st.session_state.eligible_counts_per_area['SE'],
help="Number of SE courses you are eligible to take")
st.metric(label="Eligible :blue[**CSEC**]", value=new_eligible_counts_per_area['CSEC'],
delta=new_eligible_counts_per_area['CSEC'] - st.session_state.eligible_counts_per_area['CSEC'],
help="Number of CSEC courses you are eligible to take")
st.metric(label="Eligible :blue[**CST**]", value=new_eligible_counts_per_area['CST'],
delta=new_eligible_counts_per_area['CST'] - st.session_state.eligible_counts_per_area['CST'],
help="Number of CST courses you are eligible to take")
with col4:
add_vertical_space(4)
st.metric(label="Eligible :blue[**GAM**]", value=new_eligible_counts_per_area['GAM-P'],
delta=new_eligible_counts_per_area['GAM-P'] - st.session_state.eligible_counts_per_area['GAM-P'],
help="Number of GAM-P courses you are eligible to take")
st.metric(label="Eligible :blue[**HCI**]", value=new_eligible_counts_per_area['HCI'],
delta=new_eligible_counts_per_area['HCI'] - st.session_state.eligible_counts_per_area['HCI'],
help="Number of HCI courses you are eligible to take")
st.metric(label="Eligible :blue[**HIT**]", value=new_eligible_counts_per_area['HIT'],
delta=new_eligible_counts_per_area['HIT'] - st.session_state.eligible_counts_per_area['HIT'],
help="Number of HIT courses you are eligible to take")
with col5:
add_vertical_space(4)
st.metric(label="Eligible :blue[**DSC**]", value=new_eligible_counts_per_area['DSC'],
delta=new_eligible_counts_per_area['DSC'] - st.session_state.eligible_counts_per_area['DSC'],
help="Number of DSC courses you are eligible to take")
st.metric(label="Eligible :blue[**IS**]", value=new_eligible_counts_per_area['IS'],
delta=new_eligible_counts_per_area['IS'] - st.session_state.eligible_counts_per_area['IS'],
help="Number of IS courses you are eligible to take")
st.metric(label="Eligible :blue[**IT**]", value=new_eligible_counts_per_area['IT'],
delta=new_eligible_counts_per_area['IT'] - st.session_state.eligible_counts_per_area['IT'],
help="Number of IT courses you are eligible to take")
style_metric_cards(border_left_color="#124684", border_color="#9AD8E1", border_size_px=1, box_shadow=True)
# update the session state
st.session_state.eligible_counts_per_area = new_eligible_counts_per_area
# st.write(filtered_df_ID[filtered_df_ID['SUBJECT+'].str.contains(r"\bDSC\b")])
# st.divider()
def render_course_table_per_subject(subject):
df = filtered_df_ID[filtered_df_ID['SUBJECT+'].str.contains(r"\b" + subject + r"\b")].sort_values(
by=['eligible', 'passed', 'PREREQUISITES'], ascending=[False, False, False])
df = df[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(df.style.apply(highlight_eligibility, axis=1), use_container_width=True, hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
}
)
with col1:
# 12 tabs for each subject
tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9, tab10, tab11, tab12 = st.tabs(
["🔵 CSC", "🔵 SE", "🔵 GAM-P", "🔵 DSC", "🔵 NET", "🔵 CSE", "🔵 CSEC", "🔵 CST", "🔵 HCI", "🔵 HIT", "🔵 IS",
"🔵 IT"])
with tab1:
render_course_table_per_subject("CSC")
with tab2:
render_course_table_per_subject("SE")
with tab3:
render_course_table_per_subject("GAM")
with tab4:
render_course_table_per_subject("DSC")
with tab5:
render_course_table_per_subject("NET")
with tab6:
render_course_table_per_subject("CSE")
with tab7:
render_course_table_per_subject("CSEC")
with tab8:
render_course_table_per_subject("CST")
with tab9:
render_course_table_per_subject("HCI")
with tab10:
render_course_table_per_subject("HIT")
with tab11:
render_course_table_per_subject("IS")
with tab12:
render_course_table_per_subject("IT")
# col1_expanders, col2_expanders = st.columns(2)
#
# with col1_expanders:
# expander_csc = st.expander("🔵 See CSC Courses")
# with expander_csc:
# render_course_table_per_subject("CSC")
#
# expander_gam = st.expander("🔵 See GAM Courses")
# with expander_gam:
# render_course_table_per_subject("GAM-P")
#
# expander_net = st.expander("🔵 See NET Courses")
# with expander_net:
# render_course_table_per_subject("NET")
#
# expander_cse = st.expander("🔵 See CSE Courses")
# with expander_cse:
# render_course_table_per_subject("CSE")
#
# expander_csec = st.expander("🔵 See CSEC Courses")
# with expander_csec:
# render_course_table_per_subject("CSEC")
#
# expander_cst = st.expander("🔵 See CST Courses")
# with expander_cst:
# render_course_table_per_subject("CST")
#
# with col2_expanders:
# expander_se = st.expander("🔵 See SE Courses")
# with expander_se:
# render_course_table_per_subject("SE")
#
# expander_dsc = st.expander("🔵 See DSC Courses")
# with expander_dsc:
# render_course_table_per_subject("DSC")
#
# expander_hci = st.expander("🔵 See HCI Courses")
# with expander_hci:
# render_course_table_per_subject("HCI")
#
# expander_hit = st.expander("🔵 See HIT Courses")
# with expander_hit:
# render_course_table_per_subject("HIT")
#
# expander_is = st.expander("🔵 See IS Courses")
# with expander_is:
# render_course_table_per_subject("IS")
#
# expander_it = st.expander("🔵 See IT Courses")
# with expander_it:
# render_course_table_per_subject("IT")
# ======================================================================================================================
colored_header(
label="📝 List of All Courses",
description="Use the filters to narrow down the list of courses",
color_name="red-70",
)
expander = st.expander("🔍 Filter Courses")
with expander:
options = st.multiselect(
'Select Subject(s)',
st.session_state.course_list_df['SUBJECT+'].unique(),
default=st.session_state.course_list_df['SUBJECT+'].unique()
)
# filter df based on the selected SUBJECT+ column
filtered_df_manual = filtered_df_ID[filtered_df_ID['SUBJECT+'].isin(options)]
# Display courses table with eligibility highlighted
filtered_df = dataframe_explorer(filtered_df_manual, case=False)
# sort by eligibility and passed and prerequisites
filtered_df = filtered_df.sort_values(by=['eligible', 'passed', 'PREREQUISITES'],
ascending=[False, False, False])
filtered_df = filtered_df[
['Course Link', 'Course', 'TITLE', 'PREREQUISITES', 'Typically Offered Terms', 'eligible', 'passed']]
st.dataframe(filtered_df.style.apply(highlight_eligibility, axis=1), use_container_width=True, hide_index=True,
column_config={
"Course Link": st.column_config.LinkColumn(
"Course Link",
width='small',
help="Link to the course description page on the DePaul University website",
display_text="Open Link"
),
"passed": st.column_config.CheckboxColumn(
"passed",
help="If you have passed the course or not",
width='small'
)
}
)
# ======================================================================================================================
colored_header(
label="🔗 Links",
description="",
color_name="red-70",
)
col1, col2, col3, col4 = st.columns(4)
with col2:
card(
title="DePaul University",
text="School of Computing",
image="https://depauliaonline.com/wp-content/uploads/2017/09/Depaul.png",
url="https://www.cdm.depaul.edu/academics/Pages/School-of-Computing.aspx",
)
with col3:
card(
title="Course Catalog",
text="CDM",
image="https://depauliaonline.com/wp-content/uploads/2017/09/Depaul.png",
url="https://www.cdm.depaul.edu/academics/Pages/CourseCatalog.aspx",
)
with col1:
st.markdown('''
Test: [](https://visitorbadge.io/status?path=https%3A%2F%2Fdepaul.v-alizadeh.info%2Fdepulse)
''')
if __name__ == "__main__":
app()