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: [![Visitors](https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fdepaul.v-alizadeh.info%2Fdepulse&label=Page%20View&countColor=%23263759&labelStyle=none)](https://visitorbadge.io/status?path=https%3A%2F%2Fdepaul.v-alizadeh.info%2Fdepulse) ''') if __name__ == "__main__": app()