From 07391874bcaebf09e1604f994d81128ddaf06d20 Mon Sep 17 00:00:00 2001 From: pavitgopal Date: Wed, 30 Oct 2024 23:44:47 -0500 Subject: [PATCH 1/8] test edits --- app/controllers/room_bookings_controller.rb | 61 +++++++++++++++++---- app/views/room_bookings/index.html.erb | 27 ++++----- config/routes.rb | 6 ++ 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/app/controllers/room_bookings_controller.rb b/app/controllers/room_bookings_controller.rb index 2fadc82..49c5641 100644 --- a/app/controllers/room_bookings_controller.rb +++ b/app/controllers/room_bookings_controller.rb @@ -1,23 +1,64 @@ -# frozen_string_literal: true - # Room Bookings Controller class RoomBookingsController < ApplicationController + before_action :set_schedule + def index - schedule_id = params[:schedule_id] - @schedule = Schedule.find(params[:schedule_id]) @rooms = @schedule.rooms.where(is_active: true).where.not(building_code: 'ONLINE') @tabs = TimeSlot.distinct.pluck(:day) @active_tab = params[:active_tab] || @tabs[0] - @time_slots = TimeSlot.where(time_slots: { day: @active_tab }).to_a - @time_slots.sort_by! { |ts| Time.parse(ts.start_time) } + @time_slots = TimeSlot.where(day: @active_tab).order(:start_time) - # Fetch room bookings only for the specified schedule @room_bookings = RoomBooking.joins(:room, :time_slot) - .where(rooms: { schedule_id: schedule_id }, time_slots: { day: @active_tab }) - - # Organize room bookings in a hash with room_id and time_slot_id as keys + .where(rooms: { schedule_id: @schedule.id }, time_slots: { day: @active_tab }) @bookings_matrix = @room_bookings.each_with_object({}) do |booking, hash| hash[[booking.room_id, booking.time_slot_id]] = booking end end + + # RoomBookingsController +# RoomBookingsController +# RoomBookingsController +def toggle_availability + room_booking = RoomBooking.find_or_initialize_by(room_id: params[:room_id], time_slot_id: params[:time_slot_id]) + new_status = !room_booking.is_available + room_booking.update(is_available: new_status) + + # Calculate relevant days based on the current active tab + relevant_days = calculate_relevant_days(params[:active_tab]) + + # Manually construct the overlap conditions since SQLite lacks the OVERLAPS function + related_time_slots = TimeSlot.where(day: relevant_days) + .where("start_time < ? AND end_time > ?", + room_booking.time_slot.end_time, + room_booking.time_slot.start_time) + + # Update RoomBookings to reflect the new status across relevant overlapping time slots and days + RoomBooking.where(room_id: params[:room_id], time_slot: related_time_slots) + .update_all(is_available: new_status) + + # Redirect back to the room bookings page with the active tab + redirect_to schedule_room_bookings_path(@schedule, active_tab: params[:active_tab]) +end + + + + + private + + def set_schedule + @schedule = Schedule.find(params[:schedule_id]) + end + + def calculate_relevant_days(current_tab) + case current_tab + when 'MWF' + %w[MWF MW F] + when 'MW' + %w[MWF MW] + when 'F' + %w[MWF F] + else + [current_tab] # Only affects TR or any isolated day + end + end end diff --git a/app/views/room_bookings/index.html.erb b/app/views/room_bookings/index.html.erb index 7b7b254..e25c6e6 100644 --- a/app/views/room_bookings/index.html.erb +++ b/app/views/room_bookings/index.html.erb @@ -33,32 +33,29 @@ Times \ Rooms <% @rooms.each do |room| %> - <%= room.building_code %> <%= room.room_number %> - + <%= room.building_code %> <%= room.room_number %> <% end %> - <% @time_slots.each do |time_slot| %> + <% @time_slots.each do |time_slot| %> - <%= time_slot.start_time %> - <%= time_slot.end_time %> - - <% @rooms.each do |room| %> + <%= time_slot.start_time %> - <%= time_slot.end_time %> + <% @rooms.each do |room| %> <% booking = @bookings_matrix[[room.id, time_slot.id]] %> - - <% if booking %> - <%= booking.is_available ? 'Available' : 'Booked' %> | - <%= booking.is_lab ? 'Lab' : 'Lecture' %> - <% else %> - <% end %> - + <% if booking && !booking.is_available %> + <%= button_to "U", toggle_availability_room_bookings_path, method: :post, params: { room_id: room.id, time_slot_id: time_slot.id, active_tab: @active_tab, schedule_id: @schedule.id }, class: "btn btn-sm btn-success" %> + <% else %> + <%= button_to "BL", toggle_availability_room_bookings_path, method: :post, params: { room_id: room.id, time_slot_id: time_slot.id, active_tab: @active_tab, schedule_id: @schedule.id }, class: "btn btn-sm btn-danger" %> <% end %> - + <% end %> + + <% end %> <% else %>

No rooms added to this schedule, click on View Data to Add Rooms!

-<% end %> \ No newline at end of file +<% end %> diff --git a/config/routes.rb b/config/routes.rb index c5aa2a4..4a85dd4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,6 +41,12 @@ get '/time_slots', to: 'time_slots#index' resources :room_bookings, only: [:index] + post 'room_bookings/toggle_availability', to: 'room_bookings#toggle_availability' + + end + + resources :room_bookings do + post 'toggle_availability', on: :collection end # Show Time Slot View From 2433bb69ec7455d48785f5e2b7bbe25d49cfeec1 Mon Sep 17 00:00:00 2001 From: pavitgopal Date: Wed, 30 Oct 2024 23:47:08 -0500 Subject: [PATCH 2/8] initial commit --- app/models/instructor_preference.rb | 7 ++ ...026204612_create_instructor_preferences.rb | 14 ++++ ...2021_add_max_course_load_to_instructors.rb | 8 ++ ...ructor_preferences_add_course_reference.rb | 9 +++ db/teaching_preferences_anonymized.csv | 77 +++++++++++++++++++ features/step_definitions/time_slots_steps.rb | 33 ++++++++ features/time_slots.feature | 38 +++++++++ test/factories/instructor_preferences.rb | 1 + test/models/instructor_preference_test.rb | 9 +++ 9 files changed, 196 insertions(+) create mode 100644 app/models/instructor_preference.rb create mode 100644 db/migrate/20241026204612_create_instructor_preferences.rb create mode 100644 db/migrate/20241027152021_add_max_course_load_to_instructors.rb create mode 100644 db/migrate/20241029040851_change_instructor_preferences_add_course_reference.rb create mode 100644 db/teaching_preferences_anonymized.csv create mode 100644 features/step_definitions/time_slots_steps.rb create mode 100644 features/time_slots.feature create mode 100644 test/factories/instructor_preferences.rb create mode 100644 test/models/instructor_preference_test.rb diff --git a/app/models/instructor_preference.rb b/app/models/instructor_preference.rb new file mode 100644 index 0000000..fde0a48 --- /dev/null +++ b/app/models/instructor_preference.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Model for Instructor preferences +class InstructorPreference < ApplicationRecord + belongs_to :instructor + belongs_to :course +end diff --git a/db/migrate/20241026204612_create_instructor_preferences.rb b/db/migrate/20241026204612_create_instructor_preferences.rb new file mode 100644 index 0000000..11d9968 --- /dev/null +++ b/db/migrate/20241026204612_create_instructor_preferences.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Migration for creating instructor preferences +class CreateInstructorPreferences < ActiveRecord::Migration[7.2] + def change + create_table :instructor_preferences do |t| + t.references :instructor, null: false, foreign_key: true + t.string :course + t.integer :preference_level + + t.timestamps + end + end +end diff --git a/db/migrate/20241027152021_add_max_course_load_to_instructors.rb b/db/migrate/20241027152021_add_max_course_load_to_instructors.rb new file mode 100644 index 0000000..0ccf5a2 --- /dev/null +++ b/db/migrate/20241027152021_add_max_course_load_to_instructors.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Migration for adding a column to Instructor Preferences +class AddMaxCourseLoadToInstructors < ActiveRecord::Migration[7.2] + def change + add_column :instructors, :max_course_load, :integer + end +end diff --git a/db/migrate/20241029040851_change_instructor_preferences_add_course_reference.rb b/db/migrate/20241029040851_change_instructor_preferences_add_course_reference.rb new file mode 100644 index 0000000..4f6a5f8 --- /dev/null +++ b/db/migrate/20241029040851_change_instructor_preferences_add_course_reference.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# Add the foreign key to courses in instructor_preferences and remove the string column +class ChangeInstructorPreferencesAddCourseReference < ActiveRecord::Migration[7.2] + def change + remove_column :instructor_preferences, :course, :string + add_reference :instructor_preferences, :course, null: false, foreign_key: true + end +end diff --git a/db/teaching_preferences_anonymized.csv b/db/teaching_preferences_anonymized.csv new file mode 100644 index 0000000..1648bc6 --- /dev/null +++ b/db/teaching_preferences_anonymized.csv @@ -0,0 +1,77 @@ +IDNO,Q20_1,Q20_2,Q20_3,Q20_4,Q20_5,Q20_6,Q20_7,Q20_8,Q20_9,Q20_10,Q20_11,Q20_12,Q20_13,Q20_14,Q20_15,Q20_16,Q20_17,Q20_18,Q20_19,Q20_20,Q20_21,Q20_22,Q20_23,Q20_24,Q20_25,Q20_26,Q20_27,Q20_28,Q20_29,Q20_30,Q20_31,Q20_32,Q20_33,Q20_34,Q20_35,Q20_36,Q20_37,Q20_38,Q20_39,Q20_40,Q20_41,Q20_42,Q20_43,Q20_44,Q20_45,Q20_46,Q20_47,Q20_48,Q20_49,Q20_50,Q20_51,Q20_52,Q20_53,Q20_54,Q20_55,Q20_56,Q20_57,Q20_58,Q5_1,Q5_2,Q5_3,Q5_4,Q5_5,Q5_6,Q5_7,Q5_8,Q5_9,Q5_10,Q5_11,Q5_12,Q5_65,Q5_13,Q5_14,Q5_15,Q5_16,Q5_17,Q5_18,Q5_19,Q5_20,Q5_21,Q5_22,Q5_23,Q5_24,Q5_25,Q5_90,Q5_26,Q5_27,Q5_28,Q5_29,Q5_30,Q5_66,Q5_32,Q5_33,Q5_87,Q5_34,Q5_35,Q5_36,Q5_37,Q5_38,Q5_39,Q5_40,Q5_67,Q5_67,Q5_41,Q5_42,Q5_43,Q5_44,Q5_45,Q5_46,Q5_47,Q5_48,Q5_49,Q5_50,Q5_51,Q5_52,Q5_53,Q5_54,Q5_55,Q5_56,Q5_57,Q5_58,Q5_59,Q5_67,Q5_61,Q5_68,Q5_69,Q5_72,Q5_62,Q5_63,Q5_88,Q5_77,Q5_71,Q5_70,Q5_79,Q5_75,Q5_81,Q5_74,Q5_80,Q5_76,Q5_82,Q5_83,Q5_84,Q5_85,Q5_86,Q5_89,Q7,Q22,Q21,Q12,Q13,Q17,Q18 +anonimized ID,Please rate your capability/interest in teaching each undergraduate course. - 110/707 - Programming I (Python),Please rate your capability/interest in teaching each undergraduate course. - 111/708 - Introduction to Computer Science Concepts and Programming (Java),Please rate your capability/interest in teaching each undergraduate course. - 121/120/709 - Introduction to Program Design and Concepts (C++),Please rate your capability/interest in teaching each undergraduate course. - 181 - Introduction to Computing (intro seminar; half teaching credit),Please rate your capability/interest in teaching each undergraduate course. - 201 - Fundamentals of Cybersecurity,Please rate your capability/interest in teaching each undergraduate course. - 206 - Structured Programming in C,Please rate your capability/interest in teaching each undergraduate course. - 221 - Data Structures and Algorithms,Please rate your capability/interest in teaching each undergraduate course. - 222 - Discrete Structures for Computing,Please rate your capability/interest in teaching each undergraduate course. - 305 - Computational Data Science (rarely taught by us),Please rate your capability/interest in teaching each undergraduate course. - 310 - Database Systems,Please rate your capability/interest in teaching each undergraduate course. - 312 - Computer Organization,Please rate your capability/interest in teaching each undergraduate course. - 313 - Introduction to Computer Systems,Please rate your capability/interest in teaching each undergraduate course. - 314 - Programming Languages,Please rate your capability/interest in teaching each undergraduate course. - 320 - Principles of Data Science,Please rate your capability/interest in teaching each undergraduate course. - 315/331 - Foundations of Software Engineering,Please rate your capability/interest in teaching each undergraduate course. - 350 - Computer Architecture and Design,Please rate your capability/interest in teaching each undergraduate course. - 402/702 - Law & Policy in Cybersecurity,Please rate your capability/interest in teaching each undergraduate course. - 410 - Operating Systems,Please rate your capability/interest in teaching each undergraduate course. - 411 - Design and Analysis of Algoirthms,Please rate your capability/interest in teaching each undergraduate course. - 412 - Cloud Computing,Please rate your capability/interest in teaching each undergraduate course. - 413 - Software Security,Please rate your capability/interest in teaching each undergraduate course. - 416 - Introduction to Hardware Design Verification,Please rate your capability/interest in teaching each undergraduate course. - 420 - Artificial Intelligence,Please rate your capability/interest in teaching each undergraduate course. - 421 - Machine Learning,Please rate your capability/interest in teaching each undergraduate course. - 430 - Problem Solving Programming Strategies,Please rate your capability/interest in teaching each undergraduate course. - 431 - Software Engineering,Please rate your capability/interest in teaching each undergraduate course. - 432 - Accessible Computing,Please rate your capability/interest in teaching each undergraduate course. - 433 - Formal Languages and Automata,Please rate your capability/interest in teaching each undergraduate course. - 434 - Compiler Design,Please rate your capability/interest in teaching each undergraduate course. - 435 - Parallel Computing,Please rate your capability/interest in teaching each undergraduate course. - 436 - Human Computer Interaction,Please rate your capability/interest in teaching each undergraduate course. - 438 - Distributed Objects Programming,Please rate your capability/interest in teaching each undergraduate course. - 439 - Data Analytics for Cybersecurity,Please rate your capability/interest in teaching each undergraduate course. - 440 - Quantum Algorithms,Please rate your capability/interest in teaching each undergraduate course. - 441 - Computer Graphics,Please rate your capability/interest in teaching each undergraduate course. - 442 - Scientific Programming,Please rate your capability/interest in teaching each undergraduate course. - 443 - Game Development,Please rate your capability/interest in teaching each undergraduate course. - 444 - Structures of Interactive Information,Please rate your capability/interest in teaching each undergraduate course. - 445 - Computers and New Media,Please rate your capability/interest in teaching each undergraduate course. - 446 - Virtual Reality,Please rate your capability/interest in teaching each undergraduate course. - 447 - Data Visualization,Please rate your capability/interest in teaching each undergraduate course. - 448 - Computational Photography,Please rate your capability/interest in teaching each undergraduate course. - 449 - Applied Cryptography,Please rate your capability/interest in teaching each undergraduate course. - 450 - Computer Animation,Please rate your capability/interest in teaching each undergraduate course. - 451 - Software Reverse Engineering,Please rate your capability/interest in teaching each undergraduate course. - 452 - Robotics and Spatial Intelligence,Please rate your capability/interest in teaching each undergraduate course. - 456 - RealTime Computing,Please rate your capability/interest in teaching each undergraduate course. - 461 - Embedded Systems for Medical Applications,Please rate your capability/interest in teaching each undergraduate course. - 462 - Microcomputer Systems,Please rate your capability/interest in teaching each undergraduate course. - 463 - Networking and Distributed Systems,Please rate your capability/interest in teaching each undergraduate course. - 464 - Wireless and Mobile Systems,Please rate your capability/interest in teaching each undergraduate course. - 465 - Computer and Network Security,Please rate your capability/interest in teaching each undergraduate course. - 469 - Advanced Computer Architecture,Please rate your capability/interest in teaching each undergraduate course. - 470- Information Storage and Retrieval,Please rate your capability/interest in teaching each undergraduate course. - 477 - Cybersecurity Risk Analysis,Please rate your capability/interest in teaching each undergraduate course. - 481 - Seminar (half teaching credit),Please rate your capability/interest in teaching each undergraduate course. - 482 - Senior Capstone Design (CS capstone),Please rate your capability/interest in teaching each undergraduate course. - 483 - Computer Systems Design (CE capstone),Please rate your capability/interest in teaching each graduate course. - 601 - Programming with C and Java (service course),"Please rate your capability/interest in teaching each graduate course. - 602 - Object-Oriented Programming, Development, and Software Engineering (service course)",Please rate your capability/interest in teaching each graduate course. - 603 - Database Analysis (service course often stacked with 310),Please rate your capability/interest in teaching each graduate course. - 604 - Programming Languages,Please rate your capability/interest in teaching each graduate course. - 605 - Compiler Design,Please rate your capability/interest in teaching each graduate course. - 606 - Software Engineering,Please rate your capability/interest in teaching each graduate course. - 608 - Database Systems,Please rate your capability/interest in teaching each graduate course. - 610 - Hypertext/Hypermedia Systems,Please rate your capability/interest in teaching each graduate course. - 611 - Operating Systems and Applications (service course often stacked with 410),Please rate your capability/interest in teaching each graduate course. - 612 - Applied Networks and Distributed Processing (service course often stacked with 463),Please rate your capability/interest in teaching each graduate course. - 613 - Operating Systems,Please rate your capability/interest in teaching each graduate course. - 614 - Computer Architecture,Please rate your capability/interest in teaching each graduate course. - 616 - Introduction to Hardware Design Verification,Please rate your capability/interest in teaching each graduate course. - 617 - CoDesign of Embedded Systems (CODES),Please rate your capability/interest in teaching each graduate course. - 619 - Networks and Distributed Computing,Please rate your capability/interest in teaching each graduate course. - 620 - Computational Geometry,"Please rate your capability/interest in teaching each graduate course. - 621 - Language, Library, and Program Design Using C++",Please rate your capability/interest in teaching each graduate course. - 622 - Generic Programming,Please rate your capability/interest in teaching each graduate course. - 624 - Sketch Recognition,Please rate your capability/interest in teaching each graduate course. - 625 - Artificial Intelligence,Please rate your capability/interest in teaching each graduate course. - 626 - Parallel Algorithm Design and Analysis,Please rate your capability/interest in teaching each graduate course. - 627 - Theory of Computability,Please rate your capability/interest in teaching each graduate course. - 628 - Computational Biology,Please rate your capability/interest in teaching each graduate course. - 629 - Analysis of Algorithms,Please rate your capability/interest in teaching each graduate course. - 630 - Speech Processing,Please rate your capability/interest in teaching each graduate course. - 631 - Intelligent Agents,Please rate your capability/interest in teaching each graduate course. - 632 - Accessible Computing,Please rate your capability/interest in teaching each graduate course. - 633 - Machine Learning,Please rate your capability/interest in teaching each graduate course. - 634 - Intelligent User Interfaces,Please rate your capability/interest in teaching each graduate course. - 635 - AI Robotics,Please rate your capability/interest in teaching each graduate course. - 636 - Deep Learning,Please rate your capability/interest in teaching each graduate course. - 637 - Complexity Theory,Please rate your capability/interest in teaching each graduate course. - 638 - Natural Language Processing: Foundations and Techniques,Please rate your capability/interest in teaching each graduate course. - 640 - Quantum Algorithms,Please rate your capability/interest in teaching each graduate course. - 641 - Computer Graphics,Please rate your capability/interest in teaching each graduate course. - 642 - Deep Reinforcement Learning,Please rate your capability/interest in teaching each graduate course. - 643 - Seminar in Intelligent Systems and Robotics,Please rate your capability/interest in teaching each graduate course. - 644 - Cortical Networks,Please rate your capability/interest in teaching each graduate course. - 645 - Geometric Modeling,Please rate your capability/interest in teaching each graduate course. - 646 - The Digital Image (usually taught by VIZA),Please rate your capability/interest in teaching each graduate course. - 647 - Image Synthesis (usually taught by VIZA),Please rate your capability/interest in teaching each graduate course. - 648 - Computer Aided Sculpting (usually taught by VIZA),Please rate your capability/interest in teaching each graduate course. - 649 - Physically-Based Modeling,Please rate your capability/interest in teaching each graduate course. - 650 - Virtual Reality,Please rate your capability/interest in teaching each graduate course. - 652 - Software Reverse Engineering,Please rate your capability/interest in teaching each graduate course. - 653 - Computer Methods in Applied Sciences,Please rate your capability/interest in teaching each graduate course. - 654 - Supercomputing,Please rate your capability/interest in teaching each graduate course. - 655 - Human-Centered Computing,Please rate your capability/interest in teaching each graduate course. - 656 - Computers and New Media,Please rate your capability/interest in teaching each graduate course. - 657 - High Performance Computing for Earth Science and Petroleum Engineering (jointly taught with PETE),Please rate your capability/interest in teaching each graduate course. - 658 - Randomized Algorithms,Please rate your capability/interest in teaching each graduate course. - 659 - Parallel/Distributed Numerical Algorithms and Applications,Please rate your capability/interest in teaching each graduate course. - 660 - Computational Linear Algebra,Please rate your capability/interest in teaching each graduate course. - 661 - Integrated Systems Design Automation,Please rate your capability/interest in teaching each graduate course. - 662 - Distributed Processing Systems,Please rate your capability/interest in teaching each graduate course. - 663 - Real-Time Systems,Please rate your capability/interest in teaching each graduate course. - 664 - Wireless and Mobile Systems,Please rate your capability/interest in teaching each graduate course. - 665 - Advanced Networking and Security,Please rate your capability/interest in teaching each graduate course. - 666 - Pattern Analysis,Please rate your capability/interest in teaching each graduate course. - 667 - Seminar in Human-Centered Computing,Please rate your capability/interest in teaching each graduate course. - 668 - Distributed Algorithms and Systems,Please rate your capability/interest in teaching each graduate course. - 669 - Computational Optimization,Please rate your capability/interest in teaching each graduate course. - 670 - Information Storage and Retrieval,Please rate your capability/interest in teaching each graduate course. - 671 - Computer-Human Interaction,Please rate your capability/interest in teaching each graduate course. - 672 - Computer Supported Collaborative Work,Please rate your capability/interest in teaching each graduate course. - 675 - Digital Libraries,Please rate your capability/interest in teaching each graduate course. - 676 - Data Mining and Analysis,Please rate your capability/interest in teaching each graduate course. - 678 - Distributed Ssytems and Cloud Computing,Please rate your capability/interest in teaching each graduate course. - 679 - Data Visualization,Please rate your capability/interest in teaching each graduate course. - 680 - Testing and Diagnosis of Digital Systems,Please rate your capability/interest in teaching each graduate course. - 681 - Seminar,Please rate your capability/interest in teaching each graduate course. - 682 - Introduction to Doctoral Studies,Please rate your capability/interest in teaching each graduate course. - 701 - Foundations of Cybersecurity,Please rate your capability/interest in teaching each graduate course. - 702 - Law and Policy in Cybersecurity,Please rate your capability/interest in teaching each graduate course. - 703 - Cybersecurity Risk,Please rate your capability/interest in teaching each graduate course. - 704 - Data Analytics for Cybersecurity,Please rate your capability/interest in teaching each graduate course. - 705 - Intro to Computing Systems,Please rate your capability/interest in teaching each graduate course. - 710 - Fundamentals of Software Analysis,Please rate your capability/interest in teaching each graduate course. - 711 - Intro to Modern Cryptography,Please rate your capability/interest in teaching each graduate course. - 712 - Digital Forensic Engineering,Please rate your capability/interest in teaching each graduate course. - 713 - Software Security,Please rate your capability/interest in teaching each graduate course. - 714 - Advanced Hardware Design Functional Verification,Please rate your capability/interest in teaching each graduate course. - 735 - Parallel Computing,Please rate your capability/interest in teaching each graduate course. - 748 - Computational Photography,Please rate your capability/interest in teaching each graduate course. - 749 - Applied Cryptography,Please rate your capability/interest in teaching each graduate course. - 752 - Robotics and Spatial Intelligence,Please rate your capability/interest in teaching each graduate course. - 753 - Computer Vision and Robot Perception,Do you plan on buying out of:,Number of courses to assign,"Is there anything else we should be aware of regarding your teaching load (special course reduction, ...)",Teaching before 9:00 am.,Teaching after 3:00 pm.,"Time Preferences +- We assume that everybody likes to teach late mornings or early/mid afternoons. +- Click sparingly! Your preference weight budget will be spread across your clicked preferences.",When teaching multiple classes... +,"{""ImportId"":""QID20_1""}","{""ImportId"":""QID20_2""}","{""ImportId"":""QID20_3""}","{""ImportId"":""QID20_4""}","{""ImportId"":""QID20_54""}","{""ImportId"":""QID20_5""}","{""ImportId"":""QID20_6""}","{""ImportId"":""QID20_7""}","{""ImportId"":""QID20_61""}","{""ImportId"":""QID20_8""}","{""ImportId"":""QID20_9""}","{""ImportId"":""QID20_10""}","{""ImportId"":""QID20_11""}","{""ImportId"":""QID20_47""}","{""ImportId"":""QID20_12""}","{""ImportId"":""QID20_13""}","{""ImportId"":""QID20_48""}","{""ImportId"":""QID20_14""}","{""ImportId"":""QID20_15""}","{""ImportId"":""QID20_42""}","{""ImportId"":""QID20_53""}","{""ImportId"":""QID20_41""}","{""ImportId"":""QID20_16""}","{""ImportId"":""QID20_49""}","{""ImportId"":""QID20_50""}","{""ImportId"":""QID20_17""}","{""ImportId"":""QID20_55""}","{""ImportId"":""QID20_18""}","{""ImportId"":""QID20_19""}","{""ImportId"":""QID20_20""}","{""ImportId"":""QID20_21""}","{""ImportId"":""QID20_22""}","{""ImportId"":""QID20_60""}","{""ImportId"":""QID20_23""}","{""ImportId"":""QID20_24""}","{""ImportId"":""QID20_25""}","{""ImportId"":""QID20_26""}","{""ImportId"":""QID20_27""}","{""ImportId"":""QID20_28""}","{""ImportId"":""QID20_43""}","{""ImportId"":""QID20_44""}","{""ImportId"":""QID20_56""}","{""ImportId"":""QID20_57""}","{""ImportId"":""QID20_58""}","{""ImportId"":""QID20_29""}","{""ImportId"":""QID20_30""}","{""ImportId"":""QID20_31""}","{""ImportId"":""QID20_45""}","{""ImportId"":""QID20_32""}","{""ImportId"":""QID20_33""}","{""ImportId"":""QID20_34""}","{""ImportId"":""QID20_35""}","{""ImportId"":""QID20_36""}","{""ImportId"":""QID20_37""}","{""ImportId"":""QID20_52""}","{""ImportId"":""QID20_38""}","{""ImportId"":""QID20_39""}","{""ImportId"":""QID20_40""}","{""ImportId"":""QID5_1""}","{""ImportId"":""QID5_2""}","{""ImportId"":""QID5_3""}","{""ImportId"":""QID5_4""}","{""ImportId"":""QID5_5""}","{""ImportId"":""QID5_6""}","{""ImportId"":""QID5_7""}","{""ImportId"":""QID5_8""}","{""ImportId"":""QID5_9""}","{""ImportId"":""QID5_10""}","{""ImportId"":""QID5_11""}","{""ImportId"":""QID5_12""}","{""ImportId"":""QID5_13""}","{""ImportId"":""QID5_14""}","{""ImportId"":""QID5_15""}","{""ImportId"":""QID5_16""}","{""ImportId"":""QID5_17""}","{""ImportId"":""QID5_18""}","{""ImportId"":""QID5_19""}","{""ImportId"":""QID5_20""}","{""ImportId"":""QID5_21""}","{""ImportId"":""QID5_22""}","{""ImportId"":""QID5_23""}","{""ImportId"":""QID5_24""}","{""ImportId"":""QID5_25""}","{""ImportId"":""QID5_26""}","{""ImportId"":""QID5_90""}","{""ImportId"":""QID5_27""}","{""ImportId"":""QID5_28""}","{""ImportId"":""QID5_29""}","{""ImportId"":""QID5_30""}","{""ImportId"":""QID5_31""}","{""ImportId"":""QID5_32""}","{""ImportId"":""QID5_34""}","{""ImportId"":""QID5_35""}","{""ImportId"":""QID5_87""}","{""ImportId"":""QID5_36""}","{""ImportId"":""QID5_37""}","{""ImportId"":""QID5_38""}","{""ImportId"":""QID5_39""}","{""ImportId"":""QID5_40""}","{""ImportId"":""QID5_41""}","{""ImportId"":""QID5_42""}","{""ImportId"":""QID5_67""}","{""ImportId"":""QID5_43""}","{""ImportId"":""QID5_44""}","{""ImportId"":""QID5_45""}","{""ImportId"":""QID5_46""}","{""ImportId"":""QID5_47""}","{""ImportId"":""QID5_48""}","{""ImportId"":""QID5_49""}","{""ImportId"":""QID5_50""}","{""ImportId"":""QID5_51""}","{""ImportId"":""QID5_52""}","{""ImportId"":""QID5_53""}","{""ImportId"":""QID5_54""}","{""ImportId"":""QID5_55""}","{""ImportId"":""QID5_56""}","{""ImportId"":""QID5_57""}","{""ImportId"":""QID5_58""}","{""ImportId"":""QID5_59""}","{""ImportId"":""QID5_60""}","{""ImportId"":""QID5_61""}","{""ImportId"":""QID5_62""}","{""ImportId"":""QID5_63""}","{""ImportId"":""QID5_64""}","{""ImportId"":""QID5_68""}","{""ImportId"":""QID5_69""}","{""ImportId"":""QID5_72""}","{""ImportId"":""QID5_65""}","{""ImportId"":""QID5_66""}","{""ImportId"":""QID5_88""}","{""ImportId"":""QID5_77""}","{""ImportId"":""QID5_71""}","{""ImportId"":""QID5_70""}","{""ImportId"":""QID5_79""}","{""ImportId"":""QID5_75""}","{""ImportId"":""QID5_81""}","{""ImportId"":""QID5_74""}","{""ImportId"":""QID5_80""}","{""ImportId"":""QID5_76""}","{""ImportId"":""QID5_82""}","{""ImportId"":""QID5_83""}","{""ImportId"":""QID5_84""}","{""ImportId"":""QID5_85""}","{""ImportId"":""QID5_86""}","{""ImportId"":""QID5_89""}","{""ImportId"":""QID7""}",,"{""ImportId"":""QID21_TEXT""}","{""ImportId"":""QID12""}","{""ImportId"":""QID13""}","{""ImportId"":""QID17""}","{""ImportId"":""QID18""}" +2755728,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,2,2,2,2,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,2,2,5,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,1,2,1,2,1,1,2,2,2,1,2,2,2,2,2,2,1,2,2,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,2,1,2,2,1,1,1,1,1,2,2,1,1,2,2,2,2,2,2,1,1,2,1,2,1,1,1,2,1,1,2,1,,,,, +672598,2,2,2,2,1,2,2,2,2,1,2,2,1,5,2,2,1,1,2,1,1,1,2,4,2,2,2,1,1,1,2,1,1,1,1,1,1,2,1,1,3,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,3,2,1,3,1,2,3,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,4,2,1,1,2,2,1,1,2,1,2,1,5,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,,,,,1 +670246,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,2,1,1,1,2,1,1,2,2,1,1,1,3,1,1,1,1,1,1,1,5,1,4,1,1,1,1,1,1,1,1,1,1,1,1,2,1,3,2,2,1,1,1,1,1,2,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,5,1,1,1,1,1,1,1,1,1,1,2,1,1,2,3,5,3,1,1,4,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,,1,,3,2 +2476413,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,3, +2332341,3,3,2,2,1,1,3,1,2,1,1,1,2,3,2,1,1,1,3,1,1,1,4,4,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,3,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,2,1,1,1,3,1,4,1,3,3,2,1,1,1,5,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,,,,3,2 +1295464,2,2,3,2,1,3,3,2,2,2,2,2,3,2,2,3,1,2,3,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,2,2,2,2,2,1,3,3,1,1,1,2,1,3,5,1,1,1,2,2,1,1,2,1,2,1,3,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,,1,,1,2 +1152574,3,3,4,3,2,3,4,4,2,2,2,2,2,2,2,2,1,1,4,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,,,1, +2036178,2,2,2,2,2,2,3,2,2,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,2,1,1,1,1,1,1,1,5,1,2,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,,1,,3, +48906,3,3,2,2,3,2,2,2,2,2,2,2,5,2,4,1,3,1,1,5,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,2,3,3,1,3,1,2,1,2,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,,,2,1 +676911,2,2,2,2,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,,,3,1 +749735,4,1,1,1,1,4,2,3,1,1,4,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,1,"1,3", +2938931,3,3,2,3,3,3,3,4,2,3,2,4,3,2,2,2,1,3,1,4,3,1,2,1,2,3,1,2,2,2,1,4,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,4,1,4,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,1,,,"2,3" +674610,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,,1,1 +672529,3,3,3,3,3,3,5,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,,,3, +424079,2,2,4,3,2,2,3,3,2,2,2,2,2,2,3,2,1,1,1,1,1,1,1,1,1,2,5,1,1,1,5,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,2,2,2,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,,,2,"1,3" +2202367,3,3,2,2,1,3,3,2,3,2,3,3,2,4,2,2,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,4,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,,,,2,1 +670859,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,1,1,4,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,3,1,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,,1,,1,1 +713579,2,2,3,2,1,2,4,4,2,3,2,2,4,2,2,2,1,1,4,1,1,1,5,4,2,2,2,4,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,3,3,3,2,2,3,2,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,5,1,4,1,4,1,4,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,3,1,1,,,,,1 +617243,2,2,2,2,2,2,4,4,2,3,2,2,2,2,2,2,1,2,4,1,1,1,1,1,1,1,1,4,4,2,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,3,1,3,1,1,1,1,1,1,1,1,5,1,1,1,1,3,5,2,4,1,1,1,1,1,1,1,4,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,2,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,,,1,1 +2472710,3,3,3,3,3,3,4,5,2,2,2,4,3,2,2,2,2,3,3,2,2,1,1,1,1,1,1,3,3,1,1,1,4,1,1,1,1,1,1,1,1,1,3,1,5,1,1,1,1,1,1,5,1,1,3,3,2,2,2,2,2,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,2,1,1,4,1,1,1,3,1,1,1,1,2,1,1,1,2,,,,3, +939540,3,3,3,3,3,3,3,3,2,2,4,4,2,2,2,4,1,4,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,1,,,1 +1636277,3,3,3,4,3,3,4,3,2,2,4,3,2,1,2,4,1,2,2,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,1,3,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,4,,,,1,2 +667061,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,0,"I am buying out, so I am not planning to teach anything in Spring 2024",,,, +233153,2,2,1,2,2,1,4,4,3,1,1,1,1,3,2,2,1,1,4,1,1,1,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,3,3,4,1,4,1,1,1,2,1,1,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,3,3,1,1,1,1,1,1,1,3,1,1,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,1,2 +2332340,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,I will be on fac developmental leave for fall 24 and spring 25,,,, +676913,3,3,3,3,3,3,3,4,2,2,2,2,2,2,2,2,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,1,,1 +487444,2,2,2,2,2,2,3,5,2,2,2,2,5,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,1,,"1,3",1 +2623488,2,3,3,2,1,2,3,3,1,2,2,3,3,1,2,1,1,2,1,2,1,1,1,1,1,2,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,2,2,2,1,2,4,2,2,1,2,1,2,1,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,,1,,1,3 +118480,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,3,3,1,2,3,1,2,2,1,2,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,4,3,2,2,2,2,1,1,1,1,1,1,3,2,3,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,4,3,4,1,1,2,3,4,3,1,1,1,2,1,1,3,0,I currently plan to teach one course in Fall 24 and buyout in Spring 25 BUT I will work to support the department. ,,,1,1 +2944519,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,4,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,1,1, +673660,2,2,2,2,3,2,2,2,2,2,2,3,2,2,2,2,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,3,1,4,1,1,1,1,1,1,5,1,1,3,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,3,1,4,1,1,4,3,1,3,4,4,1,1,1,3,1,1,2,1,,,,3,1 +2957849,2,2,2,3,5,2,2,2,2,2,3,3,2,2,2,2,2,4,1,2,5,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,3,1,5,1,1,1,1,1,1,5,1,1,4,3,2,2,1,1,1,1,1,1,1,1,1,1,4,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,3,5,1,2,1,5,5,1,1,1,1,1,1,1,1,,,,3,1 +2938933,3,3,3,3,1,3,3,3,2,1,2,2,2,2,2,2,1,1,1,1,1,1,3,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,4,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,2,1,2,1,1,1,2,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,3,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,2,0,Buyout plan is tentative,1,,, +555614,3,3,3,3,3,3,5,3,2,2,4,4,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,I only teach in Spring.,,1,"2,3", +2938934,3,3,3,3,2,3,5,4,2,2,2,2,2,2,2,2,1,1,4,1,1,1,1,3,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,4,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,3,1 +676785,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,,1,1 +617634,2,2,2,2,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,3,1,1,3,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,,1,1,"1,3", +305257,3,2,2,4,1,2,2,1,1,5,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,5,1,1,2,4,1,1,4,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,1,1 +2332343,3,3,3,3,3,3,3,3,2,2,4,2,2,2,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,,,,3,1 +675964,3,3,3,3,3,3,3,3,2,2,2,2,2,4,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,4,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,,,1,,1 +64785,4,4,4,2,2,4,4,4,2,4,2,3,5,2,4,2,2,2,4,4,4,1,3,2,3,4,2,4,3,2,2,2,2,1,1,2,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,3,1,1,2,2,5,4,2,2,2,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,,1,,"2,3",1 +670154,2,2,2,2,1,2,2,4,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,, +2755727,2,2,2,2,2,2,3,3,3,2,2,2,2,3,2,2,1,1,4,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,4,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,2,1,3,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,3, +1740388,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,,1,1,"1,3",1 +100615,3,3,3,2,1,3,4,3,1,2,2,2,2,1,4,2,1,1,4,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,2,4,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,I have a 3 course reduction per year for advising (typically reduction by 2 in the fall and by 1 in the spring -- meaning teaching 1 course in the fall and 2 courses in the spring). ,,1,3,"1,3" +2708588,2,2,2,2,2,1,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,1,1,1,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,,1,,"1,2", +3103405,4,4,4,3,3,4,4,3,3,4,4,4,4,2,4,4,1,4,4,1,1,1,1,1,1,4,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,4,4,4,4,1,4,4,1,1,1,1,4,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,,,,3,1 +3178380,3,3,3,3,1,3,3,2,2,2,3,3,3,3,3,3,2,3,2,1,2,1,3,3,3,3,3,2,1,3,3,3,3,1,3,2,3,3,3,3,3,3,1,3,3,1,1,1,1,1,1,2,3,3,1,3,3,2,3,3,3,3,1,3,3,3,3,1,3,3,1,1,1,2,1,1,3,3,2,2,1,2,3,3,3,3,4,3,3,1,3,1,3,3,3,1,1,1,1,1,3,3,1,1,1,4,3,1,1,1,1,1,1,1,1,1,1,4,1,1,1,4,1,1,1,1,4,1,4,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,"It's my first semester, and I might teach the special topics on Human-AI Interaction.",1,,1,3 +2200830,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,3,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,4,1,1,1,1,1,2,1,1,2,1,,1,,1, +667690,4,2,3,4,1,2,4,3,1,2,2,2,2,1,3,2,1,1,4,1,1,1,1,1,5,2,1,1,1,1,1,1,1,1,4,4,2,1,1,3,3,2,1,3,2,1,1,1,1,1,1,1,1,1,1,3,2,2,2,3,2,1,1,2,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,4,1,1,1,4,3,3,3,5,3,2,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,,1,,,1 +667624,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,,2 +2938935,2,2,4,3,1,4,4,4,3,2,2,2,2,3,2,2,1,2,4,1,1,1,3,4,2,1,1,4,1,2,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,2,1,3,2,2,2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,3,4,4,3,4,1,1,1,4,1,1,1,4,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,2,1,2,4,1,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,,1,,"1,3", +3099007,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,,1,,, +2392253,3,3,3,3,4,3,3,3,2,2,4,4,3,3,3,4,1,4,3,4,4,2,1,1,2,3,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,4,1,2,1,2,2,1,4,3,1,2,3,2,2,3,3,2,2,2,3,2,1,4,2,4,3,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,2,1,1,1,1,1,1,1,2,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,4,1,3,1,2,1,1,1,1,,1,1,,3 +673362,2,2,2,2,2,2,2,2,2,2,4,3,2,2,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,3,2,1,1,3,1,2,4,4,5,1,1,1,1,1,1,1,1,1,1,1,3,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,,2 +669904,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,1,,1,"2,3" +672480,1,2,2,4,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,3,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,4,1,1,3,5,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,1,2,,1,,,2 +516097,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,, +301656,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,1,,1,1 +2188757,3,3,2,3,3,3,4,4,2,3,2,2,4,2,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,4,4,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,,,,, +667603,3,3,3,3,2,3,3,3,2,2,3,2,2,4,2,2,1,1,2,1,1,1,2,2,1,1,1,1,1,1,3,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,5,5,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,3,1,3,1,3,3,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,,1,1,"1,3",1 +1636279,2,2,3,3,2,3,4,4,2,2,2,2,2,2,2,2,1,2,4,1,1,1,1,1,2,2,1,1,1,4,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,3,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,2,,1,,1,2 +131784,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,2,5,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,1,2,2,1,1,1,1,1,1,2,1,1,2,1,2,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,0,"I am teaching part time only, 1 course in the fall",1,1,"2,3", +3253135,4,3,1,4,1,1,3,3,2,1,1,1,2,3,1,1,1,1,1,1,1,1,2,5,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,1,3 +1636280,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,4,2,1,1,1,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,2,1,,,1,"2,3",1 +2274553,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,,,,,1 +3242193,2,1,2,2,1,2,3,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,3,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,4,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,1, +3233114,4,2,4,3,2,2,3,2,2,2,4,3,2,2,2,5,1,2,3,4,1,4,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,4,2,2,3,3,1,2,1,1,1,1,2,1,2,4,4,3,2,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,3,2,1,1,1,1,2,1,1,1,1,1,3,,,,, +672510,3,3,4,3,2,4,4,4,2,2,2,3,2,2,2,1,1,2,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,3,3,1,2,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,3,,,,2, +1300757,1,1,1,1,1,1,1,2,1,1,1,1,1,4,1,1,1,1,3,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,4,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,,,,3, +3242194,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,3,3,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,4,1,2,4,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,5,1,1,,,,,1 +193825,2,4,3,5,5,3,3,3,2,2,2,2,2,2,4,2,5,2,2,2,5,1,2,1,2,4,2,1,1,1,3,1,2,1,1,2,1,1,3,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,5,4,4,2,3,4,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,2,1,2,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,4,1,5,5,5,3,1,1,3,1,5,1,1,1,1,1,1,1,3,,,,,1 diff --git a/features/step_definitions/time_slots_steps.rb b/features/step_definitions/time_slots_steps.rb new file mode 100644 index 0000000..1bda90a --- /dev/null +++ b/features/step_definitions/time_slots_steps.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +Given('the following time slots exist:') do |table| + table.hashes.each do |time_slot| + TimeSlot.create!( + day: time_slot['day'], + start_time: time_slot['start_time'], + end_time: time_slot['end_time'], + slot_type: time_slot['slot_type'] + ) + end +end + +When('I visit the time slots page for {string}') do |schedule_name| + schedule = Schedule.find_by(schedule_name:) + visit schedule_time_slots_path(schedule) +end + +When('I select {string} from the {string} dropdown') do |option, dropdown_label| + select option, from: dropdown_label +end + +Then('I should see a time slot for {string} from {string} to {string} of type {string}') do |day, start_time, end_time, slot_type| + within('.timeTable-table') do + expect(page).to have_content("#{day} #{start_time} #{end_time} #{slot_type}") + end +end + +Then('I should not see a time slot for {string} from {string} to {string} of type {string}') do |day, start_time, end_time, slot_type| + within('.timeTable-table') do + expect(page).not_to have_content("#{day} #{start_time} #{end_time} #{slot_type}") + end +end diff --git a/features/time_slots.feature b/features/time_slots.feature new file mode 100644 index 0000000..22c1d1c --- /dev/null +++ b/features/time_slots.feature @@ -0,0 +1,38 @@ +Feature: Time Slots Page + As a user + I want to view time slots for a schedule + So that I can filter and find time slots by day and type + + Background: + Given a schedule exists with the schedule name "Sched 1" and semester name "Fall 2024" + And I am logged in as a user with first name "Test" + And the following time slots exist: + | day | start_time | end_time | slot_type | + | MWF | 09:00 | 10:00 | LEC | + | MW | 10:00 | 11:00 | LAB | + | TR | 11:00 | 12:00 | LEC | + | F | 13:00 | 14:00 | LEC | + + Scenario: Viewing all time slots + When I visit the time slots page for "Sched 1" + Then I should see a time slot for "MWF" from "09:00" to "10:00" of type "LEC" + And I should see a time slot for "MW" from "10:00" to "11:00" of type "LAB" + And I should see a time slot for "TR" from "11:00" to "12:00" of type "LEC" + And I should see a time slot for "F" from "13:00" to "14:00" of type "LEC" + + Scenario: Filtering time slots by day + When I visit the time slots page for "Sched 1" + And I select "MWF" from the "Filter by Day" dropdown + And I click the "Filter" button + Then I should see a time slot for "MWF" from "09:00" to "10:00" of type "LEC" + And I should not see a time slot for "MW" from "10:00" to "11:00" of type "LAB" + And I should not see a time slot for "TR" from "11:00" to "12:00" of type "LEC" + + Scenario: Filtering time slots by type + When I visit the time slots page for "Sched 1" + And I select "LAB" from the "Filter by Type" dropdown + And I click the "Filter" button + Then I should see a time slot for "MW" from "10:00" to "11:00" of type "LAB" + And I should not see a time slot for "MWF" from "09:00" to "10:00" of type "LEC" + And I should not see a time slot for "TR" from "11:00" to "12:00" of type "LEC" + And I should not see a time slot for "F" from "13:00" to "14:00" of type "LEC" diff --git a/test/factories/instructor_preferences.rb b/test/factories/instructor_preferences.rb new file mode 100644 index 0000000..8e9b8f9 --- /dev/null +++ b/test/factories/instructor_preferences.rb @@ -0,0 +1 @@ +# frozen_string_literal: true diff --git a/test/models/instructor_preference_test.rb b/test/models/instructor_preference_test.rb new file mode 100644 index 0000000..fe53a64 --- /dev/null +++ b/test/models/instructor_preference_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class InstructorPreferenceTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 12bf6ec890a66c3ef188067bf51f527e2f11bf38 Mon Sep 17 00:00:00 2001 From: pavitgopal Date: Wed, 30 Oct 2024 23:56:23 -0500 Subject: [PATCH 3/8] implemented propogation across tabs --- app/controllers/room_bookings_controller.rb | 55 ++++++++++----------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/app/controllers/room_bookings_controller.rb b/app/controllers/room_bookings_controller.rb index 49c5641..a28960b 100644 --- a/app/controllers/room_bookings_controller.rb +++ b/app/controllers/room_bookings_controller.rb @@ -15,33 +15,22 @@ def index end end - # RoomBookingsController -# RoomBookingsController -# RoomBookingsController -def toggle_availability - room_booking = RoomBooking.find_or_initialize_by(room_id: params[:room_id], time_slot_id: params[:time_slot_id]) - new_status = !room_booking.is_available - room_booking.update(is_available: new_status) - - # Calculate relevant days based on the current active tab - relevant_days = calculate_relevant_days(params[:active_tab]) - - # Manually construct the overlap conditions since SQLite lacks the OVERLAPS function - related_time_slots = TimeSlot.where(day: relevant_days) - .where("start_time < ? AND end_time > ?", - room_booking.time_slot.end_time, - room_booking.time_slot.start_time) - - # Update RoomBookings to reflect the new status across relevant overlapping time slots and days - RoomBooking.where(room_id: params[:room_id], time_slot: related_time_slots) - .update_all(is_available: new_status) - - # Redirect back to the room bookings page with the active tab - redirect_to schedule_room_bookings_path(@schedule, active_tab: params[:active_tab]) -end + before_action :set_schedule + def toggle_availability + room_booking = RoomBooking.find_or_initialize_by(room_id: params[:room_id], time_slot_id: params[:time_slot_id]) + new_status = !room_booking.is_available + room_booking.update(is_available: new_status) + # Apply changes to overlapping time slots across relevant days + overlapping_time_slots = find_overlapping_time_slots(room_booking.time_slot) + overlapping_time_slots.each do |overlapping_slot| + overlapping_booking = RoomBooking.find_or_initialize_by(room_id: params[:room_id], time_slot_id: overlapping_slot.id) + overlapping_booking.update(is_available: new_status) + end + redirect_to schedule_room_bookings_path(@schedule, active_tab: params[:active_tab]) + end private @@ -49,8 +38,18 @@ def set_schedule @schedule = Schedule.find(params[:schedule_id]) end - def calculate_relevant_days(current_tab) - case current_tab + # Finds overlapping time slots based on start and end time + def find_overlapping_time_slots(time_slot) + relevant_days = calculate_relevant_days(time_slot.day) + + # Select time slots on relevant days that overlap in time + TimeSlot.where(day: relevant_days) + .where("start_time < ? AND end_time > ?", time_slot.end_time, time_slot.start_time) + end + + # Determine relevant days based on the current day pattern (e.g., 'MWF' overlaps with 'MW' and 'F') + def calculate_relevant_days(current_day) + case current_day when 'MWF' %w[MWF MW F] when 'MW' @@ -58,7 +57,7 @@ def calculate_relevant_days(current_tab) when 'F' %w[MWF F] else - [current_tab] # Only affects TR or any isolated day + [current_day] # Only affect the current day, such as TR or any isolated day end end -end +end \ No newline at end of file From f72dd3ec2cd96d181c45df16c3c1c053894234e7 Mon Sep 17 00:00:00 2001 From: pavitgopal Date: Thu, 31 Oct 2024 01:25:04 -0500 Subject: [PATCH 4/8] added rspec tests --- db/schema.rb | 188 ++++++++++-------- .../room_bookings_controller_spec.rb | 106 ++++++++-- 2 files changed, 194 insertions(+), 100 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 1314eff..fc55a58 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -12,100 +10,126 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 20_241_027_021_034) do - create_table 'courses', force: :cascade do |t| - t.string 'course_number' - t.integer 'max_seats' - t.string 'lecture_type' - t.integer 'num_labs' - t.integer 'schedule_id', null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['schedule_id'], name: 'index_courses_on_schedule_id' +ActiveRecord::Schema[7.2].define(version: 2024_10_30_180433) do + create_table "courses", force: :cascade do |t| + t.string "course_number" + t.integer "max_seats" + t.string "lecture_type" + t.integer "num_labs" + t.integer "schedule_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["schedule_id"], name: "index_courses_on_schedule_id" + end + + create_table "instructor_preferences", force: :cascade do |t| + t.integer "instructor_id", null: false + t.integer "preference_level" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "course_id", null: false + t.index ["course_id"], name: "index_instructor_preferences_on_course_id" + t.index ["instructor_id"], name: "index_instructor_preferences_on_instructor_id" + end + + create_table "instructors", force: :cascade do |t| + t.integer "id_number" + t.string "last_name" + t.string "first_name" + t.string "middle_name" + t.string "email" + t.boolean "before_9" + t.boolean "after_3" + t.text "beaware_of" + t.integer "schedule_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "max_course_load" + t.index ["schedule_id"], name: "index_instructors_on_schedule_id" end - create_table 'instructors', force: :cascade do |t| - t.integer 'id_number' - t.string 'last_name' - t.string 'first_name' - t.string 'middle_name' - t.string 'email' - t.boolean 'before_9' - t.boolean 'after_3' - t.text 'beaware_of' - t.integer 'schedule_id' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['schedule_id'], name: 'index_instructors_on_schedule_id' + create_table "room_blocks", force: :cascade do |t| + t.integer "room_id", null: false + t.integer "time_slot_id", null: false + t.boolean "is_blocked", default: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["room_id"], name: "index_room_blocks_on_room_id" + t.index ["time_slot_id"], name: "index_room_blocks_on_time_slot_id" end - create_table 'room_bookings', force: :cascade do |t| - t.integer 'room_id', null: false - t.integer 'time_slot_id', null: false - t.boolean 'is_available' - t.boolean 'is_lab' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['room_id'], name: 'index_room_bookings_on_room_id' - t.index ['time_slot_id'], name: 'index_room_bookings_on_time_slot_id' + create_table "room_bookings", force: :cascade do |t| + t.integer "room_id", null: false + t.integer "time_slot_id", null: false + t.boolean "is_available" + t.boolean "is_lab" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["room_id"], name: "index_room_bookings_on_room_id" + t.index ["time_slot_id"], name: "index_room_bookings_on_time_slot_id" end - create_table 'rooms', force: :cascade do |t| - t.integer 'campus' - t.boolean 'is_lecture_hall' - t.boolean 'is_learning_studio' - t.boolean 'is_lab' - t.string 'building_code' - t.string 'room_number' - t.integer 'capacity' - t.boolean 'is_active' - t.string 'comments' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.integer 'schedule_id', default: -1, null: false - t.index ['schedule_id'], name: 'index_rooms_on_schedule_id' + create_table "rooms", force: :cascade do |t| + t.integer "campus" + t.boolean "is_lecture_hall" + t.boolean "is_learning_studio" + t.boolean "is_lab" + t.string "building_code" + t.string "room_number" + t.integer "capacity" + t.boolean "is_active" + t.string "comments" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "schedule_id", default: -1, null: false + t.index ["schedule_id"], name: "index_rooms_on_schedule_id" end - create_table 'schedules', force: :cascade do |t| - t.string 'schedule_name' - t.string 'semester_name' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false + create_table "schedules", force: :cascade do |t| + t.string "schedule_name" + t.string "semester_name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table 'sections', force: :cascade do |t| - t.string 'section_number' - t.integer 'seats_alloted' - t.integer 'course_id', null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['course_id'], name: 'index_sections_on_course_id' + create_table "sections", force: :cascade do |t| + t.string "section_number" + t.integer "seats_alloted" + t.integer "course_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["course_id"], name: "index_sections_on_course_id" end - create_table 'time_slots', force: :cascade do |t| - t.string 'day' - t.string 'start_time' - t.string 'end_time' - t.string 'slot_type' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false + create_table "time_slots", force: :cascade do |t| + t.string "day" + t.string "start_time" + t.string "end_time" + t.string "slot_type" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "day_change" end - create_table 'users', force: :cascade do |t| - t.string 'email' - t.string 'first_name' - t.string 'last_name' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'uid' - t.string 'provider' - t.index ['email'], name: 'index_users_on_email', unique: true + create_table "users", force: :cascade do |t| + t.string "email" + t.string "first_name" + t.string "last_name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "uid" + t.string "provider" + t.index ["email"], name: "index_users_on_email", unique: true end - add_foreign_key 'courses', 'schedules' - add_foreign_key 'instructors', 'schedules' - add_foreign_key 'room_bookings', 'rooms' - add_foreign_key 'room_bookings', 'time_slots' - add_foreign_key 'rooms', 'schedules' - add_foreign_key 'sections', 'courses' + add_foreign_key "courses", "schedules" + add_foreign_key "instructor_preferences", "courses" + add_foreign_key "instructor_preferences", "instructors" + add_foreign_key "instructors", "schedules" + add_foreign_key "room_blocks", "rooms" + add_foreign_key "room_blocks", "time_slots" + add_foreign_key "room_bookings", "rooms" + add_foreign_key "room_bookings", "time_slots" + add_foreign_key "rooms", "schedules" + add_foreign_key "sections", "courses" end diff --git a/spec/controllers/room_bookings_controller_spec.rb b/spec/controllers/room_bookings_controller_spec.rb index cec0ca3..4188254 100644 --- a/spec/controllers/room_bookings_controller_spec.rb +++ b/spec/controllers/room_bookings_controller_spec.rb @@ -13,38 +13,108 @@ let!(:room_booking2) { create(:room_booking, room: room2, time_slot: time_slot2, is_available: false) } before do - @user = User.create!(uid: '12345', provider: 'google_oauth2', email: 'test@example.com', first_name: 'John', - last_name: 'Doe') + @user = User.create!(uid: '12345', provider: 'google_oauth2', email: 'test@example.com', first_name: 'John', last_name: 'Doe') allow(controller).to receive(:logged_in?).and_return(true) controller.instance_variable_set(:@current_user, @user) end describe 'GET #index' do - context 'when room_booking already exists' do - before do - get :index, params: { schedule_id: schedule.id } - end + before do + get :index, params: { schedule_id: schedule.id } + end + + it 'returns a successful response' do + expect(response).to have_http_status(:success) + end + + it 'assigns @rooms' do + expect(assigns(:rooms)).to match_array([room1, room2]) + end + + it 'assigns @time_slots' do + expect(assigns(:time_slots)).to match_array([time_slot1, time_slot2]) + end + + it 'assigns @bookings_matrix with room_booking data' do + bookings_matrix = assigns(:bookings_matrix) + expect(bookings_matrix[[room1.id, time_slot1.id]]).to eq(room_booking1) + expect(bookings_matrix[[room2.id, time_slot2.id]]).to eq(room_booking2) + end + + it 'renders the index template' do + expect(response).to render_template(:index) + end + end - it 'returns a successful response' do - expect(response).to have_http_status(:success) + describe 'POST #toggle_availability' do + context 'when booking is currently available' do + it 'toggles availability to false' do + expect { + post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } + room_booking1.reload + }.to change { room_booking1.is_available }.from(true).to(false) + + # Check redirect + expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end - it 'assigns @rooms' do - expect(assigns(:rooms)).to match_array([room1, room2]) + it 'toggles availability for overlapping bookings' do + # Create another overlapping time slot + overlapping_slot = create(:time_slot, day: 'Monday', start_time: '09:30', end_time: '10:30') + create(:room_booking, room: room1, time_slot: overlapping_slot, is_available: true) + + expect { + post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } + }.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(true).to(false) + + # Check if the overlapping booking is updated correctly + overlapping_booking = RoomBooking.find_by(room: room1, time_slot: overlapping_slot) + expect(overlapping_booking.is_available).to eq(false) + + # Check redirect + expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end + end + + context 'when booking is currently blocked' do + before { room_booking1.update(is_available: false) } - it 'assigns @time_slots' do - expect(assigns(:time_slots)).to match_array([time_slot1, time_slot2]) + it 'toggles availability to true' do + expect { + post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } + room_booking1.reload + }.to change { room_booking1.is_available }.from(false).to(true) + + # Check redirect + expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end - it 'assigns @bookings_matrix with room_booking data' do - bookings_matrix = assigns(:bookings_matrix) - expect(bookings_matrix[[room1.id, time_slot1.id]]).to eq(room_booking1) - expect(bookings_matrix[[room2.id, time_slot2.id]]).to eq(room_booking2) + it 'toggles availability for overlapping bookings' do + # Create another overlapping time slot + overlapping_slot = create(:time_slot, day: 'Monday', start_time: '09:30', end_time: '10:30') + create(:room_booking, room: room1, time_slot: overlapping_slot, is_available: false) + + expect { + post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } + }.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(false).to(true) + + # Check if the overlapping booking is updated correctly + overlapping_booking = RoomBooking.find_by(room: room1, time_slot: overlapping_slot) + expect(overlapping_booking.is_available).to eq(true) + + # Check redirect + expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end + end + end - it 'renders the index template' do - expect(response).to render_template(:index) + describe 'private methods' do + describe '#calculate_relevant_days' do + it 'returns the correct relevant days' do + expect(controller.send(:calculate_relevant_days, 'MWF')).to match_array(%w[MWF MW F]) + expect(controller.send(:calculate_relevant_days, 'MW')).to match_array(%w[MWF MW]) + expect(controller.send(:calculate_relevant_days, 'F')).to match_array(%w[MWF F]) + expect(controller.send(:calculate_relevant_days, 'TR')).to match_array(['TR']) end end end From 711dbace4b7343ac9419a9830543d032cb691f6e Mon Sep 17 00:00:00 2001 From: pavitgopal Date: Thu, 31 Oct 2024 01:29:28 -0500 Subject: [PATCH 5/8] rubocop tests --- app/controllers/room_bookings_controller.rb | 13 +- config/routes.rb | 1 - db/schema.rb | 206 +++++++++--------- .../room_bookings_controller_spec.rb | 24 +- 4 files changed, 117 insertions(+), 127 deletions(-) diff --git a/app/controllers/room_bookings_controller.rb b/app/controllers/room_bookings_controller.rb index a28960b..b2480dd 100644 --- a/app/controllers/room_bookings_controller.rb +++ b/app/controllers/room_bookings_controller.rb @@ -1,4 +1,5 @@ -# Room Bookings Controller +# frozen_string_literal: true + class RoomBookingsController < ApplicationController before_action :set_schedule @@ -22,7 +23,6 @@ def toggle_availability new_status = !room_booking.is_available room_booking.update(is_available: new_status) - # Apply changes to overlapping time slots across relevant days overlapping_time_slots = find_overlapping_time_slots(room_booking.time_slot) overlapping_time_slots.each do |overlapping_slot| overlapping_booking = RoomBooking.find_or_initialize_by(room_id: params[:room_id], time_slot_id: overlapping_slot.id) @@ -38,16 +38,13 @@ def set_schedule @schedule = Schedule.find(params[:schedule_id]) end - # Finds overlapping time slots based on start and end time def find_overlapping_time_slots(time_slot) relevant_days = calculate_relevant_days(time_slot.day) - # Select time slots on relevant days that overlap in time TimeSlot.where(day: relevant_days) - .where("start_time < ? AND end_time > ?", time_slot.end_time, time_slot.start_time) + .where('start_time < ? AND end_time > ?', time_slot.end_time, time_slot.start_time) end - # Determine relevant days based on the current day pattern (e.g., 'MWF' overlaps with 'MW' and 'F') def calculate_relevant_days(current_day) case current_day when 'MWF' @@ -57,7 +54,7 @@ def calculate_relevant_days(current_day) when 'F' %w[MWF F] else - [current_day] # Only affect the current day, such as TR or any isolated day + [current_day] end end -end \ No newline at end of file +end diff --git a/config/routes.rb b/config/routes.rb index 4a85dd4..40f66ee 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,7 +42,6 @@ get '/time_slots', to: 'time_slots#index' resources :room_bookings, only: [:index] post 'room_bookings/toggle_availability', to: 'room_bookings#toggle_availability' - end resources :room_bookings do diff --git a/db/schema.rb b/db/schema.rb index fc55a58..3515535 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -10,126 +12,126 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_30_180433) do - create_table "courses", force: :cascade do |t| - t.string "course_number" - t.integer "max_seats" - t.string "lecture_type" - t.integer "num_labs" - t.integer "schedule_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["schedule_id"], name: "index_courses_on_schedule_id" +ActiveRecord::Schema[7.2].define(version: 20_241_030_180_433) do + create_table 'courses', force: :cascade do |t| + t.string 'course_number' + t.integer 'max_seats' + t.string 'lecture_type' + t.integer 'num_labs' + t.integer 'schedule_id', null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['schedule_id'], name: 'index_courses_on_schedule_id' end - create_table "instructor_preferences", force: :cascade do |t| - t.integer "instructor_id", null: false - t.integer "preference_level" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "course_id", null: false - t.index ["course_id"], name: "index_instructor_preferences_on_course_id" - t.index ["instructor_id"], name: "index_instructor_preferences_on_instructor_id" + create_table 'instructor_preferences', force: :cascade do |t| + t.integer 'instructor_id', null: false + t.integer 'preference_level' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.integer 'course_id', null: false + t.index ['course_id'], name: 'index_instructor_preferences_on_course_id' + t.index ['instructor_id'], name: 'index_instructor_preferences_on_instructor_id' end - create_table "instructors", force: :cascade do |t| - t.integer "id_number" - t.string "last_name" - t.string "first_name" - t.string "middle_name" - t.string "email" - t.boolean "before_9" - t.boolean "after_3" - t.text "beaware_of" - t.integer "schedule_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "max_course_load" - t.index ["schedule_id"], name: "index_instructors_on_schedule_id" + create_table 'instructors', force: :cascade do |t| + t.integer 'id_number' + t.string 'last_name' + t.string 'first_name' + t.string 'middle_name' + t.string 'email' + t.boolean 'before_9' + t.boolean 'after_3' + t.text 'beaware_of' + t.integer 'schedule_id' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.integer 'max_course_load' + t.index ['schedule_id'], name: 'index_instructors_on_schedule_id' end - create_table "room_blocks", force: :cascade do |t| - t.integer "room_id", null: false - t.integer "time_slot_id", null: false - t.boolean "is_blocked", default: true - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["room_id"], name: "index_room_blocks_on_room_id" - t.index ["time_slot_id"], name: "index_room_blocks_on_time_slot_id" + create_table 'room_blocks', force: :cascade do |t| + t.integer 'room_id', null: false + t.integer 'time_slot_id', null: false + t.boolean 'is_blocked', default: true + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['room_id'], name: 'index_room_blocks_on_room_id' + t.index ['time_slot_id'], name: 'index_room_blocks_on_time_slot_id' end - create_table "room_bookings", force: :cascade do |t| - t.integer "room_id", null: false - t.integer "time_slot_id", null: false - t.boolean "is_available" - t.boolean "is_lab" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["room_id"], name: "index_room_bookings_on_room_id" - t.index ["time_slot_id"], name: "index_room_bookings_on_time_slot_id" + create_table 'room_bookings', force: :cascade do |t| + t.integer 'room_id', null: false + t.integer 'time_slot_id', null: false + t.boolean 'is_available' + t.boolean 'is_lab' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['room_id'], name: 'index_room_bookings_on_room_id' + t.index ['time_slot_id'], name: 'index_room_bookings_on_time_slot_id' end - create_table "rooms", force: :cascade do |t| - t.integer "campus" - t.boolean "is_lecture_hall" - t.boolean "is_learning_studio" - t.boolean "is_lab" - t.string "building_code" - t.string "room_number" - t.integer "capacity" - t.boolean "is_active" - t.string "comments" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "schedule_id", default: -1, null: false - t.index ["schedule_id"], name: "index_rooms_on_schedule_id" + create_table 'rooms', force: :cascade do |t| + t.integer 'campus' + t.boolean 'is_lecture_hall' + t.boolean 'is_learning_studio' + t.boolean 'is_lab' + t.string 'building_code' + t.string 'room_number' + t.integer 'capacity' + t.boolean 'is_active' + t.string 'comments' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.integer 'schedule_id', default: -1, null: false + t.index ['schedule_id'], name: 'index_rooms_on_schedule_id' end - create_table "schedules", force: :cascade do |t| - t.string "schedule_name" - t.string "semester_name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table 'schedules', force: :cascade do |t| + t.string 'schedule_name' + t.string 'semester_name' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false end - create_table "sections", force: :cascade do |t| - t.string "section_number" - t.integer "seats_alloted" - t.integer "course_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["course_id"], name: "index_sections_on_course_id" + create_table 'sections', force: :cascade do |t| + t.string 'section_number' + t.integer 'seats_alloted' + t.integer 'course_id', null: false + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.index ['course_id'], name: 'index_sections_on_course_id' end - create_table "time_slots", force: :cascade do |t| - t.string "day" - t.string "start_time" - t.string "end_time" - t.string "slot_type" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "day_change" + create_table 'time_slots', force: :cascade do |t| + t.string 'day' + t.string 'start_time' + t.string 'end_time' + t.string 'slot_type' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'day_change' end - create_table "users", force: :cascade do |t| - t.string "email" - t.string "first_name" - t.string "last_name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "uid" - t.string "provider" - t.index ["email"], name: "index_users_on_email", unique: true + create_table 'users', force: :cascade do |t| + t.string 'email' + t.string 'first_name' + t.string 'last_name' + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.string 'uid' + t.string 'provider' + t.index ['email'], name: 'index_users_on_email', unique: true end - add_foreign_key "courses", "schedules" - add_foreign_key "instructor_preferences", "courses" - add_foreign_key "instructor_preferences", "instructors" - add_foreign_key "instructors", "schedules" - add_foreign_key "room_blocks", "rooms" - add_foreign_key "room_blocks", "time_slots" - add_foreign_key "room_bookings", "rooms" - add_foreign_key "room_bookings", "time_slots" - add_foreign_key "rooms", "schedules" - add_foreign_key "sections", "courses" + add_foreign_key 'courses', 'schedules' + add_foreign_key 'instructor_preferences', 'courses' + add_foreign_key 'instructor_preferences', 'instructors' + add_foreign_key 'instructors', 'schedules' + add_foreign_key 'room_blocks', 'rooms' + add_foreign_key 'room_blocks', 'time_slots' + add_foreign_key 'room_bookings', 'rooms' + add_foreign_key 'room_bookings', 'time_slots' + add_foreign_key 'rooms', 'schedules' + add_foreign_key 'sections', 'courses' end diff --git a/spec/controllers/room_bookings_controller_spec.rb b/spec/controllers/room_bookings_controller_spec.rb index 4188254..00cf008 100644 --- a/spec/controllers/room_bookings_controller_spec.rb +++ b/spec/controllers/room_bookings_controller_spec.rb @@ -49,29 +49,25 @@ describe 'POST #toggle_availability' do context 'when booking is currently available' do it 'toggles availability to false' do - expect { + expect do post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } room_booking1.reload - }.to change { room_booking1.is_available }.from(true).to(false) + end.to change { room_booking1.is_available }.from(true).to(false) - # Check redirect expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end it 'toggles availability for overlapping bookings' do - # Create another overlapping time slot overlapping_slot = create(:time_slot, day: 'Monday', start_time: '09:30', end_time: '10:30') create(:room_booking, room: room1, time_slot: overlapping_slot, is_available: true) - expect { + expect do post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } - }.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(true).to(false) + end.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(true).to(false) - # Check if the overlapping booking is updated correctly overlapping_booking = RoomBooking.find_by(room: room1, time_slot: overlapping_slot) expect(overlapping_booking.is_available).to eq(false) - # Check redirect expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end end @@ -80,29 +76,25 @@ before { room_booking1.update(is_available: false) } it 'toggles availability to true' do - expect { + expect do post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } room_booking1.reload - }.to change { room_booking1.is_available }.from(false).to(true) + end.to change { room_booking1.is_available }.from(false).to(true) - # Check redirect expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end it 'toggles availability for overlapping bookings' do - # Create another overlapping time slot overlapping_slot = create(:time_slot, day: 'Monday', start_time: '09:30', end_time: '10:30') create(:room_booking, room: room1, time_slot: overlapping_slot, is_available: false) - expect { + expect do post :toggle_availability, params: { room_id: room1.id, time_slot_id: time_slot1.id, schedule_id: schedule.id } - }.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(false).to(true) + end.to change { RoomBooking.find_by(room: room1, time_slot: overlapping_slot).is_available }.from(false).to(true) - # Check if the overlapping booking is updated correctly overlapping_booking = RoomBooking.find_by(room: room1, time_slot: overlapping_slot) expect(overlapping_booking.is_available).to eq(true) - # Check redirect expect(response).to redirect_to(schedule_room_bookings_path(schedule, active_tab: nil)) end end From c23a933e360a4f86ad3872cc7cf46a136b5121fb Mon Sep 17 00:00:00 2001 From: kingofikings441 Date: Fri, 1 Nov 2024 13:06:32 -0500 Subject: [PATCH 6/8] failing one cucmber test --- db/schema.rb | 197 ++++++++---------- features/room_booking_management.feature | 19 ++ .../room_booking_management_steps.rb | 32 +++ 3 files changed, 142 insertions(+), 106 deletions(-) create mode 100644 features/room_booking_management.feature create mode 100644 features/step_definitions/room_booking_management_steps.rb diff --git a/db/schema.rb b/db/schema.rb index 3515535..bc0a95d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -12,126 +10,113 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 20_241_030_180_433) do - create_table 'courses', force: :cascade do |t| - t.string 'course_number' - t.integer 'max_seats' - t.string 'lecture_type' - t.integer 'num_labs' - t.integer 'schedule_id', null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['schedule_id'], name: 'index_courses_on_schedule_id' - end - - create_table 'instructor_preferences', force: :cascade do |t| - t.integer 'instructor_id', null: false - t.integer 'preference_level' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.integer 'course_id', null: false - t.index ['course_id'], name: 'index_instructor_preferences_on_course_id' - t.index ['instructor_id'], name: 'index_instructor_preferences_on_instructor_id' +ActiveRecord::Schema[7.2].define(version: 2024_10_29_040851) do + create_table "courses", force: :cascade do |t| + t.string "course_number" + t.integer "max_seats" + t.string "lecture_type" + t.integer "num_labs" + t.integer "schedule_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["schedule_id"], name: "index_courses_on_schedule_id" end - create_table 'instructors', force: :cascade do |t| - t.integer 'id_number' - t.string 'last_name' - t.string 'first_name' - t.string 'middle_name' - t.string 'email' - t.boolean 'before_9' - t.boolean 'after_3' - t.text 'beaware_of' - t.integer 'schedule_id' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.integer 'max_course_load' - t.index ['schedule_id'], name: 'index_instructors_on_schedule_id' + create_table "instructor_preferences", force: :cascade do |t| + t.integer "instructor_id", null: false + t.integer "preference_level" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "course_id", null: false + t.index ["course_id"], name: "index_instructor_preferences_on_course_id" + t.index ["instructor_id"], name: "index_instructor_preferences_on_instructor_id" end - create_table 'room_blocks', force: :cascade do |t| - t.integer 'room_id', null: false - t.integer 'time_slot_id', null: false - t.boolean 'is_blocked', default: true - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['room_id'], name: 'index_room_blocks_on_room_id' - t.index ['time_slot_id'], name: 'index_room_blocks_on_time_slot_id' + create_table "instructors", force: :cascade do |t| + t.integer "id_number" + t.string "last_name" + t.string "first_name" + t.string "middle_name" + t.string "email" + t.boolean "before_9" + t.boolean "after_3" + t.text "beaware_of" + t.integer "schedule_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "max_course_load" + t.index ["schedule_id"], name: "index_instructors_on_schedule_id" end - create_table 'room_bookings', force: :cascade do |t| - t.integer 'room_id', null: false - t.integer 'time_slot_id', null: false - t.boolean 'is_available' - t.boolean 'is_lab' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['room_id'], name: 'index_room_bookings_on_room_id' - t.index ['time_slot_id'], name: 'index_room_bookings_on_time_slot_id' + create_table "room_bookings", force: :cascade do |t| + t.integer "room_id", null: false + t.integer "time_slot_id", null: false + t.boolean "is_available" + t.boolean "is_lab" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["room_id"], name: "index_room_bookings_on_room_id" + t.index ["time_slot_id"], name: "index_room_bookings_on_time_slot_id" end - create_table 'rooms', force: :cascade do |t| - t.integer 'campus' - t.boolean 'is_lecture_hall' - t.boolean 'is_learning_studio' - t.boolean 'is_lab' - t.string 'building_code' - t.string 'room_number' - t.integer 'capacity' - t.boolean 'is_active' - t.string 'comments' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.integer 'schedule_id', default: -1, null: false - t.index ['schedule_id'], name: 'index_rooms_on_schedule_id' + create_table "rooms", force: :cascade do |t| + t.integer "campus" + t.boolean "is_lecture_hall" + t.boolean "is_learning_studio" + t.boolean "is_lab" + t.string "building_code" + t.string "room_number" + t.integer "capacity" + t.boolean "is_active" + t.string "comments" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "schedule_id", default: -1, null: false + t.index ["schedule_id"], name: "index_rooms_on_schedule_id" end - create_table 'schedules', force: :cascade do |t| - t.string 'schedule_name' - t.string 'semester_name' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false + create_table "schedules", force: :cascade do |t| + t.string "schedule_name" + t.string "semester_name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table 'sections', force: :cascade do |t| - t.string 'section_number' - t.integer 'seats_alloted' - t.integer 'course_id', null: false - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.index ['course_id'], name: 'index_sections_on_course_id' + create_table "sections", force: :cascade do |t| + t.string "section_number" + t.integer "seats_alloted" + t.integer "course_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["course_id"], name: "index_sections_on_course_id" end - create_table 'time_slots', force: :cascade do |t| - t.string 'day' - t.string 'start_time' - t.string 'end_time' - t.string 'slot_type' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'day_change' + create_table "time_slots", force: :cascade do |t| + t.string "day" + t.string "start_time" + t.string "end_time" + t.string "slot_type" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table 'users', force: :cascade do |t| - t.string 'email' - t.string 'first_name' - t.string 'last_name' - t.datetime 'created_at', null: false - t.datetime 'updated_at', null: false - t.string 'uid' - t.string 'provider' - t.index ['email'], name: 'index_users_on_email', unique: true + create_table "users", force: :cascade do |t| + t.string "email" + t.string "first_name" + t.string "last_name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "uid" + t.string "provider" + t.index ["email"], name: "index_users_on_email", unique: true end - add_foreign_key 'courses', 'schedules' - add_foreign_key 'instructor_preferences', 'courses' - add_foreign_key 'instructor_preferences', 'instructors' - add_foreign_key 'instructors', 'schedules' - add_foreign_key 'room_blocks', 'rooms' - add_foreign_key 'room_blocks', 'time_slots' - add_foreign_key 'room_bookings', 'rooms' - add_foreign_key 'room_bookings', 'time_slots' - add_foreign_key 'rooms', 'schedules' - add_foreign_key 'sections', 'courses' + add_foreign_key "courses", "schedules" + add_foreign_key "instructor_preferences", "courses" + add_foreign_key "instructor_preferences", "instructors" + add_foreign_key "instructors", "schedules" + add_foreign_key "room_bookings", "rooms" + add_foreign_key "room_bookings", "time_slots" + add_foreign_key "rooms", "schedules" + add_foreign_key "sections", "courses" end diff --git a/features/room_booking_management.feature b/features/room_booking_management.feature new file mode 100644 index 0000000..6721c00 --- /dev/null +++ b/features/room_booking_management.feature @@ -0,0 +1,19 @@ +Feature: Room Booking Management + Scenario: Toggling room booking availability + Given I am logged in as a user with first name "Test" + And a schedule exists with the schedule name "Sched 1" and semester name "Fall 2024" + And the following rooms exist for that schedule: + | campus | building_code | room_number | capacity | is_active | is_lab | is_learning_studio | is_lecture_hall | + | CS | BLDG1 | 101 | 30 | true | true | true | true | + | GV | BLDG2 | 102 | 50 | true | true | true | true | + | CS | BLDG3 | 102 | 50 | false | true | true | true | + And the following time slots exist: + | day | start_time | end_time | slot_type | + | MWF | 09:00 | 10:00 | "LEC" | + | MW | 08:00 | 10:00 | "LEC" | + And a room booking exists for "Sched 1" with room "BLDG1" "101" at "09:00" that is available + When I visit the room bookings page for "Sched 1" + + And I toggle availability for the room booking in "BLDG1" "101" at "09:00" + Then the booking in "BLDG1" "101" at "09:00" should be unavailable + And overlapping bookings should also be unavailable \ No newline at end of file diff --git a/features/step_definitions/room_booking_management_steps.rb b/features/step_definitions/room_booking_management_steps.rb new file mode 100644 index 0000000..75e61fb --- /dev/null +++ b/features/step_definitions/room_booking_management_steps.rb @@ -0,0 +1,32 @@ + + +Given('a room booking exists for {string} with room {string} {string} at {string} that is available') do |schedule, building, room, start| + RoomBooking.create!( + room: Room.find_by(schedule_id: Schedule.find_by(schedule_name: schedule ),building_code: building, room_number: room), + time_slot: TimeSlot.find_by(start_time: start), + is_available: true, + is_lab: false + ) +end + +When('I toggle availability for the room booking in {string} {string} at {string}') do |building, room, start| + timeslot=TimeSlot.find_by(start_time: start) + row = find('tr', text: "#{timeslot.start_time} - #{timeslot.end_time}") + room_headers = all('th') + room_header_index = room_headers.find_index { |header| header.text == "#{building} #{room}" } + room_cell = row.all('td')[room_header_index] + room_cell.click_button("BL") + +end + + +Then('the booking in {string} {string} at {string} should be unavailable') do | building, room, start| + expect(RoomBooking.find_by( + room: Room.find_by(schedule_id: @schedule.id, building_code: building, room_number: room), + time_slot: TimeSlot.find_by(start_time: start) + ).is_available).to eq(false) +end + +Then('overlapping bookings should also be unavailable') do + pending # Write code here that turns the phrase above into concrete actions +end \ No newline at end of file From cb253715cb244ddbce3ee88d9cca33c5ef0659a4 Mon Sep 17 00:00:00 2001 From: kingofikings441 Date: Wed, 6 Nov 2024 14:26:12 -0600 Subject: [PATCH 7/8] still need to do the overlapping test --- features/room_booking_management.feature | 3 ++- features/step_definitions/room_booking_management_steps.rb | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/features/room_booking_management.feature b/features/room_booking_management.feature index 6721c00..e24558b 100644 --- a/features/room_booking_management.feature +++ b/features/room_booking_management.feature @@ -10,7 +10,8 @@ Feature: Room Booking Management And the following time slots exist: | day | start_time | end_time | slot_type | | MWF | 09:00 | 10:00 | "LEC" | - | MW | 08:00 | 10:00 | "LEC" | + | MW | 09:00 | 10:00 | "LEC" | + And a room booking exists for "Sched 1" with room "BLDG1" "101" at "09:00" that is available When I visit the room bookings page for "Sched 1" diff --git a/features/step_definitions/room_booking_management_steps.rb b/features/step_definitions/room_booking_management_steps.rb index 75e61fb..edef432 100644 --- a/features/step_definitions/room_booking_management_steps.rb +++ b/features/step_definitions/room_booking_management_steps.rb @@ -14,9 +14,10 @@ row = find('tr', text: "#{timeslot.start_time} - #{timeslot.end_time}") room_headers = all('th') room_header_index = room_headers.find_index { |header| header.text == "#{building} #{room}" } - room_cell = row.all('td')[room_header_index] - room_cell.click_button("BL") - + room_cell = row.all('td')[room_header_index-1] + room_cell.find_button('BL').click + + end From 1899a2ee1b3f8028307e8bcd172dbb910a12e120 Mon Sep 17 00:00:00 2001 From: kingofikings441 Date: Wed, 6 Nov 2024 15:28:00 -0600 Subject: [PATCH 8/8] cucumber finish --- features/room_booking_management.feature | 11 ++++++++-- .../room_booking_management_steps.rb | 22 ++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/features/room_booking_management.feature b/features/room_booking_management.feature index e24558b..2091057 100644 --- a/features/room_booking_management.feature +++ b/features/room_booking_management.feature @@ -11,10 +11,17 @@ Feature: Room Booking Management | day | start_time | end_time | slot_type | | MWF | 09:00 | 10:00 | "LEC" | | MW | 09:00 | 10:00 | "LEC" | + | F | 09:00 | 10:00 | "LEC" | And a room booking exists for "Sched 1" with room "BLDG1" "101" at "09:00" that is available When I visit the room bookings page for "Sched 1" And I toggle availability for the room booking in "BLDG1" "101" at "09:00" - Then the booking in "BLDG1" "101" at "09:00" should be unavailable - And overlapping bookings should also be unavailable \ No newline at end of file + Then the booking in "BLDG1" "101" at "09:00" "MWF" should be unavailable + + When I click "MW" + And I toggle unavailability for the room booking in "BLDG1" "101" at "09:00" + + Then the booking in "BLDG1" "101" at "09:00" "F" should be unavailable + And the booking in "BLDG1" "101" at "09:00" "MW" should be available + And the booking in "BLDG1" "101" at "09:00" "MWF" should be available \ No newline at end of file diff --git a/features/step_definitions/room_booking_management_steps.rb b/features/step_definitions/room_booking_management_steps.rb index edef432..9d10936 100644 --- a/features/step_definitions/room_booking_management_steps.rb +++ b/features/step_definitions/room_booking_management_steps.rb @@ -15,18 +15,30 @@ room_headers = all('th') room_header_index = room_headers.find_index { |header| header.text == "#{building} #{room}" } room_cell = row.all('td')[room_header_index-1] - room_cell.find_button('BL').click - - + room_cell.find_button('BL').click end +When('I toggle unavailability for the room booking in {string} {string} at {string}') do |building, room, start| + timeslot=TimeSlot.find_by(start_time: start) + row = find('tr', text: "#{timeslot.start_time} - #{timeslot.end_time}") + room_headers = all('th') + room_header_index = room_headers.find_index { |header| header.text == "#{building} #{room}" } + room_cell = row.all('td')[room_header_index-1] + room_cell.find_button('U').click +end -Then('the booking in {string} {string} at {string} should be unavailable') do | building, room, start| +Then('the booking in {string} {string} at {string} {string} should be unavailable') do | building, room, start, days| expect(RoomBooking.find_by( room: Room.find_by(schedule_id: @schedule.id, building_code: building, room_number: room), - time_slot: TimeSlot.find_by(start_time: start) + time_slot: TimeSlot.find_by(start_time: start, day: days) ).is_available).to eq(false) end +Then('the booking in {string} {string} at {string} {string} should be available') do | building, room, start, days| + expect(RoomBooking.find_by( + room: Room.find_by(schedule_id: @schedule.id, building_code: building, room_number: room), + time_slot: TimeSlot.find_by(start_time: start, day: days) + ).is_available).to eq(true) +end Then('overlapping bookings should also be unavailable') do pending # Write code here that turns the phrase above into concrete actions