From a319d061e41abe32f5c0d8e667cc9b6f4abe5389 Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Sat, 25 Nov 2023 23:06:38 -0400 Subject: [PATCH 01/44] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 6797b4469..9b0266ea5 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/uwidcit/flaskmvc) +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Ara-Ara-Arabiansss/CodeCraftersProject-Refactored) Deploy to Render From ad0b4701840788cd38681d4aaa8cc2ef345d7b75 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 26 Nov 2023 03:18:32 +0000 Subject: [PATCH 02/44] test comment --- App/models/student.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/models/student.py b/App/models/student.py index a0445ecb1..70d75ea72 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -19,6 +19,6 @@ def get_json(self): return{'student_id': self.id, 'name': self.name, 'program' : self.program_id - + #test commment } From bbc16c9f0467c28af21de868108eee391a6abb42 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 26 Nov 2023 03:20:22 +0000 Subject: [PATCH 03/44] anothre test comment --- App/models/student.py | 1 + 1 file changed, 1 insertion(+) diff --git a/App/models/student.py b/App/models/student.py index 70d75ea72..cefe42a28 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -21,4 +21,5 @@ def get_json(self): 'program' : self.program_id #test commment } +#another test comment From 6b0beb750e6f088257108d24aee0da125d3a9eb8 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Mon, 27 Nov 2023 04:46:35 +0000 Subject: [PATCH 04/44] added 2 columns to course model --- App/models/courses.py | 2 ++ App/models/student.py | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/App/models/courses.py b/App/models/courses.py index c198814c0..7fbd4385c 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -7,6 +7,8 @@ class Course(db.Model): courseName = db.Column(db.String(25)) credits = db.Column(db.Integer) rating = db.Column(db.Integer) + semester = db.Column(db.Integer) + level = db.Column(db.Integer) #the degree year that the course is typically taken offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) diff --git a/App/models/student.py b/App/models/student.py index cefe42a28..eacd0429d 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -17,9 +17,8 @@ def __init__(self, username, password, name, program_id): def get_json(self): return{'student_id': self.id, - 'name': self.name, + 'name': self.name, 'program' : self.program_id - #test commment + } -#another test comment From 56d9b78c72cfd3e614fda1ba8003e8c57a3b2b34 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Tue, 28 Nov 2023 03:35:12 +0000 Subject: [PATCH 05/44] refactoring, add list_courses to course view --- App/controllers/courses.py | 2 ++ App/controllers/coursesOfferedPerSem.py | 4 ++-- App/models/courses.py | 4 ++++ App/views/__init__.py | 3 ++- App/views/courses.py | 27 +++++++++++++++++++++++++ App/views/staff.py | 3 +++ App/views/student.py | 2 +- wsgi.py | 6 +++++- 8 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 App/views/courses.py diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 3d285f0f1..8302fe292 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -76,5 +76,7 @@ def get_ratings(code): course = get_course_by_courseCode(code) return course.rating if course else 0 +def list_all_courses(): + return (Course.query.all()) diff --git a/App/controllers/coursesOfferedPerSem.py b/App/controllers/coursesOfferedPerSem.py index d82985c6e..e0a10c427 100644 --- a/App/controllers/coursesOfferedPerSem.py +++ b/App/controllers/coursesOfferedPerSem.py @@ -26,8 +26,8 @@ def isCourseOffered(courseCode): course = CoursesOfferedPerSem.query.filter_by(code=courseCode).first() return True if course else False -def get_all_courses(): - return CoursesOfferedPerSem.query.all() +# def get_all_courses(): +# return CoursesOfferedPerSem.query.all() def get_all_OfferedCodes(): offered = get_all_courses() diff --git a/App/models/courses.py b/App/models/courses.py index 7fbd4385c..d42173876 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -28,6 +28,10 @@ def get_json(self): return{ 'Course Code:': self.courseCode, 'Course Name: ': self.courseName, + 'Credits: ': self.credits, + 'Semester: ': self.semester, + 'Level: ': self.level, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, + 'Prerequisites: ': [prereq.get_json() for prereq in self.prerequisites] } \ No newline at end of file diff --git a/App/views/__init__.py b/App/views/__init__.py index 756127bb3..18eeaa987 100644 --- a/App/views/__init__.py +++ b/App/views/__init__.py @@ -5,6 +5,7 @@ from .auth import auth_views from .staff import staff_views from .student import student_views +from .courses import course_views -views = [user_views, index_views, auth_views, staff_views, student_views] +views = [user_views, index_views, auth_views, staff_views, student_views, course_views] # blueprints must be added to this list \ No newline at end of file diff --git a/App/views/courses.py b/App/views/courses.py new file mode 100644 index 000000000..68698a314 --- /dev/null +++ b/App/views/courses.py @@ -0,0 +1,27 @@ +from flask import Blueprint, render_template, jsonify, request, send_from_directory, flash, redirect, url_for +from flask_jwt_extended import jwt_required, current_user as jwt_current_user +from flask_login import current_user, login_required +from App.models import Program, ProgramCourses + +from.index import index_views + +from App.controllers import ( + list_all_courses, + create_course + +) + +course_views = Blueprint('course_views', __name__, template_folder='../templates') + + +@course_views.route('/course', methods = ["GET"]) +def list_courses_json(): + course_list = list_all_courses() + course_json = ([course.get_json() for course in course_list]) + + return jsonify(course_json) + +@course_views.route('course', methods = ['POST']) +def new_course(): + data = request.json() + create_course(data['code'], data['name'], data['credits'], data['rating'], data['prereqs'].split(",")) diff --git a/App/views/staff.py b/App/views/staff.py index 91b134725..b0568053f 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -31,6 +31,9 @@ def getOfferedCourses(): listing=get_all_OfferedCodes() return jsonify({'message':'Success', 'offered_courses':listing}), 200 + + + @staff_views.route('/staff/program', methods=['POST']) @login_required def addProgram(): diff --git a/App/views/student.py b/App/views/student.py index 927928cc5..4a0cb1e33 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -109,4 +109,4 @@ def create_student_plan_route(): - + diff --git a/wsgi.py b/wsgi.py index be2229779..ebfc8befd 100644 --- a/wsgi.py +++ b/wsgi.py @@ -28,7 +28,8 @@ get_allCore, addCourseToPlan, get_student_by_id, - generator + generator, + list_all_courses ) test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] @@ -361,6 +362,9 @@ def addProgramCourse(programname): # newcourse = create_course(file_path) # print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') +@course.command('all', help = 'get all the courses in the db') +def list_courses(): + print(list_all_courses()) @course.command('prereqs', help='Create a new course') @click.argument('code', type=str) From deac6d58818d7c7037354b1d71b41673e821bbfe Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Tue, 28 Nov 2023 03:40:18 +0000 Subject: [PATCH 06/44] minor fix in courses.py view --- App/views/courses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/views/courses.py b/App/views/courses.py index 68698a314..f33f53a10 100644 --- a/App/views/courses.py +++ b/App/views/courses.py @@ -21,7 +21,7 @@ def list_courses_json(): return jsonify(course_json) -@course_views.route('course', methods = ['POST']) +@course_views.route('/course', methods = ['POST']) def new_course(): data = request.json() create_course(data['code'], data['name'], data['credits'], data['rating'], data['prereqs'].split(",")) From b55356379171973a5db432f3d27135bec3f72370 Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Mon, 27 Nov 2023 23:46:22 -0400 Subject: [PATCH 07/44] Update wsgi.py --- wsgi.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wsgi.py b/wsgi.py index ebfc8befd..5857e8227 100644 --- a/wsgi.py +++ b/wsgi.py @@ -403,4 +403,8 @@ def allSemCourses(): print("empty") -app.cli.add_command(course) \ No newline at end of file +app.cli.add_command(course) + + + +#this is a test to play with merging from main to my own branch From 7ae3e5f87559c59c1dcff4a61d48152a658cd2b1 Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Tue, 28 Nov 2023 00:27:27 -0400 Subject: [PATCH 08/44] Update wsgi.py --- wsgi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wsgi.py b/wsgi.py index 5857e8227..7642d024e 100644 --- a/wsgi.py +++ b/wsgi.py @@ -408,3 +408,4 @@ def allSemCourses(): #this is a test to play with merging from main to my own branch +#lalalalalal another test comment to play with merging main to me pwon branch remember to delete lol From 96abba6143696d3c010cd1aebe7121d42f18eb8e Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Tue, 28 Nov 2023 04:31:56 +0000 Subject: [PATCH 09/44] removed test comments in wsgi --- wsgi.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/wsgi.py b/wsgi.py index 7642d024e..cc524d44d 100644 --- a/wsgi.py +++ b/wsgi.py @@ -406,6 +406,3 @@ def allSemCourses(): app.cli.add_command(course) - -#this is a test to play with merging from main to my own branch -#lalalalalal another test comment to play with merging main to me pwon branch remember to delete lol From 793cdc58e9c699092fb737272019acc5cba82dde Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:15:42 -0400 Subject: [PATCH 10/44] Update wsgi.py --- wsgi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wsgi.py b/wsgi.py index cc524d44d..b5fef34b9 100644 --- a/wsgi.py +++ b/wsgi.py @@ -405,4 +405,5 @@ def allSemCourses(): app.cli.add_command(course) +#lalalal this is a test comment From 5e55c9f80aa0ec1de70adfd521c5bb06cf73933c Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Tue, 28 Nov 2023 20:21:10 +0000 Subject: [PATCH 11/44] removed coursesofferedpersem among other things --- App/controllers/courses.py | 13 ++++++ App/controllers/coursesOfferedPerSem.py | 58 ++++++++++++------------- App/controllers/staff.py | 11 +++++ App/models/__init__.py | 2 +- App/models/courses.py | 3 +- App/models/coursesOfferedPerSem.py | 24 +++++----- App/models/department.py | 0 App/models/staff.py | 2 + wsgi.py | 24 +++++----- 9 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 App/models/department.py diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 8302fe292..8ce651705 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -63,6 +63,19 @@ def courses_Sorted_byRating_Objects(): return Course.query.order_by(Course.rating.asc()).all() +def isCourseOffered(courseCode): + course = Course.query.filter_by(code=courseCode).first() + return course.offered + +def get_all_OfferedCodes(): + offered = list_all_courses() + offeredcodes=[] + + for c in offered: + offeredcodes.append(c.code) + + return offeredcodes + def get_prerequisites(code): course = get_course_by_courseCode(code) prereqs = get_all_prerequisites(course.courseName) diff --git a/App/controllers/coursesOfferedPerSem.py b/App/controllers/coursesOfferedPerSem.py index e0a10c427..5ab61a731 100644 --- a/App/controllers/coursesOfferedPerSem.py +++ b/App/controllers/coursesOfferedPerSem.py @@ -1,39 +1,39 @@ -from App.models import CoursesOfferedPerSem -from App.controllers import get_course_by_courseCode -from App.database import db +# from App.models import CoursesOfferedPerSem +# from App.controllers import get_course_by_courseCode +# from App.database import db -def addSemesterCourses(courseCode): - course = get_course_by_courseCode(courseCode) - if course: - semCourses = CoursesOfferedPerSem(courseCode) - db.session.add(semCourses) - db.session.commit() - return semCourses - else: - print("Course not found") +# def addSemesterCourses(courseCode): +# course = get_course_by_courseCode(courseCode) +# if course: +# semCourses = CoursesOfferedPerSem(courseCode) +# db.session.add(semCourses) +# db.session.commit() +# return semCourses +# else: +# print("Course not found") -def delete_all_records(): - try: - db.session.query(CoursesOfferedPerSem).delete() - db.session.commit() - print("All records deleted successfully.") +# def delete_all_records(): +# try: +# db.session.query(CoursesOfferedPerSem).delete() +# db.session.commit() +# print("All records deleted successfully.") - except Exception as e: - db.session.rollback() - print(f"An error occurred: {str(e)}") +# except Exception as e: +# db.session.rollback() +# print(f"An error occurred: {str(e)}") -def isCourseOffered(courseCode): - course = CoursesOfferedPerSem.query.filter_by(code=courseCode).first() - return True if course else False +# def isCourseOffered(courseCode): +# course = CoursesOfferedPerSem.query.filter_by(code=courseCode).first() +# return True if course else False # def get_all_courses(): # return CoursesOfferedPerSem.query.all() -def get_all_OfferedCodes(): - offered = get_all_courses() - offeredcodes=[] +# def get_all_OfferedCodes(): +# offered = get_all_courses() +# offeredcodes=[] - for c in offered: - offeredcodes.append(c.code) +# for c in offered: +# offeredcodes.append(c.code) - return offeredcodes +# return offeredcodes diff --git a/App/controllers/staff.py b/App/controllers/staff.py index c90b3eec1..86ee70c40 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -19,6 +19,17 @@ def get_staff_by_id(ID): return Staff.query.filter_by(id=ID).first() +def addSemesterCourses(courseCode): + course = get_course_by_courseCode(courseCode) + if course: + semCourses = CoursesOfferedPerSem(courseCode) + db.session.add(semCourses) + db.session.commit() + return semCourses + else: + print("Course not found") + + # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/__init__.py b/App/models/__init__.py index c8b645206..5be95bde5 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -3,7 +3,7 @@ from .program import * from .staff import * from .student import * -from .coursesOfferedPerSem import * +# from .coursesOfferedPerSem import * from .programCourses import * from .prerequisites import * from .studentCourseHistory import * diff --git a/App/models/courses.py b/App/models/courses.py index d42173876..8b01ab58a 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -9,8 +9,9 @@ class Course(db.Model): rating = db.Column(db.Integer) semester = db.Column(db.Integer) level = db.Column(db.Integer) #the degree year that the course is typically taken + offered = db.Column(db.Boolean) #whether or not the course is currently offered - offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) + # offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) diff --git a/App/models/coursesOfferedPerSem.py b/App/models/coursesOfferedPerSem.py index b3dcb1f5d..59a919952 100644 --- a/App/models/coursesOfferedPerSem.py +++ b/App/models/coursesOfferedPerSem.py @@ -1,16 +1,16 @@ -from App.database import db +# from App.database import db -class CoursesOfferedPerSem(db.Model): - id = db.Column(db.Integer, primary_key=True) - code = db.Column(db.ForeignKey('course.courseCode')) +# class CoursesOfferedPerSem(db.Model): +# id = db.Column(db.Integer, primary_key=True) +# code = db.Column(db.ForeignKey('course.courseCode')) - associated_course = db.relationship('Course', back_populates='offered', overlaps="courses") +# # associated_course = db.relationship('Course', back_populates='offered', overlaps="courses") - def __init__(self, courseCode): - self.code = courseCode +# def __init__(self, courseCode): +# self.code = courseCode - def get_json(self): - return{ - 'ID:': self.id, - 'Course Code:': self.code - } +# def get_json(self): +# return{ +# 'ID:': self.id, +# 'Course Code:': self.code +# } diff --git a/App/models/department.py b/App/models/department.py new file mode 100644 index 000000000..e69de29bb diff --git a/App/models/staff.py b/App/models/staff.py index bb6013857..1bedcbd1d 100644 --- a/App/models/staff.py +++ b/App/models/staff.py @@ -6,6 +6,8 @@ class Staff(User): id = db.Column(db.String(10), db.ForeignKey('user.id'), primary_key=True) name = db.Column(db.String(50)) + # courses = db.relationship('StudentCourseHistory', backref='student', lazy=True) + def __init__(self, password, staff_id, name): super().__init__(staff_id, password) diff --git a/wsgi.py b/wsgi.py index cc524d44d..0914260bd 100644 --- a/wsgi.py +++ b/wsgi.py @@ -71,7 +71,7 @@ def initialize(): with open(file_path1, 'r') as file: for i, line in enumerate(file): line = line.strip() - addSemesterCourses(line) + # addSemesterCourses(line) @@ -184,12 +184,12 @@ def add_program_requirements(name,code,num): response=create_programCourse(name, code, num) print(response) -@staff_cli.command("addofferedcourse",help='testing add courses offered feature') -@click.argument("code", type=str) -def add_offered_course(code): - course=addSemesterCourses(code) - if course: - print(f'Course details: {course}') +# @staff_cli.command("addofferedcourse",help='testing add courses offered feature') +# @click.argument("code", type=str) +# def add_offered_course(code): +# course=addSemesterCourses(code) +# if course: +# print(f'Course details: {course}') app.cli.add_command(staff_cli) @@ -386,11 +386,11 @@ def get_course(code): for r in prereqs: print(f'{r.prereq_courseCode}') -@course.command('nextsem', help='Add a course to offered courses') -@click.argument('code', type=str) -def add_course(code): - course = addSemesterCourses(code) - print(f'Course Name: {course.courseName}') if course else print(f'error') +# @course.command('nextsem', help='Add a course to offered courses') +# @click.argument('code', type=str) +# def add_course(code): +# course = addSemesterCourses(code) +# print(f'Course Name: {course.courseName}') if course else print(f'error') @course.command('getNextSemCourses', help='Get all the courses offered next semester') def allSemCourses(): From f92b6c5ad98ae0fdd544461277f14c7b35bf28df Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Tue, 28 Nov 2023 21:16:58 +0000 Subject: [PATCH 12/44] got create course view working --- App/controllers/courses.py | 11 +++--- App/models/courses.py | 8 +++-- App/views/courses.py | 12 +++++-- testData/courseData.csv | 72 +++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 8ce651705..3494ec9dd 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -10,10 +10,10 @@ def createPrerequistes(prereqs, courseName): if prereq_course: create_prereq(prereq_code,courseName) -def create_course(code, name, rating, credits, prereqs): +def create_course(code, name, credits, rating, semester, level, offered, prereqs): already = get_course_by_courseCode(code) if already is None: - course = Course(code, name, rating, credits) + course = Course(code, name, credits, rating, semester, level, offered) if prereqs: createPrerequistes(prereqs, name) @@ -34,10 +34,13 @@ def createCoursesfromFile(file_path): courseName = row["courseName"] credits = int(row["numCredits"]) rating = int(row["rating"]) + semester = int(row["semster"]) + level = int(row["level"]) + offered = bool(row["offered"]) prerequisites_codes = row["preReqs"].split(',') + # create_course(courseCode, courseName, rating, credits, prerequisites_codes) + create_course(courseCode, courseName, credits, rating, semester, level, offered, prerequisites_codes) - create_course(courseCode, courseName, rating, credits, prerequisites_codes) - except FileNotFoundError: print("File not found.") diff --git a/App/models/courses.py b/App/models/courses.py index 8b01ab58a..2872300e0 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -19,11 +19,15 @@ class Course(db.Model): # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) - def __init__(self, code, name, rating, credits): + def __init__(self, code, name, credits, rating, semester, level, offered): self.courseCode = code self.courseName = name - self.rating = rating self.credits = credits + self.rating = rating + self.semester = semester + self.level = level + self.offered = offered + def get_json(self): return{ diff --git a/App/views/courses.py b/App/views/courses.py index f33f53a10..1c07e32cc 100644 --- a/App/views/courses.py +++ b/App/views/courses.py @@ -23,5 +23,13 @@ def list_courses_json(): @course_views.route('/course', methods = ['POST']) def new_course(): - data = request.json() - create_course(data['code'], data['name'], data['credits'], data['rating'], data['prereqs'].split(",")) + data = request.json + course = create_course(data['code'], + data['name'], + data['credits'], + data['rating'], + data['semester'], + data['level'], + data['offered'], + data['prereqs']) + return "Successfully Created course!" diff --git a/testData/courseData.csv b/testData/courseData.csv index 9ef96328e..0036da018 100644 --- a/testData/courseData.csv +++ b/testData/courseData.csv @@ -1,36 +1,36 @@ -courseCode,courseName,numCredits,rating,preReqs -COMP1600,Introduction to Computing Concepts,3,4, -COMP1601,Programming 1,3,1, -COMP1602,Programming 2,3,4, -COMP1603,Programming 3,3,3, -COMP1604,Mathematics for Computing,3,2, -INFO1600, Introduction to Information Technology Concepts,3,1, -INFO1601,Introduction to WWW Programming,3,1, -MATH1115,Fundamental Mathematics for the General Sciences 1,3,1, -COMP2611,Data Structures,3,5,COMP1602 -COMP2601,Computer Architecture,3,5,COMP1600 -MATH2250,Industrial Statistics,3,4, -COMP3605,Introduction to Data Analytics,3,3,"COMP2611,MATH2250" -COMP3610,Big Data Analytics,3,5,COMP3605 -COMP2602,Computer Networks,3,1,COMP1600 -COMP2603,Object-Oriented Programming 1,3,1,COMP1603 -COMP2604,Operating Systems,3,5,COMP1600 -COMP2605,Enterprise Database Systems,3,2,COMP1602 -COMP2606,Software Engineering 1,3,3,COMP1602 -INFO2602,Web Programming and Technologies 1,3,3,INFO1601 -INFO2604,Information Systems Security,3,3,COMP1602 -COMP3601,Design and Analysis of Algorithms,3,5,COMP2611 -COMP3602,Theory of Computing,3,5,COMP1604 -COMP3603,Human-Computer Interaction,3,1,COMP2606 -INFO3604,Project,3,5,"INFO2600,COMP2606" -FOUN1101,Caribbean Civilization,3,1, -FOUN1105,Scientific and Technical Writing,3,1, -FOUN1301,"Law, Governance, Economy and Society",3,1, -COMP3606,Wireless and Mobile Computing,3,3,"COMP2602,INFO2601" -COMP3607,Object-Oriented Programming II,3,2,COMP2603 -COMP3608,Intelligent Systems,3,4,"COMP2611,MATH2250" -COMP3609,Game Programming,3,1,"COMP2603,COMP2606" -COMP3611,Modelling and Simulation,3,5,MATH2250 -COMP3612,Special Topics in Computer,3,5,"COMP2611,COMP2603" -COMP3613,Software Engineering 2,3,5,COMP2606 -INFO2606, Internship, 6, 1, +courseCode,courseName,numCredits,rating,semster,level,offered,preReqs +COMP1600,Introduction to Computing Concepts,3,4,1,1,TRUE, +COMP1601,Programming 1,3,1,1,1,TRUE, +COMP1602,Programming 2,3,4,2,1,TRUE, +COMP1603,Programming 3,3,3,2,1,TRUE, +COMP1604,Mathematics for Computing,3,2,2,1,TRUE, +INFO1600, Introduction to Information Technology Concepts,3,1,1,1,TRUE, +INFO1601,Introduction to WWW Programming,3,1,2,1,TRUE, +MATH1115,Fundamental Mathematics for the General Sciences 1,3,1,1,1,TRUE, +COMP2611,Data Structures,3,5,1,2,TRUE,COMP1602 +COMP2601,Computer Architecture,3,5,1,2,TRUE,COMP1600 +MATH2250,Industrial Statistics,3,4,1,2,TRUE, +COMP3605,Introduction to Data Analytics,3,3,1,3,TRUE,"COMP2611,MATH2250" +COMP3610,Big Data Analytics,3,5,2,3,TRUE,COMP3605 +COMP2602,Computer Networks,3,1,1,2,TRUE,COMP1600 +COMP2603,Object-Oriented Programming 1,3,1,1,2,TRUE,COMP1603 +COMP2604,Operating Systems,3,5,1,2,TRUE,COMP1600 +COMP2605,Enterprise Database Systems,3,2,1,2,TRUE,COMP1602 +COMP2606,Software Engineering 1,3,3,1,2,TRUE,COMP1602 +INFO2602,Web Programming and Technologies 1,3,3,1,2,TRUE,INFO1601 +INFO2604,Information Systems Security,3,3,2,2,TRUE,COMP1602 +COMP3601,Design and Analysis of Algorithms,3,5,1,3,TRUE,COMP2611 +COMP3602,Theory of Computing,3,5,1,3,TRUE,COMP1604 +COMP3603,Human-Computer Interaction,3,1,1,3,TRUE,COMP2606 +INFO3604,Project,3,5,2,3,TRUE,"INFO2600,COMP2606" +FOUN1101,Caribbean Civilization,3,1,1,1,TRUE, +FOUN1105,Scientific and Technical Writing,3,1,1,1,TRUE, +FOUN1301,"Law, Governance, Economy and Society",3,1,2,1,TRUE, +COMP3606,Wireless and Mobile Computing,3,3,1,3,TRUE,"COMP2602,INFO2601" +COMP3607,Object-Oriented Programming II,3,2,1,3,TRUE,COMP2603 +COMP3608,Intelligent Systems,3,4,2,3,TRUE,"COMP2611,MATH2250" +COMP3609,Game Programming,3,1,2,3,TRUE,"COMP2603,COMP2606" +COMP3611,Modelling and Simulation,3,5,2,3,TRUE,MATH2250 +COMP3612,Special Topics in Computer,3,5,2,3,TRUE,"COMP2611,COMP2603" +COMP3613,Software Engineering 2,3,5,2,3,TRUE,COMP2606 +INFO2606, Internship,6,1,3,2,TRUE, From b1dd290acf69cf493c75287e8b27c3bbc13125bc Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Thu, 30 Nov 2023 05:22:32 +0000 Subject: [PATCH 13/44] fixed error where prereqs added to wrong courses --- App/controllers/courses.py | 52 ++++++++++++++++++++++++------ App/controllers/prerequistes.py | 12 +++++-- App/models/__init__.py | 3 +- App/models/coursePlanCourses.py | 2 +- App/models/courses.py | 8 +++-- App/models/prerequisites.py | 31 ++++++++++++------ App/models/programCourses.py | 6 +++- App/models/studentCourseHistory.py | 2 +- App/views/courses.py | 3 +- wsgi.py | 6 ++-- 10 files changed, 93 insertions(+), 32 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 3494ec9dd..657ae6e08 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -3,23 +3,57 @@ from App.database import db import json, csv -def createPrerequistes(prereqs, courseName): - for prereq_code in prereqs: - prereq_course = Course.query.filter_by(courseCode=prereq_code).first() +def createPrerequistes(courseCode, preReqCodes): + print("Course: " + courseCode) + + course = Course.query.filter_by(courseCode = courseCode).first() + + + if course: + for prereq in preReqCodes: + prerequisite = Course.query.filter_by(courseCode = prereq).first() + + if prerequisite: + # create_prereq(courseCode, prereq) + new_prereq = Prerequisites(course_code=course, prereq_code= prereq) + course.prerequisites.append(new_prereq) + + try: + db.session.add(new_prereq) + db.session.commit() + except Exception as e: + db.session.rollback() + print("There was an error...") + print(e) + + + else: + print("Course " + prereq + " not found. Create a new course before adding it as a prerequisite.") + # return ("unable to add prereq") - if prereq_course: - create_prereq(prereq_code,courseName) + else: + return "Unable to add prerequisite. Course not found." + + + + def create_course(code, name, credits, rating, semester, level, offered, prereqs): + + already = get_course_by_courseCode(code) if already is None: course = Course(code, name, credits, rating, semester, level, offered) - - if prereqs: - createPrerequistes(prereqs, name) - db.session.add(course) db.session.commit() + + + if (prereqs[0] != ""): + createPrerequistes(code, prereqs) + + + + return course else: return None diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 671db33c8..0aecc2259 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -1,9 +1,15 @@ from App.models import Prerequisites from App.database import db -def create_prereq(prereqCode, courseName): - prereq = Prerequisites(prereqCode, courseName) - db.session.add(prereq) +# def create_prereq(prereqCode, courseName): +# prereq = Prerequisites(prereqCode, courseName) +# db.session.add(prereq) +# db.session.commit() + +def create_prereq(course, preReqCode): + new_prereq = Prerequisites(course, preReqCode) + # print(new_prereq.course) + db.session.add(new_prereq) db.session.commit() def get_all_prerequisites(courseName): diff --git a/App/models/__init__.py b/App/models/__init__.py index 5be95bde5..22956967f 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -1,11 +1,12 @@ from .user import * +from .prerequisites import * from .courses import * from .program import * from .staff import * from .student import * # from .coursesOfferedPerSem import * from .programCourses import * -from .prerequisites import * + from .studentCourseHistory import * from .coursePlanCourses import * from .coursePlan import * diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index e4f982a9f..4e7e63880 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -4,7 +4,7 @@ class CoursePlanCourses(db.Model): id = db.Column(db.Integer, primary_key=True) planId = db.Column(db.ForeignKey('course_plan.planId')) - code = db.Column(db.ForeignKey('course.courseCode')) + code = db.Column(db.ForeignKey('courses.courseCode')) # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") diff --git a/App/models/courses.py b/App/models/courses.py index 2872300e0..d8f243bc9 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -1,8 +1,12 @@ +# from App.models import Prerequisites from App.database import db -from App.models import prerequisites +from App.models import Prerequisites + import json class Course(db.Model): + __tablename__ = 'courses' + courseCode = db.Column(db.String(8), primary_key=True) courseName = db.Column(db.String(25)) credits = db.Column(db.Integer) @@ -14,7 +18,7 @@ class Course(db.Model): # offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) - prerequisites = db.relationship('Prerequisites', backref='courses', lazy = True) + prerequisites = db.relationship('Prerequisites', foreign_keys=[Prerequisites.course_code], lazy = True) # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py index 4858c747a..b1492b6c5 100644 --- a/App/models/prerequisites.py +++ b/App/models/prerequisites.py @@ -1,21 +1,32 @@ from App.database import db + + class Prerequisites(db.Model): + id = db.Column(db.Integer, primary_key=True) - prereq_courseCode = db.Column(db.ForeignKey('course.courseCode')) - courseName = db.Column(db.String(25)) + # courseName = db.Column(db.String(25)) + + course_code = db.Column(db.String(8), db.ForeignKey('courses.courseCode')) + prereq_code = db.Column(db.String(8), db.ForeignKey('courses.courseCode')) + + # associated_course = db.relationship('Course', back_populates='prerequisites', overlaps="courses") + + # course = db.relationship("Course", foreign_keys=[course_code]) + # prerequisite = db.relationship("Course", foreign_keys=[prereq_code]) + + + def __init__(self, course_code, prereq_code): + self.course_code = course_code + self.prereq_code = prereq_code - associated_course = db.relationship('Course', back_populates='prerequisites', overlaps="courses") - - + - def __init__(self, prereqCode, nameofCourse): - self.prereq_courseCode = prereqCode - self.courseName = nameofCourse def get_json(self): return{ 'prereq_id': self.id, - 'prerequisite_courseCode': self.prereq_courseCode, - 'prerequisite_course':self.courseName + 'prerequisite_courseCode': self.prereq_code, + # 'prerequisite_name': self.prerequisite.courseName + # 'prerequisite_course':self.courseName } \ No newline at end of file diff --git a/App/models/programCourses.py b/App/models/programCourses.py index c74cf1137..201c05a8e 100644 --- a/App/models/programCourses.py +++ b/App/models/programCourses.py @@ -1,9 +1,13 @@ from App.database import db + + + class ProgramCourses(db.Model): + __tablename__ ='program_courses' id = db.Column(db.Integer, primary_key=True) program_id = db.Column(db.ForeignKey('program.id')) - code = db.Column(db.ForeignKey('course.courseCode')) + code = db.Column(db.ForeignKey('courses.courseCode')) courseType = db.Column(db.Integer) associated_program = db.relationship('Program', back_populates='courses', overlaps="program") diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index b5d9e8528..339594391 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -4,7 +4,7 @@ class StudentCourseHistory(db.Model): __tablename__ = 'studentCourses' id = db.Column(db.Integer, primary_key=True) studentID = db.Column(db.ForeignKey('student.id')) - code = db.Column(db.ForeignKey('course.courseCode')) + code = db.Column(db.ForeignKey('courses.courseCode')) associated_course = db.relationship('Course', back_populates='students', overlaps="courses") associated_student = db.relationship('Student', back_populates='courses', overlaps="student") diff --git a/App/views/courses.py b/App/views/courses.py index 1c07e32cc..f7a5b514b 100644 --- a/App/views/courses.py +++ b/App/views/courses.py @@ -24,6 +24,7 @@ def list_courses_json(): @course_views.route('/course', methods = ['POST']) def new_course(): data = request.json + course = create_course(data['code'], data['name'], data['credits'], @@ -32,4 +33,4 @@ def new_course(): data['level'], data['offered'], data['prereqs']) - return "Successfully Created course!" + return "Successfully Created course!" \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 0914260bd..6b8bcd35f 100644 --- a/wsgi.py +++ b/wsgi.py @@ -54,9 +54,9 @@ def initialize(): create_student(816, "boo", "testing", "Computer Science Major") create_staff("adminpass","999", "admin") - for c in test1: - addCoursetoHistory(816, c) - print('Student course history updated') + # for c in test1: + # addCoursetoHistory(816, c) + # print('Student course history updated') with open(file_path, 'r') as file: for i, line in enumerate(file): From 6443f16a68c5a904239a1a5594f28cc319efa9b5 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Thu, 30 Nov 2023 05:35:32 +0000 Subject: [PATCH 14/44] minor refactoring --- App/controllers/courses.py | 18 +----------------- App/controllers/prerequistes.py | 18 +++++++++++++----- App/models/courses.py | 3 --- App/models/prerequisites.py | 14 +------------- 4 files changed, 15 insertions(+), 38 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 657ae6e08..156506cd8 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -4,32 +4,16 @@ import json, csv def createPrerequistes(courseCode, preReqCodes): - print("Course: " + courseCode) - course = Course.query.filter_by(courseCode = courseCode).first() - if course: for prereq in preReqCodes: prerequisite = Course.query.filter_by(courseCode = prereq).first() if prerequisite: - # create_prereq(courseCode, prereq) - new_prereq = Prerequisites(course_code=course, prereq_code= prereq) - course.prerequisites.append(new_prereq) - - try: - db.session.add(new_prereq) - db.session.commit() - except Exception as e: - db.session.rollback() - print("There was an error...") - print(e) - - + create_prereq(course, courseCode, prereq) else: print("Course " + prereq + " not found. Create a new course before adding it as a prerequisite.") - # return ("unable to add prereq") else: return "Unable to add prerequisite. Course not found." diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 0aecc2259..847313edd 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -6,11 +6,19 @@ # db.session.add(prereq) # db.session.commit() -def create_prereq(course, preReqCode): - new_prereq = Prerequisites(course, preReqCode) - # print(new_prereq.course) - db.session.add(new_prereq) - db.session.commit() +def create_prereq(course, courseCode, prereqCode): + new_prereq = Prerequisites(course_code=course, prereq_code= prereqCode) + course.prerequisites.append(new_prereq) + + try: + db.session.add(new_prereq) + db.session.commit() + except Exception as e: + db.session.rollback() + print("There was an error...") + print(e) + + def get_all_prerequisites(courseName): return Prerequisites.query.filter(Prerequisites.courseName == courseName).all() diff --git a/App/models/courses.py b/App/models/courses.py index d8f243bc9..7f2283fde 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -15,12 +15,9 @@ class Course(db.Model): level = db.Column(db.Integer) #the degree year that the course is typically taken offered = db.Column(db.Boolean) #whether or not the course is currently offered - # offered = db.relationship('CoursesOfferedPerSem', backref ='courses', lazy=True) students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', foreign_keys=[Prerequisites.course_code], lazy = True) - - # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) def __init__(self, code, name, credits, rating, semester, level, offered): diff --git a/App/models/prerequisites.py b/App/models/prerequisites.py index b1492b6c5..ccb2f9888 100644 --- a/App/models/prerequisites.py +++ b/App/models/prerequisites.py @@ -3,30 +3,18 @@ class Prerequisites(db.Model): - id = db.Column(db.Integer, primary_key=True) - # courseName = db.Column(db.String(25)) - course_code = db.Column(db.String(8), db.ForeignKey('courses.courseCode')) prereq_code = db.Column(db.String(8), db.ForeignKey('courses.courseCode')) - # associated_course = db.relationship('Course', back_populates='prerequisites', overlaps="courses") - - # course = db.relationship("Course", foreign_keys=[course_code]) - # prerequisite = db.relationship("Course", foreign_keys=[prereq_code]) def __init__(self, course_code, prereq_code): self.course_code = course_code self.prereq_code = prereq_code - - - def get_json(self): return{ 'prereq_id': self.id, 'prerequisite_courseCode': self.prereq_code, - # 'prerequisite_name': self.prerequisite.courseName - # 'prerequisite_course':self.courseName - } \ No newline at end of file + } \ No newline at end of file From cdc70b3b4b675b3fe611bfcfd9cc7e3e4d9c33e1 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Thu, 30 Nov 2023 05:58:19 +0000 Subject: [PATCH 15/44] minor refactoring --- App/controllers/courses.py | 14 ++++++++------ App/controllers/prerequistes.py | 10 ++++++++-- App/views/courses.py | 12 +++++++++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 156506cd8..dbbfb20df 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -1,9 +1,9 @@ -from App.models import Course, Prerequisites +from App.models import Course from App.controllers.prerequistes import (create_prereq, get_all_prerequisites) from App.database import db import json, csv -def createPrerequistes(courseCode, preReqCodes): +def createPrerequisites(courseCode, preReqCodes): course = Course.query.filter_by(courseCode = courseCode).first() if course: @@ -11,14 +11,16 @@ def createPrerequistes(courseCode, preReqCodes): prerequisite = Course.query.filter_by(courseCode = prereq).first() if prerequisite: - create_prereq(course, courseCode, prereq) + success = create_prereq(course, prereq) else: - print("Course " + prereq + " not found. Create a new course before adding it as a prerequisite.") + return("Course " + prereq + " not found. Create a new course before adding it as a prerequisite.") + if (success == False): + return ("One or more prerequisites already exist for this course.") else: - return "Unable to add prerequisite. Course not found." + return ("Unable to add prerequisite. Course not found.") - + return ("Successfully added Prerequisite!") diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 847313edd..4bd3cc251 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -6,8 +6,14 @@ # db.session.add(prereq) # db.session.commit() -def create_prereq(course, courseCode, prereqCode): - new_prereq = Prerequisites(course_code=course, prereq_code= prereqCode) +def create_prereq(course, prereqCode): + exists = Prerequisites.query.filter_by(course_code= course.courseCode, prereq_code= prereqCode).first() + + if exists: + return False + + + new_prereq = Prerequisites(course_code=course.courseCode, prereq_code= prereqCode) course.prerequisites.append(new_prereq) try: diff --git a/App/views/courses.py b/App/views/courses.py index f7a5b514b..642fa828a 100644 --- a/App/views/courses.py +++ b/App/views/courses.py @@ -7,8 +7,8 @@ from App.controllers import ( list_all_courses, - create_course - + create_course, + createPrerequisites ) course_views = Blueprint('course_views', __name__, template_folder='../templates') @@ -33,4 +33,10 @@ def new_course(): data['level'], data['offered'], data['prereqs']) - return "Successfully Created course!" \ No newline at end of file + return "Successfully Created course!" + +@course_views.route('/course/prereq', methods = ['POST']) +def add_prereq(): + data = request.json + + return createPrerequisites(data['courseCode'], data['prereqCode']) \ No newline at end of file From 91a1339dfeaeb122b286f86f68107e4ffb3aa7ea Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Thu, 30 Nov 2023 06:00:49 +0000 Subject: [PATCH 16/44] minor neatening up of courses.py --- App/controllers/courses.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index dbbfb20df..aad1cd50a 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -26,25 +26,21 @@ def createPrerequisites(courseCode, preReqCodes): def create_course(code, name, credits, rating, semester, level, offered, prereqs): - already = get_course_by_courseCode(code) if already is None: course = Course(code, name, credits, rating, semester, level, offered) db.session.add(course) db.session.commit() - if (prereqs[0] != ""): - createPrerequistes(code, prereqs) + createPrerequisites(code, prereqs) - - - return course else: return None + def createCoursesfromFile(file_path): try: with open(file_path, 'r') as file: From fcfa3d37e9b486cb819d41a15831ab967bfa143a Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:54:41 -0400 Subject: [PATCH 17/44] add courseOfferings --- App/controllers/courseOfferings.py | 79 ++++++++++++++++++++++++++++++ App/controllers/staff.py | 12 ----- App/models/courseOfferings.py | 29 +++++++++++ App/views/staff.py | 44 ++++++++++++++++- wsgi.py | 43 ++++++++++++---- 5 files changed, 184 insertions(+), 23 deletions(-) create mode 100644 App/controllers/courseOfferings.py create mode 100644 App/models/courseOfferings.py diff --git a/App/controllers/courseOfferings.py b/App/controllers/courseOfferings.py new file mode 100644 index 000000000..99864d7d1 --- /dev/null +++ b/App/controllers/courseOfferings.py @@ -0,0 +1,79 @@ +from App.database import db +from .models import CourseOfferings + +def createCourseOffering(courseCode, academic_year, semester): + offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() + if offering: + print("Course offering exists already") + return None + try: + if CourseOfferings.checkAcademicYearFormat(academic_year): + if semester == 1 or semester == 2 or semester == 3: + if CourseOfferings.getCourse(courseCode): + offeredCourse = CourseOfferings(semester, academic_year, courseCode) + if offeredCourse: + db.session.add(offeredCourse) + db.session.commit() + print("Course offering created successfully") + return offeredCourse + else: + print("The new course offering could not be created") + else: + print(f"Invalid course code") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + else: + print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to add a course to the course offerings: {e}") + +def getAllCourseOfferings(): + return CourseOfferings.query.all() + +def getCourseOfferingsByYear(year): + if CourseOfferings.checkAcademicYearFormat(year): + offerings = CourseOfferings.query.filter_by(academic_year = year).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected year") + else: + print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + +def getCourseOfferingsBySemester(sem): + if sem == 1 or sem == 2 or sem == 3: + offerings = CourseOfferings.query.filter_by(semester = sem).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected semester") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + +def getCourseOfferingsByYearAndSemester(year, sem): + if CourseOfferings.checkAcademicYearFormat(year): + if sem == 1 or sem == 2 or sem == 3: + offerings = CourseOfferings.query.filter_by(semester = sem, academic_year = year).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected year and semester") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + else: + print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + +def deleteCourseOffering(courseCode, academic_year, semester): + try: + offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() + if offering: + db.session.delete(offering) + db.session.commit() + print("Course offering deleted successfully") + return True + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to delete a course from the course offerings: {e}") + return False + diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 86ee70c40..c806256df 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,7 +1,6 @@ from App.models import Program, Course, Staff from App.database import db - def create_staff(password, staff_id, name): new_staff = Staff(password, staff_id, name) db.session.add(new_staff) @@ -19,17 +18,6 @@ def get_staff_by_id(ID): return Staff.query.filter_by(id=ID).first() -def addSemesterCourses(courseCode): - course = get_course_by_courseCode(courseCode) - if course: - semCourses = CoursesOfferedPerSem(courseCode) - db.session.add(semCourses) - db.session.commit() - return semCourses - else: - print("Course not found") - - # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py new file mode 100644 index 000000000..e4aad71a0 --- /dev/null +++ b/App/models/courseOfferings.py @@ -0,0 +1,29 @@ +from App.database import db +from .courses import Course + +class CourseOfferings(db.Model): + id = db.Column(db.Integer, primary_key = True) + academic_year = db.Column(db.String, nullable=False) + semester = db.Column(db.Integer, nullable=False) + course_code = db.Column(db.String, nullable=False) + + def get_json(self): + return{ + 'id': self.id, + 'year': self.academic_year, + 'semester': self.semester, + 'course': self.course_code + } + + def getCourse(course_code): + return Course.query.filter_by(courseCode=course_code).first() + + def checkAcademicYearFormat(academic_year): + s = academic_year.split("/") + if s.size() > 2: + return False + elif int(s[0]) != int(s[1])-1: + return False + elif int(s[0]) < 2000: + return False + return True diff --git a/App/views/staff.py b/App/views/staff.py index b0568053f..dc0e3292f 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -16,7 +16,9 @@ addSemesterCourses, get_all_OfferedCodes, get_all_programCourses, - verify_staff + verify_staff, + createCourseOffering, + deleteCourseOffering ) staff_views = Blueprint('staff_views', __name__, template_folder='../templates') @@ -130,4 +132,42 @@ def addCourse(): if course: return jsonify(course.get_json()), 200 else: - return jsonify({'message': "Course addition unsucessful"}), 400 \ No newline at end of file + return jsonify({'message': "Course addition unsucessful"}), 400 + +@staff_views.route('/staff/addCourseOffering', methods=['POST']) +@login_required +def addCourseOffering(): + data=request.json + courseCode=data['code'] + year = data['year'] + sem = data['sem'] + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + offering = createCourseOffering(courseCode, year, sem) + if offering is not None: + return jsonify(offering.get_json()), 200 + else: + return jsonify({'message': "Course offering creation unsucessful"}), 400 + +@staff_views.route('/staff/removeCourseOffering', methods=['DELETE']) +@login_required +def removeCourseOffering(): + data=request.json + courseCode=data['code'] + year = data['year'] + sem = data['sem'] + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + deleted = deleteCourseOffering(courseCode, year, sem) + if deleted: + return jsonify({'message:': "Course offering deletion succesful"}), 200 + else: + return jsonify({'message': "Course offering deletion unsucessful"}), 404 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index de91e5bc9..5e992fb96 100644 --- a/wsgi.py +++ b/wsgi.py @@ -18,7 +18,9 @@ get_prerequisites, get_all_courses, create_programCourse, - addSemesterCourses, + createCourseOffering, + deleteCourseOffering, + getCourseOfferingsByYearAndSemester, create_student, create_staff, get_program_by_name, @@ -108,7 +110,16 @@ def list_user_command(format): app.cli.add_command(user_cli) # add the group to the cli - +@user_cli.command("getcourseoffering",help='testing remove courses offering feature') +@click.argument("year", type=str) +@click.argument("sem", type=int) +def get_course_offering(year, sem): + offerings=getCourseOfferingsByYearAndSemester(year, sem) + if offerings: + for offering in offerings: + print(f'{offering}') + else: + print(f'Error retrieving course offerings') # ... (previous code remains the same) ''' @@ -184,13 +195,27 @@ def add_program_requirements(name,code,num): response=create_programCourse(name, code, num) print(response) -# @staff_cli.command("addofferedcourse",help='testing add courses offered feature') -# @click.argument("code", type=str) -# def add_offered_course(code): -# course=addSemesterCourses(code) -# if course: -# print(f'Course details: {course}') - +@staff_cli.command("addcourseoffering",help='testing add courses offering feature') +@click.argument("code", type=str) +@click.argument("year", type=str) +@click.argument("sem", type=int) +def add_course_offering(code, year, sem): + offering=createCourseOffering(code, year, sem) + if offering: + print(f'Course offering: {offering}') + else: + print(f'Error creating course offering') + +@staff_cli.command("removecourseoffering",help='testing remove courses offering feature') +@click.argument("code", type=str) +@click.argument("year", type=str) +@click.argument("sem", type=int) +def remove_course_offering(code, year, sem): + deleted=deleteCourseOffering(code, year, sem) + if deleted: + print(f'Course offering deleted') + else: + print(f'Error deleting course offering') app.cli.add_command(staff_cli) From 8c8481cda75118ad3357e12512bb9e466fa72979 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 21:54:25 +0000 Subject: [PATCH 18/44] bug fixes --- App/controllers/__init__.py | 3 ++- App/controllers/courseOfferings.py | 10 +++++++--- App/models/__init__.py | 1 + App/models/courseOfferings.py | 7 ++++++- App/views/staff.py | 2 -- wsgi.py | 15 ++++----------- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index fc0f1af34..b0275d784 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -9,4 +9,5 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursesOfferedPerSem import * -from .coursePlan import * \ No newline at end of file +from .coursePlan import * +from .courseOfferings import * \ No newline at end of file diff --git a/App/controllers/courseOfferings.py b/App/controllers/courseOfferings.py index 99864d7d1..315c9f0a1 100644 --- a/App/controllers/courseOfferings.py +++ b/App/controllers/courseOfferings.py @@ -1,7 +1,8 @@ from App.database import db -from .models import CourseOfferings +from App.models import CourseOfferings def createCourseOffering(courseCode, academic_year, semester): + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() if offering: print("Course offering exists already") @@ -10,7 +11,7 @@ def createCourseOffering(courseCode, academic_year, semester): if CourseOfferings.checkAcademicYearFormat(academic_year): if semester == 1 or semester == 2 or semester == 3: if CourseOfferings.getCourse(courseCode): - offeredCourse = CourseOfferings(semester, academic_year, courseCode) + offeredCourse = CourseOfferings(academic_year, semester, courseCode) if offeredCourse: db.session.add(offeredCourse) db.session.commit() @@ -65,6 +66,7 @@ def getCourseOfferingsByYearAndSemester(year, sem): print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") def deleteCourseOffering(courseCode, academic_year, semester): + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format try: offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() if offering: @@ -72,8 +74,10 @@ def deleteCourseOffering(courseCode, academic_year, semester): db.session.commit() print("Course offering deleted successfully") return True + else: + print("The course offering you are trying to delete does not exist") except Exception as e: db.session.rollback() - print(f"An error occured when trying to delete a course from the course offerings: {e}") + print(f"An error occured when trying to delete the course from the course offerings: {e}") return False diff --git a/App/models/__init__.py b/App/models/__init__.py index 5be95bde5..ee0629a37 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -9,3 +9,4 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursePlan import * +from .courseOfferings import * diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py index e4aad71a0..64fe7d7e6 100644 --- a/App/models/courseOfferings.py +++ b/App/models/courseOfferings.py @@ -7,6 +7,11 @@ class CourseOfferings(db.Model): semester = db.Column(db.Integer, nullable=False) course_code = db.Column(db.String, nullable=False) + def __init__(self, academic_year, semester, course_code): + self.academic_year = academic_year + self.semester = semester + self.course_code = course_code + def get_json(self): return{ 'id': self.id, @@ -20,7 +25,7 @@ def getCourse(course_code): def checkAcademicYearFormat(academic_year): s = academic_year.split("/") - if s.size() > 2: + if len(s) != 2: return False elif int(s[0]) != int(s[1])-1: return False diff --git a/App/views/staff.py b/App/views/staff.py index dc0e3292f..19adf6d22 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -13,7 +13,6 @@ get_all_users, get_all_users_json, jwt_required, - addSemesterCourses, get_all_OfferedCodes, get_all_programCourses, verify_staff, @@ -141,7 +140,6 @@ def addCourseOffering(): courseCode=data['code'] year = data['year'] sem = data['sem'] - courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format username=current_user.username if not verify_staff(username): #verify that the user is staff diff --git a/wsgi.py b/wsgi.py index 5e992fb96..4e3f21973 100644 --- a/wsgi.py +++ b/wsgi.py @@ -117,9 +117,8 @@ def get_course_offering(year, sem): offerings=getCourseOfferingsByYearAndSemester(year, sem) if offerings: for offering in offerings: - print(f'{offering}') - else: - print(f'Error retrieving course offerings') + print(f'{offering.get_json()}') + # ... (previous code remains the same) ''' @@ -202,20 +201,14 @@ def add_program_requirements(name,code,num): def add_course_offering(code, year, sem): offering=createCourseOffering(code, year, sem) if offering: - print(f'Course offering: {offering}') - else: - print(f'Error creating course offering') + print(f'Course offering: {offering.get_json()}') @staff_cli.command("removecourseoffering",help='testing remove courses offering feature') @click.argument("code", type=str) @click.argument("year", type=str) @click.argument("sem", type=int) def remove_course_offering(code, year, sem): - deleted=deleteCourseOffering(code, year, sem) - if deleted: - print(f'Course offering deleted') - else: - print(f'Error deleting course offering') + deleteCourseOffering(code, year, sem) app.cli.add_command(staff_cli) From 5500b55dd0abdf8bf75d160187cbbe0774d941e2 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:57:25 -0400 Subject: [PATCH 19/44] Revert "Add coruseOfferings class" --- App/controllers/__init__.py | 3 +- App/controllers/courseOfferings.py | 83 ------------------------------ App/controllers/staff.py | 12 +++++ App/models/__init__.py | 1 - App/models/courseOfferings.py | 34 ------------ App/views/staff.py | 44 ++-------------- wsgi.py | 34 +++--------- 7 files changed, 24 insertions(+), 187 deletions(-) delete mode 100644 App/controllers/courseOfferings.py delete mode 100644 App/models/courseOfferings.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index b0275d784..fc0f1af34 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -9,5 +9,4 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursesOfferedPerSem import * -from .coursePlan import * -from .courseOfferings import * \ No newline at end of file +from .coursePlan import * \ No newline at end of file diff --git a/App/controllers/courseOfferings.py b/App/controllers/courseOfferings.py deleted file mode 100644 index 315c9f0a1..000000000 --- a/App/controllers/courseOfferings.py +++ /dev/null @@ -1,83 +0,0 @@ -from App.database import db -from App.models import CourseOfferings - -def createCourseOffering(courseCode, academic_year, semester): - courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format - offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() - if offering: - print("Course offering exists already") - return None - try: - if CourseOfferings.checkAcademicYearFormat(academic_year): - if semester == 1 or semester == 2 or semester == 3: - if CourseOfferings.getCourse(courseCode): - offeredCourse = CourseOfferings(academic_year, semester, courseCode) - if offeredCourse: - db.session.add(offeredCourse) - db.session.commit() - print("Course offering created successfully") - return offeredCourse - else: - print("The new course offering could not be created") - else: - print(f"Invalid course code") - else: - print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") - else: - print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") - except Exception as e: - db.session.rollback() - print(f"An error occured when trying to add a course to the course offerings: {e}") - -def getAllCourseOfferings(): - return CourseOfferings.query.all() - -def getCourseOfferingsByYear(year): - if CourseOfferings.checkAcademicYearFormat(year): - offerings = CourseOfferings.query.filter_by(academic_year = year).all() - if offerings: - return offerings - else: - print("There are no offerings for the selected year") - else: - print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") - -def getCourseOfferingsBySemester(sem): - if sem == 1 or sem == 2 or sem == 3: - offerings = CourseOfferings.query.filter_by(semester = sem).all() - if offerings: - return offerings - else: - print("There are no offerings for the selected semester") - else: - print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") - -def getCourseOfferingsByYearAndSemester(year, sem): - if CourseOfferings.checkAcademicYearFormat(year): - if sem == 1 or sem == 2 or sem == 3: - offerings = CourseOfferings.query.filter_by(semester = sem, academic_year = year).all() - if offerings: - return offerings - else: - print("There are no offerings for the selected year and semester") - else: - print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") - else: - print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") - -def deleteCourseOffering(courseCode, academic_year, semester): - courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format - try: - offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() - if offering: - db.session.delete(offering) - db.session.commit() - print("Course offering deleted successfully") - return True - else: - print("The course offering you are trying to delete does not exist") - except Exception as e: - db.session.rollback() - print(f"An error occured when trying to delete the course from the course offerings: {e}") - return False - diff --git a/App/controllers/staff.py b/App/controllers/staff.py index c806256df..86ee70c40 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,6 +1,7 @@ from App.models import Program, Course, Staff from App.database import db + def create_staff(password, staff_id, name): new_staff = Staff(password, staff_id, name) db.session.add(new_staff) @@ -18,6 +19,17 @@ def get_staff_by_id(ID): return Staff.query.filter_by(id=ID).first() +def addSemesterCourses(courseCode): + course = get_course_by_courseCode(courseCode) + if course: + semCourses = CoursesOfferedPerSem(courseCode) + db.session.add(semCourses) + db.session.commit() + return semCourses + else: + print("Course not found") + + # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/__init__.py b/App/models/__init__.py index de91ac513..22956967f 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -10,4 +10,3 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursePlan import * -from .courseOfferings import * diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py deleted file mode 100644 index 64fe7d7e6..000000000 --- a/App/models/courseOfferings.py +++ /dev/null @@ -1,34 +0,0 @@ -from App.database import db -from .courses import Course - -class CourseOfferings(db.Model): - id = db.Column(db.Integer, primary_key = True) - academic_year = db.Column(db.String, nullable=False) - semester = db.Column(db.Integer, nullable=False) - course_code = db.Column(db.String, nullable=False) - - def __init__(self, academic_year, semester, course_code): - self.academic_year = academic_year - self.semester = semester - self.course_code = course_code - - def get_json(self): - return{ - 'id': self.id, - 'year': self.academic_year, - 'semester': self.semester, - 'course': self.course_code - } - - def getCourse(course_code): - return Course.query.filter_by(courseCode=course_code).first() - - def checkAcademicYearFormat(academic_year): - s = academic_year.split("/") - if len(s) != 2: - return False - elif int(s[0]) != int(s[1])-1: - return False - elif int(s[0]) < 2000: - return False - return True diff --git a/App/views/staff.py b/App/views/staff.py index 19adf6d22..b0568053f 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -13,11 +13,10 @@ get_all_users, get_all_users_json, jwt_required, + addSemesterCourses, get_all_OfferedCodes, get_all_programCourses, - verify_staff, - createCourseOffering, - deleteCourseOffering + verify_staff ) staff_views = Blueprint('staff_views', __name__, template_folder='../templates') @@ -131,41 +130,4 @@ def addCourse(): if course: return jsonify(course.get_json()), 200 else: - return jsonify({'message': "Course addition unsucessful"}), 400 - -@staff_views.route('/staff/addCourseOffering', methods=['POST']) -@login_required -def addCourseOffering(): - data=request.json - courseCode=data['code'] - year = data['year'] - sem = data['sem'] - - username=current_user.username - if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - - offering = createCourseOffering(courseCode, year, sem) - if offering is not None: - return jsonify(offering.get_json()), 200 - else: - return jsonify({'message': "Course offering creation unsucessful"}), 400 - -@staff_views.route('/staff/removeCourseOffering', methods=['DELETE']) -@login_required -def removeCourseOffering(): - data=request.json - courseCode=data['code'] - year = data['year'] - sem = data['sem'] - courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format - - username=current_user.username - if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - - deleted = deleteCourseOffering(courseCode, year, sem) - if deleted: - return jsonify({'message:': "Course offering deletion succesful"}), 200 - else: - return jsonify({'message': "Course offering deletion unsucessful"}), 404 \ No newline at end of file + return jsonify({'message': "Course addition unsucessful"}), 400 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 0d4c113af..bd9c80542 100644 --- a/wsgi.py +++ b/wsgi.py @@ -18,9 +18,7 @@ get_prerequisites, get_all_courses, create_programCourse, - createCourseOffering, - deleteCourseOffering, - getCourseOfferingsByYearAndSemester, + addSemesterCourses, create_student, create_staff, get_program_by_name, @@ -110,14 +108,6 @@ def list_user_command(format): app.cli.add_command(user_cli) # add the group to the cli -@user_cli.command("getcourseoffering",help='testing remove courses offering feature') -@click.argument("year", type=str) -@click.argument("sem", type=int) -def get_course_offering(year, sem): - offerings=getCourseOfferingsByYearAndSemester(year, sem) - if offerings: - for offering in offerings: - print(f'{offering.get_json()}') # ... (previous code remains the same) @@ -194,21 +184,13 @@ def add_program_requirements(name,code,num): response=create_programCourse(name, code, num) print(response) -@staff_cli.command("addcourseoffering",help='testing add courses offering feature') -@click.argument("code", type=str) -@click.argument("year", type=str) -@click.argument("sem", type=int) -def add_course_offering(code, year, sem): - offering=createCourseOffering(code, year, sem) - if offering: - print(f'Course offering: {offering.get_json()}') - -@staff_cli.command("removecourseoffering",help='testing remove courses offering feature') -@click.argument("code", type=str) -@click.argument("year", type=str) -@click.argument("sem", type=int) -def remove_course_offering(code, year, sem): - deleteCourseOffering(code, year, sem) +# @staff_cli.command("addofferedcourse",help='testing add courses offered feature') +# @click.argument("code", type=str) +# def add_offered_course(code): +# course=addSemesterCourses(code) +# if course: +# print(f'Course details: {course}') + app.cli.add_command(staff_cli) From d8d4f27d528fdaddf91905a1a775abaaf4d092cd Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:05:17 +0000 Subject: [PATCH 20/44] slight wording change --- App/models/courseOfferings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py index 64fe7d7e6..eb55af263 100644 --- a/App/models/courseOfferings.py +++ b/App/models/courseOfferings.py @@ -1,5 +1,5 @@ from App.database import db -from .courses import Course +from App.models.courses import Course class CourseOfferings(db.Model): id = db.Column(db.Integer, primary_key = True) From 4246e800141ea75dd03e0c66e4bb7847681d2153 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:15:02 +0000 Subject: [PATCH 21/44] wording change --- App/models/courseOfferings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py index eb55af263..64fe7d7e6 100644 --- a/App/models/courseOfferings.py +++ b/App/models/courseOfferings.py @@ -1,5 +1,5 @@ from App.database import db -from App.models.courses import Course +from .courses import Course class CourseOfferings(db.Model): id = db.Column(db.Integer, primary_key = True) From 82b5ebf3253da27e04ae1e1b443c6a5dcd648922 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Thu, 30 Nov 2023 18:18:29 -0400 Subject: [PATCH 22/44] Revert "Revert "Add courseOfferings class"" --- App/controllers/__init__.py | 3 +- App/controllers/courseOfferings.py | 83 ++++++++++++++++++++++++++++++ App/controllers/staff.py | 12 ----- App/models/__init__.py | 1 + App/models/courseOfferings.py | 34 ++++++++++++ App/views/staff.py | 44 ++++++++++++++-- wsgi.py | 34 +++++++++--- 7 files changed, 187 insertions(+), 24 deletions(-) create mode 100644 App/controllers/courseOfferings.py create mode 100644 App/models/courseOfferings.py diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index fc0f1af34..b0275d784 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -9,4 +9,5 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursesOfferedPerSem import * -from .coursePlan import * \ No newline at end of file +from .coursePlan import * +from .courseOfferings import * \ No newline at end of file diff --git a/App/controllers/courseOfferings.py b/App/controllers/courseOfferings.py new file mode 100644 index 000000000..315c9f0a1 --- /dev/null +++ b/App/controllers/courseOfferings.py @@ -0,0 +1,83 @@ +from App.database import db +from App.models import CourseOfferings + +def createCourseOffering(courseCode, academic_year, semester): + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() + if offering: + print("Course offering exists already") + return None + try: + if CourseOfferings.checkAcademicYearFormat(academic_year): + if semester == 1 or semester == 2 or semester == 3: + if CourseOfferings.getCourse(courseCode): + offeredCourse = CourseOfferings(academic_year, semester, courseCode) + if offeredCourse: + db.session.add(offeredCourse) + db.session.commit() + print("Course offering created successfully") + return offeredCourse + else: + print("The new course offering could not be created") + else: + print(f"Invalid course code") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + else: + print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to add a course to the course offerings: {e}") + +def getAllCourseOfferings(): + return CourseOfferings.query.all() + +def getCourseOfferingsByYear(year): + if CourseOfferings.checkAcademicYearFormat(year): + offerings = CourseOfferings.query.filter_by(academic_year = year).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected year") + else: + print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + +def getCourseOfferingsBySemester(sem): + if sem == 1 or sem == 2 or sem == 3: + offerings = CourseOfferings.query.filter_by(semester = sem).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected semester") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + +def getCourseOfferingsByYearAndSemester(year, sem): + if CourseOfferings.checkAcademicYearFormat(year): + if sem == 1 or sem == 2 or sem == 3: + offerings = CourseOfferings.query.filter_by(semester = sem, academic_year = year).all() + if offerings: + return offerings + else: + print("There are no offerings for the selected year and semester") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + else: + print("Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + +def deleteCourseOffering(courseCode, academic_year, semester): + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + try: + offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() + if offering: + db.session.delete(offering) + db.session.commit() + print("Course offering deleted successfully") + return True + else: + print("The course offering you are trying to delete does not exist") + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to delete the course from the course offerings: {e}") + return False + diff --git a/App/controllers/staff.py b/App/controllers/staff.py index 86ee70c40..c806256df 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -1,7 +1,6 @@ from App.models import Program, Course, Staff from App.database import db - def create_staff(password, staff_id, name): new_staff = Staff(password, staff_id, name) db.session.add(new_staff) @@ -19,17 +18,6 @@ def get_staff_by_id(ID): return Staff.query.filter_by(id=ID).first() -def addSemesterCourses(courseCode): - course = get_course_by_courseCode(courseCode) - if course: - semCourses = CoursesOfferedPerSem(courseCode) - db.session.add(semCourses) - db.session.commit() - return semCourses - else: - print("Course not found") - - # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/models/__init__.py b/App/models/__init__.py index 22956967f..de91ac513 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -10,3 +10,4 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursePlan import * +from .courseOfferings import * diff --git a/App/models/courseOfferings.py b/App/models/courseOfferings.py new file mode 100644 index 000000000..64fe7d7e6 --- /dev/null +++ b/App/models/courseOfferings.py @@ -0,0 +1,34 @@ +from App.database import db +from .courses import Course + +class CourseOfferings(db.Model): + id = db.Column(db.Integer, primary_key = True) + academic_year = db.Column(db.String, nullable=False) + semester = db.Column(db.Integer, nullable=False) + course_code = db.Column(db.String, nullable=False) + + def __init__(self, academic_year, semester, course_code): + self.academic_year = academic_year + self.semester = semester + self.course_code = course_code + + def get_json(self): + return{ + 'id': self.id, + 'year': self.academic_year, + 'semester': self.semester, + 'course': self.course_code + } + + def getCourse(course_code): + return Course.query.filter_by(courseCode=course_code).first() + + def checkAcademicYearFormat(academic_year): + s = academic_year.split("/") + if len(s) != 2: + return False + elif int(s[0]) != int(s[1])-1: + return False + elif int(s[0]) < 2000: + return False + return True diff --git a/App/views/staff.py b/App/views/staff.py index b0568053f..19adf6d22 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -13,10 +13,11 @@ get_all_users, get_all_users_json, jwt_required, - addSemesterCourses, get_all_OfferedCodes, get_all_programCourses, - verify_staff + verify_staff, + createCourseOffering, + deleteCourseOffering ) staff_views = Blueprint('staff_views', __name__, template_folder='../templates') @@ -130,4 +131,41 @@ def addCourse(): if course: return jsonify(course.get_json()), 200 else: - return jsonify({'message': "Course addition unsucessful"}), 400 \ No newline at end of file + return jsonify({'message': "Course addition unsucessful"}), 400 + +@staff_views.route('/staff/addCourseOffering', methods=['POST']) +@login_required +def addCourseOffering(): + data=request.json + courseCode=data['code'] + year = data['year'] + sem = data['sem'] + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + offering = createCourseOffering(courseCode, year, sem) + if offering is not None: + return jsonify(offering.get_json()), 200 + else: + return jsonify({'message': "Course offering creation unsucessful"}), 400 + +@staff_views.route('/staff/removeCourseOffering', methods=['DELETE']) +@login_required +def removeCourseOffering(): + data=request.json + courseCode=data['code'] + year = data['year'] + sem = data['sem'] + courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + deleted = deleteCourseOffering(courseCode, year, sem) + if deleted: + return jsonify({'message:': "Course offering deletion succesful"}), 200 + else: + return jsonify({'message': "Course offering deletion unsucessful"}), 404 \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index bd9c80542..0d4c113af 100644 --- a/wsgi.py +++ b/wsgi.py @@ -18,7 +18,9 @@ get_prerequisites, get_all_courses, create_programCourse, - addSemesterCourses, + createCourseOffering, + deleteCourseOffering, + getCourseOfferingsByYearAndSemester, create_student, create_staff, get_program_by_name, @@ -108,6 +110,14 @@ def list_user_command(format): app.cli.add_command(user_cli) # add the group to the cli +@user_cli.command("getcourseoffering",help='testing remove courses offering feature') +@click.argument("year", type=str) +@click.argument("sem", type=int) +def get_course_offering(year, sem): + offerings=getCourseOfferingsByYearAndSemester(year, sem) + if offerings: + for offering in offerings: + print(f'{offering.get_json()}') # ... (previous code remains the same) @@ -184,13 +194,21 @@ def add_program_requirements(name,code,num): response=create_programCourse(name, code, num) print(response) -# @staff_cli.command("addofferedcourse",help='testing add courses offered feature') -# @click.argument("code", type=str) -# def add_offered_course(code): -# course=addSemesterCourses(code) -# if course: -# print(f'Course details: {course}') - +@staff_cli.command("addcourseoffering",help='testing add courses offering feature') +@click.argument("code", type=str) +@click.argument("year", type=str) +@click.argument("sem", type=int) +def add_course_offering(code, year, sem): + offering=createCourseOffering(code, year, sem) + if offering: + print(f'Course offering: {offering.get_json()}') + +@staff_cli.command("removecourseoffering",help='testing remove courses offering feature') +@click.argument("code", type=str) +@click.argument("year", type=str) +@click.argument("sem", type=int) +def remove_course_offering(code, year, sem): + deleteCourseOffering(code, year, sem) app.cli.add_command(staff_cli) From db5c95852c766a336f7de0a817b05eb453810eb9 Mon Sep 17 00:00:00 2001 From: Chefboyadee Date: Fri, 1 Dec 2023 02:30:38 +0000 Subject: [PATCH 23/44] push grade changes --- App/controllers/studentCourseHistory.py | 37 +++++++++++++++++-------- App/models/studentCourseHistory.py | 28 +++++++++++-------- wsgi.py | 11 ++++---- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index cb157ee69..c65ec0539 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -2,18 +2,31 @@ from App.controllers import (get_student_by_id, get_course_by_courseCode) from App.database import db -def addCoursetoHistory(studentid, code): - student = get_student_by_id(studentid) - if student: - course = get_course_by_courseCode(code) - if course: - completed = StudentCourseHistory(studentid, code) - db.session.add(completed) - db.session.commit() - else: - print("Course doesn't exist") - else: - print("Student doesn't exist") +def addCourseToHistory(student_id, course_code, grade=None): + + try: + student = get_student_by_id(student_id) + course = get_course_by_courseCode(course_code) + + if not student: + raise ValueError("Student does not exist") + + if not course: + raise ValueError("Course does not exist") + + enrollment = StudentCourseHistory( + student_id=student_id, + course_code=course_code, + grade=grade + ) + + db.session.add(enrollment) + db.session.commit() + + except ValueError as e: + print(e) + + return enrollment def getCompletedCourses(id): diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 339594391..10c490315 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -2,19 +2,23 @@ class StudentCourseHistory(db.Model): __tablename__ = 'studentCourses' - id = db.Column(db.Integer, primary_key=True) - studentID = db.Column(db.ForeignKey('student.id')) - code = db.Column(db.ForeignKey('courses.courseCode')) - - associated_course = db.relationship('Course', back_populates='students', overlaps="courses") - associated_student = db.relationship('Student', back_populates='courses', overlaps="student") + + id = db.Column(db.Integer, primary_key=True) + student_id = db.Column(db.String, db.ForeignKey('student.id')) + course_code = db.Column(db.String, db.ForeignKey('courses.courseCode')) + grade = db.Column(db.String) + + associated_course = db.relationship('Course', back_populates='students') + associated_student = db.relationship('Student', back_populates='courses') - def __init__(self, id, courseCode): - self.studentID = id - self.code = courseCode + def __init__(self, student_id, course_code): + self.student_id = student_id + self.course_code = course_code def get_json(self): - return{ - 'Program ID': self.id, #is this suppose to be id or program_id alone - 'Course Code': self.code + return { + 'StudentCourseHistory ID': self.id, + 'Student ID': self.student_id, + 'Course Code': self.course_code, + 'Grade': self.grade } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 0d4c113af..df68dd84a 100644 --- a/wsgi.py +++ b/wsgi.py @@ -138,15 +138,16 @@ def create_student_command(student_id, password, name, programname): @student_cli.command("addCourse", help="Student adds a completed course to their history") @click.argument("student_id", type=str) @click.argument("code", type=str) -def addCourse(student_id, code): - addCoursetoHistory(student_id, code) +@click.argument("grade", default="A") +def addCourse(student_id, code, grade): + addCoursetoHistory(student_id, code, grade) @student_cli.command("getCompleted", help="Get all of a student completed courses") @click.argument("student_id", type=str) def completed(student_id): - comp = getCompletedCourseCodes(student_id) - for c in comp: - print(f'{c}') + courses = getCompletedCourseCodes(student_id) + for c in courses: + print(c.get_json()) @student_cli.command("addCourseToPlan", help="Adds a course to a student's course plan") def courseToPlan(): From d6a750b03c65b2d61d98f88aa297e21da1ed6505 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Fri, 1 Dec 2023 20:14:22 +0000 Subject: [PATCH 24/44] this is a test --- App/models/coursePlanCourses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index 4e7e63880..d07f1141c 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -5,6 +5,7 @@ class CoursePlanCourses(db.Model): id = db.Column(db.Integer, primary_key=True) planId = db.Column(db.ForeignKey('course_plan.planId')) code = db.Column(db.ForeignKey('courses.courseCode')) + # test commit # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") From 7657a7b19df56b088526da3ef425ded941916fcc Mon Sep 17 00:00:00 2001 From: Chefboyadee Date: Sat, 2 Dec 2023 16:42:06 +0000 Subject: [PATCH 25/44] new grade addition --- App/controllers/studentCourseHistory.py | 32 ++++++++++++++++++++++--- App/models/studentCourseHistory.py | 11 +++++---- wsgi.py | 12 ++++++++-- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index cb157ee69..8ed9d9d38 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -2,20 +2,46 @@ from App.controllers import (get_student_by_id, get_course_by_courseCode) from App.database import db -def addCoursetoHistory(studentid, code): + +def addCoursetoHistory(studentid, code, grade): student = get_student_by_id(studentid) if student: course = get_course_by_courseCode(code) if course: - completed = StudentCourseHistory(studentid, code) + completed = StudentCourseHistory(studentid, code, grade) db.session.add(completed) db.session.commit() else: print("Course doesn't exist") else: print("Student doesn't exist") - +''' +def addCoursetoHistory(student_id, course_code, grade): + + try: + student = get_student_by_id(student_id) + course = get_course_by_courseCode(course_code) + + if not student: + raise ValueError("Invalid student ID") + + if not course: + raise ValueError("Invalid course code") + + enrollment = StudentCourseHistory( + student_id = student_id, + course_code = course_code, + grade = grade + ) + + db.session.add(enrollment) + db.session.commit() + + except ValueError as e: + print(e) + return enrollment +''' def getCompletedCourses(id): return StudentCourseHistory.query.filter_by(studentID=id).all() diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index b5d9e8528..5ee4f41c7 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -5,16 +5,19 @@ class StudentCourseHistory(db.Model): id = db.Column(db.Integer, primary_key=True) studentID = db.Column(db.ForeignKey('student.id')) code = db.Column(db.ForeignKey('course.courseCode')) + grade = db.Column(db.String) associated_course = db.relationship('Course', back_populates='students', overlaps="courses") associated_student = db.relationship('Student', back_populates='courses', overlaps="student") - def __init__(self, id, courseCode): - self.studentID = id - self.code = courseCode + def __init__(self, student_id, course_code, grade=None): + self.studentID = student_id + self.code = course_code + self.grade = grade def get_json(self): return{ 'Program ID': self.id, #is this suppose to be id or program_id alone - 'Course Code': self.code + 'Course Code': self.code, + 'Grade': self.grade } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index de91e5bc9..d8162d99a 100644 --- a/wsgi.py +++ b/wsgi.py @@ -128,8 +128,16 @@ def create_student_command(student_id, password, name, programname): @student_cli.command("addCourse", help="Student adds a completed course to their history") @click.argument("student_id", type=str) @click.argument("code", type=str) -def addCourse(student_id, code): - addCoursetoHistory(student_id, code) +@click.argument("grade", type=str) +@click.pass_context +def addCourse(ctx, student_id, code, grade): + addCoursetoHistory(student_id, code, grade) + +addCourse.params = [ + click.Argument(["student_id"], type=str), + click.Argument(["code"], type=str), + click.Argument(["grade"], type=str) +] @student_cli.command("getCompleted", help="Get all of a student completed courses") @click.argument("student_id", type=str) From 04ff845349cd9950ec9f1faee734db94d706c0f5 Mon Sep 17 00:00:00 2001 From: Chefboyadee Date: Sat, 2 Dec 2023 18:26:33 +0000 Subject: [PATCH 26/44] grades being intialised and displayed now --- App/controllers/studentCourseHistory.py | 8 ++++---- App/models/department.py | 10 ++++++++++ App/models/studentCourseHistory.py | 2 +- wsgi.py | 6 ++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index 8ed9d9d38..81d57fe8e 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -46,10 +46,10 @@ def getCompletedCourses(id): return StudentCourseHistory.query.filter_by(studentID=id).all() def getCompletedCourseCodes(id): - completed = getCompletedCourses(id) + completed_courses = getCompletedCourses(id) codes = [] - for c in completed: - codes.append(c.code) + for course in completed_courses: + codes.append(course.code) - return codes + return completed_courses # Return instances, not just codes diff --git a/App/models/department.py b/App/models/department.py index e69de29bb..736f7d7c7 100644 --- a/App/models/department.py +++ b/App/models/department.py @@ -0,0 +1,10 @@ +from App.database import db + +class Department(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(50), nullable=False, unique=True) + + __tablename__ = 'departments' # Explicitly set the table name + + def __repr__(self): + return f"Department('{self.name}')" diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 5ee4f41c7..435fb45d0 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -10,7 +10,7 @@ class StudentCourseHistory(db.Model): associated_course = db.relationship('Course', back_populates='students', overlaps="courses") associated_student = db.relationship('Student', back_populates='courses', overlaps="student") - def __init__(self, student_id, course_code, grade=None): + def __init__(self, student_id, course_code, grade): self.studentID = student_id self.code = course_code self.grade = grade diff --git a/wsgi.py b/wsgi.py index d8162d99a..596d3d12e 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,4 +1,5 @@ import click, pytest, sys +import random import csv from flask import Flask from App.controllers.student import create_student @@ -55,7 +56,8 @@ def initialize(): create_staff("adminpass","999", "admin") for c in test1: - addCoursetoHistory(816, c) + grade = random.choice(['A', 'B', 'C', 'F']) + addCoursetoHistory(816, c, grade) print('Student course history updated') with open(file_path, 'r') as file: @@ -144,7 +146,7 @@ def addCourse(ctx, student_id, code, grade): def completed(student_id): comp = getCompletedCourseCodes(student_id) for c in comp: - print(f'{c}') + print(f'Course Code: {c.code}, Grade: {c.grade}') @student_cli.command("addCourseToPlan", help="Adds a course to a student's course plan") def courseToPlan(): From 22c65244b174fc519770c44e99d6a869decce078 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sat, 2 Dec 2023 18:38:21 +0000 Subject: [PATCH 27/44] minor changes --- App/controllers/coursePlan.py | 10 +++++----- App/controllers/courses.py | 2 +- App/models/coursePlanCourses.py | 3 +-- App/models/student.py | 2 ++ App/models/studentCourseHistory.py | 4 ++-- App/views/student.py | 4 ++-- wsgi.py | 10 +++++----- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 50ffab72a..0b58e6d85 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -33,11 +33,11 @@ def getCoursePlan(studentid): return CoursePlan.query.filter_by(studentId=studentid).first() def possessPrereqs(Student, course): - preqs = getPrereqCodes(course.courseName) - completed = getCompletedCourseCodes(Student.id) - for course in preqs: - if course not in completed: - return False + # preqs = getPrereqCodes(course.courseName) + # completed = getCompletedCourseCodes(Student.id) + # for course in preqs: + # if course not in completed: + # return False return True diff --git a/App/controllers/courses.py b/App/controllers/courses.py index aad1cd50a..9d50921ce 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -83,7 +83,7 @@ def courses_Sorted_byRating_Objects(): def isCourseOffered(courseCode): - course = Course.query.filter_by(code=courseCode).first() + course = Course.query.filter_by(courseCode=courseCode).first() return course.offered def get_all_OfferedCodes(): diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index d07f1141c..90d235a7e 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -5,8 +5,7 @@ class CoursePlanCourses(db.Model): id = db.Column(db.Integer, primary_key=True) planId = db.Column(db.ForeignKey('course_plan.planId')) code = db.Column(db.ForeignKey('courses.courseCode')) - # test commit - + # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") diff --git a/App/models/student.py b/App/models/student.py index eacd0429d..d22fe560c 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -8,7 +8,9 @@ class Student(User): associated_program = db.relationship('Program', back_populates='students', overlaps="program") courses = db.relationship('StudentCourseHistory', backref='student', lazy=True) + + def __init__(self, username, password, name, program_id): super().__init__(username, password) self.id = username diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 10c490315..39da47ef8 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -8,8 +8,8 @@ class StudentCourseHistory(db.Model): course_code = db.Column(db.String, db.ForeignKey('courses.courseCode')) grade = db.Column(db.String) - associated_course = db.relationship('Course', back_populates='students') - associated_student = db.relationship('Student', back_populates='courses') + # associated_course = db.relationship('Course', back_populates='students') + # associated_student = db.relationship('Student', back_populates='courses') def __init__(self, student_id, course_code): self.student_id = student_id diff --git a/App/views/student.py b/App/views/student.py index 4a0cb1e33..821992942 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -13,7 +13,7 @@ get_program_by_name, get_student_by_id, get_course_by_courseCode, - addCoursetoHistory, + # addCoursetoHistory, getCompletedCourseCodes, generator, addCourseToPlan, @@ -73,7 +73,7 @@ def add_course_to_student_route(): if course_code in completed_courses: return jsonify({'Error': 'Course already completed'}), 400 - addCoursetoHistory(student_id, course_code) + # addCoursetoHistory(student_id, course_code) return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}), 200 diff --git a/wsgi.py b/wsgi.py index df68dd84a..0870edf65 100644 --- a/wsgi.py +++ b/wsgi.py @@ -25,7 +25,7 @@ create_staff, get_program_by_name, get_all_programCourses, - addCoursetoHistory, + # addCoursetoHistory, getCompletedCourseCodes, get_allCore, addCourseToPlan, @@ -325,12 +325,12 @@ def create_program_command(name, core, elective, foun): @program.command('core', help='Get program core courses') -#@click.argument('programname', type=str) -def get_CoreCourses(): +@click.argument('programname', type=str) +def get_CoreCourses(programname): create_programCourse("Computer Science Major", "COMP2611", 1) create_programCourse("Computer Science Major", "COMP3605", 1) create_programCourse("Computer Science Major", "COMP3610", 2) - core = get_allCore("Computer Science Major") + core = get_allCore(programname) for c in core: print({c.code}) @@ -364,7 +364,7 @@ def addProgramCourse(programname, code, type): def addProgramCourse(programname): courses = get_all_programCourses(programname) for c in courses: - print(f'{c.code}') + print(f'{c.code} {c.courseType}') app.cli.add_command(program) ################################################################# From 4510e49311bc901865ab69ef380e3666998ce462 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Sat, 2 Dec 2023 21:22:17 +0000 Subject: [PATCH 28/44] create strategy dp classes for course planning --- App/models/CoursePlanner.py | 14 ++++++++++++++ App/models/CoursePlannerStrategy.py | 10 ++++++++++ App/models/EasyCoursePlanner.py | 9 +++++++++ App/models/ElectiveCoursePlanner.py | 9 +++++++++ App/models/FastCoursePlanner.py | 9 +++++++++ App/models/coursePlan.py | 26 +++++++++++++++++++++----- App/models/coursePlanCourses.py | 5 ++++- 7 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 App/models/CoursePlanner.py create mode 100644 App/models/CoursePlannerStrategy.py create mode 100644 App/models/EasyCoursePlanner.py create mode 100644 App/models/ElectiveCoursePlanner.py create mode 100644 App/models/FastCoursePlanner.py diff --git a/App/models/CoursePlanner.py b/App/models/CoursePlanner.py new file mode 100644 index 000000000..f52ab2708 --- /dev/null +++ b/App/models/CoursePlanner.py @@ -0,0 +1,14 @@ +from typing import List +from App.database import db +from App.models import CoursePlannerStrategy, CoursePlan + +# Context +class CoursePlanner: + def __init__(self, strategy: CoursePlannerStrategy): + self._strategy = strategy + + def set_strategy(self, strategy: CoursePlannerStrategy): + self._strategy = strategy + + def plan_courses(self, data: List[str], target: CoursePlan) -> CoursePlan: + return self._strategy.search(data, target) \ No newline at end of file diff --git a/App/models/CoursePlannerStrategy.py b/App/models/CoursePlannerStrategy.py new file mode 100644 index 000000000..9dd0fd958 --- /dev/null +++ b/App/models/CoursePlannerStrategy.py @@ -0,0 +1,10 @@ +from App.database import db +from App.models import CoursePlan +from typing import List +from abc import ABC, abstractmethod + +# Strategy Interface +class CoursePlannerStrategy(ABC): + @abstractmethod + def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + pass \ No newline at end of file diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py new file mode 100644 index 000000000..d8b243690 --- /dev/null +++ b/App/models/EasyCoursePlanner.py @@ -0,0 +1,9 @@ +from App.database import db +from App.models import CoursePlan, CoursePlannerStrategy +from typing import List + +# Concrete Strategy: Fast +class EasyCoursePlanner(CoursePlannerStrategy): + def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + # implement logic + pass \ No newline at end of file diff --git a/App/models/ElectiveCoursePlanner.py b/App/models/ElectiveCoursePlanner.py new file mode 100644 index 000000000..ad41bc9d3 --- /dev/null +++ b/App/models/ElectiveCoursePlanner.py @@ -0,0 +1,9 @@ +from App.database import db +from App.models import CoursePlan, CoursePlannerStrategy +from typing import List + +# Concrete Strategy: Fast +class ElectiveCoursePlanner(CoursePlannerStrategy): + def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + # implement logic + pass \ No newline at end of file diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py new file mode 100644 index 000000000..29c171493 --- /dev/null +++ b/App/models/FastCoursePlanner.py @@ -0,0 +1,9 @@ +from App.database import db +from App.models import CoursePlan, CoursePlannerStrategy +from typing import List + +# Concrete Strategy: Fast +class FastCoursePlanner(CoursePlannerStrategy): + def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + # implement logic + pass \ No newline at end of file diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index e3cfaa1e5..bab88dd0b 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -2,18 +2,34 @@ class CoursePlan(db.Model): planId=db.Column(db.Integer, primary_key=True) - studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - + academic_year = db.Column(db.String, nullable=False) + semester = db.Column(db.String(1), nullable=False) + studentId=db.Column(db.String(10), db.ForeignKey('student.id'), nullable=False) + student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) # courses = db.relationship('CoursePlanCourses', backref = 'coursePlan', lazy=True) - - def __init__(self, studentid, ): + + def __init__(self, studentid, year, sem): self.studentId = studentid + self.academic_year = year + self.semester = sem def get_json(self): return{ 'planId': self.planId, + 'year': self.academic_year, + 'semester': self.semester, 'studentId': self.studentId, - } \ No newline at end of file + } + + def checkAcademicYearFormat(academic_year): + s = academic_year.split("/") + if len(s) != 2: + return False + elif int(s[0]) != int(s[1])-1: + return False + elif int(s[0]) < 2000: + return False + return True \ No newline at end of file diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index 4e7e63880..3aebe2fa3 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -1,5 +1,5 @@ from App.database import db - +from App.models import Course class CoursePlanCourses(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -19,4 +19,7 @@ def get_json(self): 'Course Plan ID': self.planId, 'Course': self.code } + + def getCourse(course_code): + return Course.query.filter_by(courseCode=course_code).first() From 3f87751ea4887964e2fd79c78964eb64df947206 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Sat, 2 Dec 2023 21:27:29 +0000 Subject: [PATCH 29/44] remove unused parameter 'target' --- App/models/CoursePlanner.py | 4 ++-- App/models/CoursePlannerStrategy.py | 2 +- App/models/EasyCoursePlanner.py | 2 +- App/models/ElectiveCoursePlanner.py | 2 +- App/models/FastCoursePlanner.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/App/models/CoursePlanner.py b/App/models/CoursePlanner.py index f52ab2708..1df2f4331 100644 --- a/App/models/CoursePlanner.py +++ b/App/models/CoursePlanner.py @@ -10,5 +10,5 @@ def __init__(self, strategy: CoursePlannerStrategy): def set_strategy(self, strategy: CoursePlannerStrategy): self._strategy = strategy - def plan_courses(self, data: List[str], target: CoursePlan) -> CoursePlan: - return self._strategy.search(data, target) \ No newline at end of file + def plan_courses(self, data: List[str]) -> CoursePlan: + return self._strategy.search(data) \ No newline at end of file diff --git a/App/models/CoursePlannerStrategy.py b/App/models/CoursePlannerStrategy.py index 9dd0fd958..32d3f8b4c 100644 --- a/App/models/CoursePlannerStrategy.py +++ b/App/models/CoursePlannerStrategy.py @@ -6,5 +6,5 @@ # Strategy Interface class CoursePlannerStrategy(ABC): @abstractmethod - def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + def planCourses(self, data: List[str]) -> CoursePlan: pass \ No newline at end of file diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index d8b243690..2d81f8a36 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -4,6 +4,6 @@ # Concrete Strategy: Fast class EasyCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + def planCourses(self, data: List[str]) -> CoursePlan: # implement logic pass \ No newline at end of file diff --git a/App/models/ElectiveCoursePlanner.py b/App/models/ElectiveCoursePlanner.py index ad41bc9d3..a4f037828 100644 --- a/App/models/ElectiveCoursePlanner.py +++ b/App/models/ElectiveCoursePlanner.py @@ -4,6 +4,6 @@ # Concrete Strategy: Fast class ElectiveCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + def planCourses(self, data: List[str]) -> CoursePlan: # implement logic pass \ No newline at end of file diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index 29c171493..9ccf58f77 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -4,6 +4,6 @@ # Concrete Strategy: Fast class FastCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str], target: CoursePlan) -> CoursePlan: + def planCourses(self, data: List[str]) -> CoursePlan: # implement logic pass \ No newline at end of file From cef87e09b84c8be840c58e02179fc7be0ef94fb5 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 14:35:39 +0000 Subject: [PATCH 30/44] fix coursePlan and CoursePlanCourses relationship --- App/controllers/CoursePlanner.py | 13 ++++++ App/controllers/coursePlan.py | 15 +++++- App/controllers/coursePlanCourses.py | 1 + App/controllers/courses.py | 8 ++-- App/controllers/prerequistes.py | 9 ++-- App/models/coursePlan.py | 15 ++++-- App/models/coursePlanCourses.py | 8 ++-- App/models/courses.py | 3 ++ App/models/student.py | 1 + App/models/studentCourseHistory.py | 2 +- wsgi.py | 69 +++++++++++++++++++++++++--- 11 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 App/controllers/CoursePlanner.py diff --git a/App/controllers/CoursePlanner.py b/App/controllers/CoursePlanner.py new file mode 100644 index 000000000..153d66afc --- /dev/null +++ b/App/controllers/CoursePlanner.py @@ -0,0 +1,13 @@ +from App.models import CoursePlan, Student +from App.database import db +from App.controllers import ( + get_student_by_id, + +) + +def createCoursePlan(student_id, Mode): #mode is easy, fastest or prioritise electives + student = get_student_by_id(student_id) + + + + diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 0b58e6d85..8b32186e6 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -1,4 +1,4 @@ -from App.models import CoursePlan +from App.models import CoursePlan, CoursePlanCourses from App.database import db from App.controllers import ( get_program_by_id, @@ -29,11 +29,12 @@ def create_CoursePlan(id): db.session.commit() return plan + def getCoursePlan(studentid): return CoursePlan.query.filter_by(studentId=studentid).first() def possessPrereqs(Student, course): - # preqs = getPrereqCodes(course.courseName) + # preqs = getPrereqCodes(course.courseCode) # completed = getCompletedCourseCodes(Student.id) # for course in preqs: # if course not in completed: @@ -41,13 +42,23 @@ def possessPrereqs(Student, course): return True + +def getPlanCourses(student_id): + plan = getCoursePlan(student_id) + return get_all_courses_by_planid(plan.planId) + + + def addCourseToPlan(Student, courseCode): course = get_course_by_courseCode(courseCode) if course: + print("Course Found!") offered = isCourseOffered(courseCode) if offered: + print("course is offered") haveAllpreqs = possessPrereqs(Student, course) if haveAllpreqs: + print("all prereqs") plan = getCoursePlan(Student.id) if plan: createPlanCourse(plan.planId, courseCode) diff --git a/App/controllers/coursePlanCourses.py b/App/controllers/coursePlanCourses.py index b3c5bc8b1..c539903b8 100644 --- a/App/controllers/coursePlanCourses.py +++ b/App/controllers/coursePlanCourses.py @@ -6,6 +6,7 @@ def createPlanCourse(planid, code): db.session.add(course) db.session.commit() + def getCourseFromCoursePlan(planid, coursecode): return CoursePlanCourses.query.filter_by( planId = planid, diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 9d50921ce..9c009be2b 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -1,5 +1,5 @@ from App.models import Course -from App.controllers.prerequistes import (create_prereq, get_all_prerequisites) +from App.controllers.prerequistes import (create_prereq, get_prerequisites) from App.database import db import json, csv @@ -96,9 +96,9 @@ def get_all_OfferedCodes(): return offeredcodes def get_prerequisites(code): - course = get_course_by_courseCode(code) - prereqs = get_all_prerequisites(course.courseName) - return prereqs + # course = get_course_by_courseCode(code) + # prereqs = get_all_prerequisites(course.courseName) + return get_prerequisites(code) def get_credits(code): course = get_course_by_courseCode(code) diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 4bd3cc251..366fbb7b8 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -29,11 +29,14 @@ def create_prereq(course, prereqCode): def get_all_prerequisites(courseName): return Prerequisites.query.filter(Prerequisites.courseName == courseName).all() -def getPrereqCodes(courseName): - prereqs = get_all_prerequisites(courseName) +def get_prerequisites(courseCode): + return Prerequisites.query.filter_by(course_code = courseCode).all() + +def getPrereqCodes(courseCode): + prereqs = get_prerequisites(courseCode) codes = [] for p in prereqs: - codes.append(p.prereq_courseCode) + codes.append(p.prereq_code) return codes \ No newline at end of file diff --git a/App/models/coursePlan.py b/App/models/coursePlan.py index e3cfaa1e5..25e179b8a 100644 --- a/App/models/coursePlan.py +++ b/App/models/coursePlan.py @@ -1,19 +1,26 @@ from App.database import db class CoursePlan(db.Model): + __tablename__ = 'courseplan' + + planId=db.Column(db.Integer, primary_key=True) studentId=db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False) - - student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) + course_code = db.Column(db.ForeignKey('courses.courseCode')) + - # courses = db.relationship('CoursePlanCourses', backref = 'coursePlan', lazy=True) - def __init__(self, studentid, ): + # student = db.relationship('Student', backref=db.backref('course_plans', uselist=True)) + courseplancourses = db.relationship('CoursePlanCourses', backref = 'courseplan', lazy=True) + + def __init__(self, studentid): self.studentId = studentid + def get_json(self): return{ 'planId': self.planId, 'studentId': self.studentId, + 'courses' : [plancourse.get_json() for plancourse in self.courseplancourses] } \ No newline at end of file diff --git a/App/models/coursePlanCourses.py b/App/models/coursePlanCourses.py index 90d235a7e..29c174b04 100644 --- a/App/models/coursePlanCourses.py +++ b/App/models/coursePlanCourses.py @@ -1,13 +1,15 @@ + from App.database import db class CoursePlanCourses(db.Model): id = db.Column(db.Integer, primary_key=True) - planId = db.Column(db.ForeignKey('course_plan.planId')) + planId = db.Column(db.ForeignKey('courseplan.planId')) code = db.Column(db.ForeignKey('courses.courseCode')) - # associated_coursePlan = db.relationship('CoursePlan', back_populates='students', overlaps="coursePlan") - # associated_course = db.relationship('Course', back_populates='planIds', overlaps="courses") + + # courseplan = db.relationship('CoursePlan', back_populates='courses', overlaps="courseplan") + def __init__(self, plan, courseCode): self.planId = plan diff --git a/App/models/courses.py b/App/models/courses.py index 7f2283fde..ed1701af3 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -17,7 +17,10 @@ class Course(db.Model): students = db.relationship('StudentCourseHistory', backref='courses', lazy=True) programs = db.relationship('ProgramCourses', backref='courses', lazy=True) + coursePlan = db.relationship('CoursePlanCourses', backref='courses', lazy=True) prerequisites = db.relationship('Prerequisites', foreign_keys=[Prerequisites.course_code], lazy = True) + + def __init__(self, code, name, credits, rating, semester, level, offered): diff --git a/App/models/student.py b/App/models/student.py index d22fe560c..991ea68e6 100644 --- a/App/models/student.py +++ b/App/models/student.py @@ -9,6 +9,7 @@ class Student(User): associated_program = db.relationship('Program', back_populates='students', overlaps="program") courses = db.relationship('StudentCourseHistory', backref='student', lazy=True) + def __init__(self, username, password, name, program_id): diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 435fb45d0..0fd2979c6 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -4,7 +4,7 @@ class StudentCourseHistory(db.Model): __tablename__ = 'studentCourses' id = db.Column(db.Integer, primary_key=True) studentID = db.Column(db.ForeignKey('student.id')) - code = db.Column(db.ForeignKey('course.courseCode')) + code = db.Column(db.ForeignKey('courses.courseCode')) grade = db.Column(db.String) associated_course = db.relationship('Course', back_populates='students', overlaps="courses") diff --git a/wsgi.py b/wsgi.py index 97a2db617..b954482fd 100644 --- a/wsgi.py +++ b/wsgi.py @@ -26,13 +26,16 @@ create_staff, get_program_by_name, get_all_programCourses, - # addCoursetoHistory, + addCoursetoHistory, getCompletedCourseCodes, get_allCore, addCourseToPlan, get_student_by_id, generator, - list_all_courses + list_all_courses, + getCoursePlan, + create_CoursePlan, + getPlanCourses ) test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] @@ -151,6 +154,8 @@ def addCourse(ctx, student_id, code, grade): click.Argument(["grade"], type=str) ] + + @student_cli.command("getCompleted", help="Get all of a student completed courses") @click.argument("student_id", type=str) def completed(student_id): @@ -158,10 +163,12 @@ def completed(student_id): for c in comp: print(f'Course Code: {c.code}, Grade: {c.grade}') -@student_cli.command("addCourseToPlan", help="Adds a course to a student's course plan") -def courseToPlan(): - student = get_student_by_id("816") - addCourseToPlan(student, "COMP2611") + +# @student_cli.command("addCourseToPlan", help="Adds a course to a student's course plan") +# def courseToPlan(): +# student = get_student_by_id("816") +# addCourseToPlan(student, "COMP2611") + @student_cli.command("generate", help="Generates a course plan based on what they request") @click.argument("student_id", type=str) @@ -172,6 +179,11 @@ def generatePlan(student_id, command): for c in courses: print(c) +@student_cli.command("courseplan", help= "Get the current courseplan for a student") +@click.argument("student_id", type=str) +def getcourseplan(student_id): + print(getCoursePlan(student_id)) + app.cli.add_command(student_cli) @@ -431,7 +443,50 @@ def allSemCourses(): print("empty") + app.cli.add_command(course) -#lalalal this is a test comment +################################################################# + +''' +Course Plan Commands +''' + +course_plan = AppGroup('course_plan', help = 'Program object commands') + +@course_plan.command('newPlan', help = 'create a new courseplan for a student') +@click.argument('id', type=int) +def new_course_plan(id): + create_CoursePlan(id) + print("Course plan created!") + + +@course_plan.command('getPlan', help = 'get a courseplan for a student') +@click.argument('id', type=int) +def get_course_plan(id): + courseplan = getCoursePlan(id) + print (courseplan.get_json()) + + +@course_plan.command('AddCourse', help = 'add a new course for a student') +@click.argument('id', type=int) +@click.argument('courseCode', type = str) +def add_new_course(): + student = get_student_by_id("816") + plan = addCourseToPlan(student, "COMP2601") + if (plan): + print(plan.get_json()) + else: + print("no success") + +@course_plan.command('getplancourses', help = "get a list of courses in the course plan") +@click.argument('student_id', type = int) +def get_plan_courses(student_id): + plan_courses = getPlanCourses(student_id) + for plan in plan_courses: + print(plan.get_json()) + # print(getPlanCourses(student_id)) + + +app.cli.add_command(course_plan) \ No newline at end of file From a15dabc9b917fac91740e10ec05948a73a91c69f Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Sun, 3 Dec 2023 14:40:01 +0000 Subject: [PATCH 31/44] course planning updates pt 1 --- App/controllers/__init__.py | 4 +- App/controllers/courseOfferings.py | 8 ++- App/controllers/coursePlan.py | 76 ++++++++++++++++--------- App/controllers/coursePlanCourses.py | 24 +++++--- App/controllers/prerequistes.py | 10 ++-- App/controllers/programCourses.py | 55 +++++++++--------- App/controllers/studentCourseHistory.py | 12 +++- App/models/__init__.py | 5 ++ App/models/programCourses.py | 6 ++ App/models/studentCourseHistory.py | 4 +- wsgi.py | 1 - 11 files changed, 129 insertions(+), 76 deletions(-) diff --git a/App/controllers/__init__.py b/App/controllers/__init__.py index b0275d784..4d7978872 100644 --- a/App/controllers/__init__.py +++ b/App/controllers/__init__.py @@ -9,5 +9,5 @@ from .studentCourseHistory import * from .coursePlanCourses import * from .coursesOfferedPerSem import * -from .coursePlan import * -from .courseOfferings import * \ No newline at end of file +from .courseOfferings import * +from .coursePlan import * \ No newline at end of file diff --git a/App/controllers/courseOfferings.py b/App/controllers/courseOfferings.py index 315c9f0a1..2613d1f1d 100644 --- a/App/controllers/courseOfferings.py +++ b/App/controllers/courseOfferings.py @@ -80,4 +80,10 @@ def deleteCourseOffering(courseCode, academic_year, semester): db.session.rollback() print(f"An error occured when trying to delete the course from the course offerings: {e}") return False - + +def isCourseOffering(courseCode, academic_year, semester): + offering = CourseOfferings.query.filter_by(course_code=courseCode, academic_year=academic_year, semester=semester).first() + if offering: + return True + else: + return False diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 50ffab72a..9f3f92c00 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -11,61 +11,85 @@ get_allCore, get_allFoun, get_allElectives, - getCompletedCourseCodes, + getPassedCourseCodes, convertToList, get_all_OfferedCodes, isCourseOffered, programCourses_SortedbyRating, programCourses_SortedbyHighestCredits, get_all_courses_by_planid, - + isCourseOffering ) -def create_CoursePlan(id): - plan = CoursePlan(id) - db.session.add(plan) - db.session.commit() - return plan +def create_CoursePlan(id, year, sem): + plan = CoursePlan.query.filter_by(studentId=id, academic_year=year, semester=sem).first() + if plan: + print("Course plan exists already") + return None + try: + if CoursePlan.checkAcademicYearFormat(year): + if sem == 1 or sem == 2 or sem == 3: + plan = CoursePlan(id, year, sem) + if plan: + db.session.add(plan) + db.session.commit() + print("Course offering created successfully") + return plan + else: + print("The course plan could not be created") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") + else: + print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to create the course plan: {e}") -def getCoursePlan(studentid): - return CoursePlan.query.filter_by(studentId=studentid).first() +def getCoursePlan(studentid, year, sem): + return CoursePlan.query.filter_by(studentId=studentid, academic_year=year, semester=sem).first() -def possessPrereqs(Student, course): - preqs = getPrereqCodes(course.courseName) - completed = getCompletedCourseCodes(Student.id) +def possessPrereqs(studentId, courseCode): + preqs = getPrereqCodes(courseCode) + completed = getPassedCourseCodes(studentId) for course in preqs: if course not in completed: return False return True -def addCourseToPlan(Student, courseCode): +def addCourseToPlan(studentId, year, sem, courseCode): course = get_course_by_courseCode(courseCode) if course: offered = isCourseOffered(courseCode) if offered: - haveAllpreqs = possessPrereqs(Student, course) - if haveAllpreqs: - plan = getCoursePlan(Student.id) - if plan: - createPlanCourse(plan.planId, courseCode) - print("Course successfully added to course plan") - return plan + offering = isCourseOffering(courseCode, year, sem) + if offering: + haveAllpreqs = possessPrereqs(studentId, course) + if haveAllpreqs: + plan = getCoursePlan(studentId, year, sem) + if plan: + createPlanCourse(plan.planId, courseCode) + print("Course successfully added to course plan") + return plan + else: + plan = create_CoursePlan(studentId, year, sem) + createPlanCourse(plan.planId, courseCode) + print("Plan successfully created and Course was successfully added to course plan") + return plan else: - plan = create_CoursePlan(Student.id) - createPlanCourse(plan.planId, courseCode) - print("Plan successfully created and Course was successfully added to course plan") - return plan + print("Missing prerequisites") + else: + print("Course not being offered for requested semester") else: print("Course is not offered") else: print("Course does not exist") -def removeCourse(Student, courseCode): - plan=getCoursePlan(Student.id) +def removeCourse(studentid, year, sem, courseCode): + plan=getCoursePlan(studentid, year, sem) if plan: deleteCourseFromCoursePlan(plan.planId, courseCode) diff --git a/App/controllers/coursePlanCourses.py b/App/controllers/coursePlanCourses.py index b3c5bc8b1..afa87766f 100644 --- a/App/controllers/coursePlanCourses.py +++ b/App/controllers/coursePlanCourses.py @@ -2,24 +2,30 @@ from App.database import db def createPlanCourse(planid, code): - course = CoursePlanCourses(planid, code) - db.session.add(course) - db.session.commit() + exists = CoursePlanCourses.query.filter_by(planId=planid, code=code).first() + if exists: + print("Course plan course exists already") + return None + try: + course = CoursePlanCourses(planid, code) + db.session.add(course) + db.session.commit() + except Exception as e: + db.session.rollback() + print(f"An error occured when trying to add a course to the course plan: {e}") def getCourseFromCoursePlan(planid, coursecode): - return CoursePlanCourses.query.filter_by( - planId = planid, - code = coursecode - ).first() + return CoursePlanCourses.query.filter_by(planId = planid, code = coursecode).first() def get_all_courses_by_planid(id): return CoursePlanCourses.query.filter_by(planId=id).all() def deleteCourseFromCoursePlan(planid, coursecode): course = getCourseFromCoursePlan(planid, coursecode) - if course: + try: db.session.delete(course) db.session.commit() print("Course succesfully removed from course plan") - else: + except Exception as e: + db.session.rollback() print("Course is not in Course Plan") diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 4bd3cc251..deb94a095 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -26,14 +26,14 @@ def create_prereq(course, prereqCode): -def get_all_prerequisites(courseName): - return Prerequisites.query.filter(Prerequisites.courseName == courseName).all() +def get_all_prerequisites(courseCode): + return Prerequisites.query.filter_by(course_code = courseCode).all() -def getPrereqCodes(courseName): - prereqs = get_all_prerequisites(courseName) +def getPrereqCodes(courseCode): + prereqs = get_all_prerequisites(courseCode) codes = [] for p in prereqs: - codes.append(p.prereq_courseCode) + codes.append(p.prereq_code) return codes \ No newline at end of file diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 955554d37..f216f5f99 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -3,18 +3,26 @@ from App.database import db def create_programCourse(programName, code, num): - program = get_program_by_name(programName) - if program: - course = get_course_by_courseCode(code) - if course: - proCourse = ProgramCourses(program.id, code, num) - db.session.add(proCourse) - db.session.commit() - return proCourse + try: + program = get_program_by_name(programName) + if program: + course = get_course_by_courseCode(code) + if course: + proCourse = ProgramCourses.query.filter_by(program_id=program.id, code=code, courseType=num) + if proCourse: + print("Course already added to program") + else: + proCourse = ProgramCourses(program.id, code, num) + db.session.add(proCourse) + db.session.commit() + return proCourse + else: + return "Invalid course code" else: - return "Invalid course code" - else: - return "Invalid program name" + return "Invalid program name" + except Exception as e: + db.session.rollback() + print("Error occured when trying to add course to program") def get_all_programCourses(programName): program = get_program_by_name(programName) @@ -22,35 +30,26 @@ def get_all_programCourses(programName): def get_allCore(programName): program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by( - program_id=program.id, - courseType=1 - ).all() + core = ProgramCourses.query.filter_by(program_id=program.id, courseType=1).all() return core if core else [] def get_allElectives(programName): program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by( - program_id=program.id, - courseType=2 - ).all() + core = ProgramCourses.query.filter_by(program_id=program.id, courseType=2).all() return core if core else [] def get_allFoun(programName): program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by( - program_id=program.id, - courseType=3 - ).all() + core = ProgramCourses.query.filter_by(program_id=program.id, courseType=3).all() return core if core else [] -def convertToList(list): - codes = [] +def convertToList(programCourses): + courseCodes = [] - for a in list: - codes.append(a.code) + for programCourse in programCourses: + courseCodes.append(programCourse.code) - return codes + return courseCodes def programCourses_SortedbyRating(programid): program = get_program_by_id(programid) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index 81d57fe8e..8305293d5 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -45,11 +45,19 @@ def addCoursetoHistory(student_id, course_code, grade): def getCompletedCourses(id): return StudentCourseHistory.query.filter_by(studentID=id).all() +def getPassedCourseCodes(id): + completed = getCompletedCourses(id) + passed = [] + for course in completed: + if course.grade != "F1" or course.grade != "F2" or course.grade != "F3": + passed.append(course.courseCode) + return passed + def getCompletedCourseCodes(id): completed_courses = getCompletedCourses(id) codes = [] for course in completed_courses: - codes.append(course.code) + codes.append(course.courseCode) - return completed_courses # Return instances, not just codes + return codes diff --git a/App/models/__init__.py b/App/models/__init__.py index de91ac513..f99ec3157 100644 --- a/App/models/__init__.py +++ b/App/models/__init__.py @@ -11,3 +11,8 @@ from .coursePlanCourses import * from .coursePlan import * from .courseOfferings import * +from .CoursePlanner import * +from .CoursePlannerStrategy import * +from .EasyCoursePlanner import * +from .ElectiveCoursePlanner import * +from .FastCoursePlanner import * diff --git a/App/models/programCourses.py b/App/models/programCourses.py index 201c05a8e..5855cd709 100644 --- a/App/models/programCourses.py +++ b/App/models/programCourses.py @@ -3,6 +3,12 @@ class ProgramCourses(db.Model): + ''' + Course Typing: + 1: core + 2: elective + 3: foun + ''' __tablename__ ='program_courses' id = db.Column(db.Integer, primary_key=True) diff --git a/App/models/studentCourseHistory.py b/App/models/studentCourseHistory.py index 435fb45d0..bcef66d1f 100644 --- a/App/models/studentCourseHistory.py +++ b/App/models/studentCourseHistory.py @@ -4,8 +4,8 @@ class StudentCourseHistory(db.Model): __tablename__ = 'studentCourses' id = db.Column(db.Integer, primary_key=True) studentID = db.Column(db.ForeignKey('student.id')) - code = db.Column(db.ForeignKey('course.courseCode')) - grade = db.Column(db.String) + code = db.Column(db.String(8), db.ForeignKey('courses.courseCode')) + grade = db.Column(db.String(10)) associated_course = db.relationship('Course', back_populates='students', overlaps="courses") associated_student = db.relationship('Student', back_populates='courses', overlaps="student") diff --git a/wsgi.py b/wsgi.py index 1a74b6fd6..f39b89865 100644 --- a/wsgi.py +++ b/wsgi.py @@ -2,7 +2,6 @@ import random import csv from flask import Flask -from App.controllers.student import create_student from flask.cli import with_appcontext, AppGroup from App.database import db, get_migrate From 286c2d10fa9e2348659c10dd006acca391b3f5ee Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Sun, 3 Dec 2023 18:03:38 +0000 Subject: [PATCH 32/44] course planning update pt 2 --- App/controllers/coursePlan.py | 333 +++++++++++------------- App/controllers/program.py | 21 +- App/controllers/programCourses.py | 51 +++- App/controllers/student.py | 27 +- App/controllers/studentCourseHistory.py | 29 ++- App/models/EasyCoursePlanner.py | 6 +- App/models/ElectiveCoursePlanner.py | 6 +- App/models/FastCoursePlanner.py | 4 + App/views/student.py | 2 +- wsgi.py | 10 +- 10 files changed, 264 insertions(+), 225 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 9f3f92c00..3d8debf56 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -8,9 +8,7 @@ getCompletedCourses, createPlanCourse, deleteCourseFromCoursePlan, - get_allCore, - get_allFoun, - get_allElectives, + getProgramCoursesByType, getPassedCourseCodes, convertToList, get_all_OfferedCodes, @@ -18,31 +16,36 @@ programCourses_SortedbyRating, programCourses_SortedbyHighestCredits, get_all_courses_by_planid, - isCourseOffering + isCourseOffering, + getCompletedCourseCodes, + get_student_by_id, + getCourseOfferingsByYearAndSemester, + get_all_programCourses ) def create_CoursePlan(id, year, sem): - plan = CoursePlan.query.filter_by(studentId=id, academic_year=year, semester=sem).first() - if plan: - print("Course plan exists already") - return None try: - if CoursePlan.checkAcademicYearFormat(year): - if sem == 1 or sem == 2 or sem == 3: - plan = CoursePlan(id, year, sem) - if plan: - db.session.add(plan) - db.session.commit() - print("Course offering created successfully") - return plan - else: - print("The course plan could not be created") + plan = CoursePlan.query.filter_by(studentId=id, academic_year=year, semester=sem).first() + if plan: + print("Course plan exists already") + return None + else: + if CoursePlan.checkAcademicYearFormat(year): + if sem == 1 or sem == 2 or sem == 3: + plan = CoursePlan(id, year, sem) + if plan: + db.session.add(plan) + db.session.commit() + print("Course offering created successfully") + return plan + else: + print("The course plan could not be created") + else: + print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") else: - print(f"The semester is invalid. There are 3 semesters: 1, 2, 3") - else: - print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") + print(f"Academic year format incorrect. Should be yyyy/yyyy e.g. 2022/2023") except Exception as e: db.session.rollback() print(f"An error occured when trying to create the course plan: {e}") @@ -87,216 +90,190 @@ def addCourseToPlan(studentId, year, sem, courseCode): else: print("Course does not exist") - -def removeCourse(studentid, year, sem, courseCode): +def removeCourseFromPlan(studentid, year, sem, courseCode): plan=getCoursePlan(studentid, year, sem) if plan: deleteCourseFromCoursePlan(plan.planId, courseCode) -def getRemainingCourses(completed, required): - # Check if either 'completed' or 'required' is None - if completed is None or required is None: - return [] # Return an empty list or handle it in a way that makes sense for your application - - completedCodes = [] - for c in completed: - completedCodes.append(c.code) - - remainingCodes = [] - for r in required: - remainingCodes.append(r.code) - - - notCompleted = remainingCodes.copy() - for a in completedCodes: - if a in notCompleted: - notCompleted.remove(a) - - return notCompleted - - -def getRemainingCore(Student): - programme=get_program_by_id(Student.program_id) +def getRemainingCoursesByType(student_id, type): + student=get_student_by_id(student_id) + program=get_program_by_id(student.program_id) remaining = [] - if programme: - reqCore=get_allCore(programme.name) - completed = getCompletedCourses(Student.id) - remaining=getRemainingCourses(completed,reqCore) - - return remaining + if program: + required=getProgramCoursesByType(program.name, type) + completed = getPassedCourseCodes(student_id) + if completed == []: + return required -def getRemainingFoun(Student): - programme = get_program_by_id(Student.program_id) - remaining =[] + remaining = required.copy() + for course in completed: + if course in required: + remaining.remove(course) - if programme: - reqFoun = get_allFoun(programme.name) - completed = getCompletedCourses(Student.id) - remaining=getRemainingCourses(completed,reqFoun) - return remaining - -def getRemainingElec(Student): - programme = get_program_by_id(Student.program_id) # Get the student's program - remaining = [] - - if programme: - reqElec = get_allElectives(programme.name) # Use the instance method to get elective courses - completed = getCompletedCourses(Student.id) - remaining = getRemainingCourses(completed, reqElec) - - return remaining - - -def remElecCredits(Student): - programme = get_program_by_id(Student.program_id) # Get the student's program - completedcourses = getCompletedCourseCodes(Student.id) - requiredCreds = 0 - - if programme: - requiredCreds = programme.elective_credits # Access the elective_credits attribute - elective_courses = get_allElectives(programme.name) # Use the instance method to get elective courses - electCodes = convertToList(elective_courses) - if electCodes: - for code in electCodes: - if code in completedcourses: - c = get_course_by_courseCode(code) # Get course - if c: - requiredCreds = requiredCreds - c.credits # Subtract credits +def getRemainingCreditsByCourseType(student_id, type): + remaining = getRemainingCoursesByType(student_id, type) + student=get_student_by_id(student_id) + program=get_program_by_id(student.program_id) + requiredCreds=0 + if type == 1: + requiredCreds=program.core_credits + elif type == 2: + requiredCreds=program.elective_credits + elif type == 3: + requiredCreds=program.foun_credits + + for code in remaining: + course = get_course_by_courseCode(code) + if course: + requiredCreds = requiredCreds - course.credits + return requiredCreds +''' + @getAllAvailableCourseOptions + filters each course being offered in the specified semester by if: + - the student passed it already + - the student's program has it + - the student has all the prerequisites to take it + and compiles a list of courses the student can take +''' +def getAllAvailableCourseOptions(student_id, year, sem): + offerings = getCourseOfferingsByYearAndSemester(year, sem) + offeringCourseCodes = [] + for offering in offerings: + offeringCourseCodes.append(offering.course_code) + + student = get_student_by_id(student_id) + program = get_program_by_id(student.program_id) + programCourses = get_all_programCourses(program.name) + programCourseCodes = [] + for programCourse in programCourses: + programCourseCodes.append(programCourse.code) + + passed = getPassedCourseCodes(student_id) -def findAvailable(courseList): - listing=get_all_OfferedCodes() available=[] - for code in courseList: - if code in listing: - available.append(code) + for code in offeringCourseCodes: + if code not in passed: + if code in programCourseCodes: + if possessPrereqs(student.id, code): + available.append(code) return available #returns an array of course codes +# previous code - seems unnecessary +# def getTopfive(list): +# return list[:5] -def checkPrereq(Student, recommnded): - validCourses=[] - for course in recommnded: - c = get_course_by_courseCode(course) - satisfied = possessPrereqs(Student, c) - if satisfied: - validCourses.append(c.courseCode) +# def prioritizeElectives(Student): +# #get available electives +# electives=findAvailable(getRemainingElec(Student)) +# credits=remElecCredits(Student) +# courses=[] - return validCourses - -def getTopfive(list): - return list[:5] - -def prioritizeElectives(Student): - #get available electives - electives=findAvailable(getRemainingElec(Student)) - credits=remElecCredits(Student) - courses=[] - - #select courses to satisfy the programme's credit requirements - for c in electives: - if credits>0: - courses.append(c) - credits = credits - get_credits(c) +# #select courses to satisfy the programme's credit requirements +# for c in electives: +# if credits>0: +# courses.append(c) +# credits = credits - get_credits(c) - #merge available, required core and foundation courses - courses = courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) +# #merge available, required core and foundation courses +# courses = courses + findAvailable(getRemainingCore(Student)) + findAvailable(getRemainingFoun(Student)) - courses = checkPrereq(Student,courses) - return getTopfive(courses) +# courses = checkPrereq(Student,courses) +# return getTopfive(courses) -def removeCoursesFromList(list1,list2): - newlist = list2.copy() - for a in list1: - if a in newlist: - newlist.remove(a) - return newlist +# def removeCoursesFromList(list1,list2): +# newlist = list2.copy() +# for a in list1: +# if a in newlist: +# newlist.remove(a) +# return newlist -def easyCourses(Student): - program = get_program_by_id(Student.program_id) - completed = getCompletedCourseCodes(Student.id) - codesSortedbyRating = programCourses_SortedbyRating(Student.program_id) +# def easyCourses(Student): +# program = get_program_by_id(Student.program_id) +# completed = getCompletedCourseCodes(Student.id) +# codesSortedbyRating = programCourses_SortedbyRating(Student.program_id) - coursesToDo = removeCoursesFromList(completed, codesSortedbyRating) +# coursesToDo = removeCoursesFromList(completed, codesSortedbyRating) - elecCredits = remElecCredits(Student) +# elecCredits = remElecCredits(Student) - if elecCredits == 0: - allElectives = convertToList(get_allElectives(program.name)) - coursesToDo = removeCoursesFromList(allElectives, coursesToDo) +# if elecCredits == 0: +# allElectives = convertToList(get_allElectives(program.name)) +# coursesToDo = removeCoursesFromList(allElectives, coursesToDo) - coursesToDo = findAvailable(coursesToDo) +# coursesToDo = findAvailable(coursesToDo) - ableToDo = checkPrereq(Student, coursesToDo) - # for a in ableToDo: - # print(a) +# ableToDo = checkPrereq(Student, coursesToDo) +# # for a in ableToDo: +# # print(a) - return getTopfive(ableToDo) +# return getTopfive(ableToDo) -def fastestGraduation(Student): - program = get_program_by_id(Student.program_id) - sortedCourses = programCourses_SortedbyHighestCredits(Student.program_id) - completed = getCompletedCourseCodes(Student.id) +# def fastestGraduation(Student): +# program = get_program_by_id(Student.program_id) +# sortedCourses = programCourses_SortedbyHighestCredits(Student.program_id) +# completed = getCompletedCourseCodes(Student.id) - coursesToDo = removeCoursesFromList(completed, sortedCourses) +# coursesToDo = removeCoursesFromList(completed, sortedCourses) - elecCredits = remElecCredits(Student) +# elecCredits = remElecCredits(Student) - if elecCredits == 0: - allElectives = convertToList(get_allElectives(program.name)) - coursesToDo = removeCoursesFromList(allElectives, coursesToDo) +# if elecCredits == 0: +# allElectives = convertToList(get_allElectives(program.name)) +# coursesToDo = removeCoursesFromList(allElectives, coursesToDo) - coursesToDo = findAvailable(coursesToDo) - ableToDo = checkPrereq(Student, coursesToDo) +# coursesToDo = findAvailable(coursesToDo) +# ableToDo = checkPrereq(Student, coursesToDo) - return getTopfive(ableToDo) +# return getTopfive(ableToDo) -def commandCall(Student, command): - courses = [] +# def commandCall(Student, command): +# courses = [] - if command == "electives": - courses = prioritizeElectives(Student) +# if command == "electives": +# courses = prioritizeElectives(Student) - elif command == "easy": - courses = easyCourses(Student) +# elif command == "easy": +# courses = easyCourses(Student) - elif command == "fastest": - courses = fastestGraduation(Student) +# elif command == "fastest": +# courses = fastestGraduation(Student) - else: - print("Invalid command") +# else: +# print("Invalid command") - return courses +# return courses -def generator(Student, command): - courses = [] +# def generator(Student, command): +# courses = [] - plan = getCoursePlan(Student.id) +# plan = getCoursePlan(Student.id) - if plan is None: - plan = plan = create_CoursePlan(Student.id) +# if plan is None: +# plan = plan = create_CoursePlan(Student.id) - courses = commandCall(Student, command) +# courses = commandCall(Student, command) - existingPlanCourses = get_all_courses_by_planid(plan.planId) +# existingPlanCourses = get_all_courses_by_planid(plan.planId) - planCourses = [] - for q in existingPlanCourses: - planCourses.append(q.code) +# planCourses = [] +# for q in existingPlanCourses: +# planCourses.append(q.code) - for c in courses: - if c not in planCourses: - createPlanCourse(plan.planId, c) +# for c in courses: +# if c not in planCourses: +# createPlanCourse(plan.planId, c) - return courses \ No newline at end of file +# return courses \ No newline at end of file diff --git a/App/controllers/program.py b/App/controllers/program.py index 4f2cdc29f..fa639cfe8 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -2,13 +2,20 @@ from App.database import db def create_program(name, core, elective, foun): - newProgram = Program(name, core, elective, foun) - db.session.add(newProgram) - print("Program successfully created") - db.session.commit() - return newProgram - - + try: + program = Program.query.filter_by(name=name, core_credits=core, elective_credits=elective, foun_credits=foun).first() + if program is not None: + print("Program exits already") + return None + else: + newProgram = Program(name, core, elective, foun) + db.session.add(newProgram) + print("Program successfully created") + db.session.commit() + return newProgram + except Exception as e: + db.session.rollback() + print(f'Error occured when creating program: {e}') def get_program_by_name(programName): return Program.query.filter_by(name=programName).first() diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index f216f5f99..a311bedc7 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -8,7 +8,7 @@ def create_programCourse(programName, code, num): if program: course = get_course_by_courseCode(code) if course: - proCourse = ProgramCourses.query.filter_by(program_id=program.id, code=code, courseType=num) + proCourse = ProgramCourses.query.filter_by(program_id=program.id, code=code, courseType=num).first() if proCourse: print("Course already added to program") else: @@ -22,26 +22,36 @@ def create_programCourse(programName, code, num): return "Invalid program name" except Exception as e: db.session.rollback() - print("Error occured when trying to add course to program") + print(f'Error occured when trying to add course to program: {e}') def get_all_programCourses(programName): program = get_program_by_name(programName) return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() -def get_allCore(programName): +# new function to get core, elective or foun courses +def getProgramCoursesByType(programName, type): program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by(program_id=program.id, courseType=1).all() - return core if core else [] + programCourses = ProgramCourses.query.filter_by(program_id=program.id, courseType=type).all() + courseCodes = [] + for programCourse in programCourses: + courseCodes.append(programCourse.code) + return courseCodes -def get_allElectives(programName): - program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by(program_id=program.id, courseType=2).all() - return core if core else [] +# repetitive +# def get_allCore(programName): +# program = get_program_by_name(programName) +# core = ProgramCourses.query.filter_by(program_id=program.id, courseType=1).all() +# return core if core else [] -def get_allFoun(programName): - program = get_program_by_name(programName) - core = ProgramCourses.query.filter_by(program_id=program.id, courseType=3).all() - return core if core else [] +# def get_allElectives(programName): +# program = get_program_by_name(programName) +# core = ProgramCourses.query.filter_by(program_id=program.id, courseType=2).all() +# return core if core else [] + +# def get_allFoun(programName): +# program = get_program_by_name(programName) +# core = ProgramCourses.query.filter_by(program_id=program.id, courseType=3).all() +# return core if core else [] def convertToList(programCourses): courseCodes = [] @@ -51,6 +61,20 @@ def convertToList(programCourses): return courseCodes +# new function to get courses with a specific rating +def getProgramCoursesByRating(programName, rating): + courses = [] + program = get_program_by_name(programName) + programCourses = ProgramCourses.query.all.filter_by(program_id=program.id).all() + for programCourse in programCourses: + course = get_course_by_courseCode(programCourse.code) + if course.rating == rating: + courses.append(course) + if courses == []: + print("No courses found in the given program with the given rating") + return courses if courses else [] + +# from previous code - not tested def programCourses_SortedbyRating(programid): program = get_program_by_id(programid) programCourses = get_all_programCourses(program.name) @@ -65,6 +89,7 @@ def programCourses_SortedbyRating(programid): return sorted_courses_list +# from previous code - seems unnecessary def programCourses_SortedbyHighestCredits(programid): program = get_program_by_id(programid) programCourses = get_all_programCourses(program.name) diff --git a/App/controllers/student.py b/App/controllers/student.py index e3248e4b3..d681603df 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -3,15 +3,24 @@ from App.database import db def create_student(student_id, password, name, programname): - program = get_program_by_name(programname) - if program: - new_student = Student(student_id, password, name, program.id) - db.session.add(new_student) - db.session.commit() - return new_student - print("Student successfully created") - else: - print("Program doesn't exist") + try: + program = get_program_by_name(programname) + if program: + student = Student.query.filter_by(id=student_id, name=name, program_id=program.id).first() + if student is not None: + print("Student exists already") + return None + else: + new_student = Student(student_id, password, name, program.id) + db.session.add(new_student) + db.session.commit() + print("Student successfully created") + return new_student + else: + print("Program doesn't exist") + except Exception as e: + db.session.rollback() + print(f'Error creating student: {e}') def get_student_by_id(ID): return Student.query.filter_by(id=ID).first() diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index 8305293d5..a88e99383 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -4,17 +4,26 @@ def addCoursetoHistory(studentid, code, grade): - student = get_student_by_id(studentid) - if student: - course = get_course_by_courseCode(code) - if course: - completed = StudentCourseHistory(studentid, code, grade) - db.session.add(completed) - db.session.commit() + try: + exists = StudentCourseHistory.query.filter_by(studentID=studentid, code=code, grade=grade).first() + if exists is not None: + print("Course added to history already") + return None else: - print("Course doesn't exist") - else: - print("Student doesn't exist") + student = get_student_by_id(studentid) + if student: + course = get_course_by_courseCode(code) + if course: + completed = StudentCourseHistory(studentid, code, grade) + db.session.add(completed) + db.session.commit() + else: + print("Course doesn't exist") + else: + print("Student doesn't exist") + except Exception as e: + db.session.rollback() + print(f'Error adding course to student history: {e}') ''' def addCoursetoHistory(student_id, course_code, grade): diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 2d81f8a36..fa5e663f4 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -1,8 +1,12 @@ from App.database import db from App.models import CoursePlan, CoursePlannerStrategy from typing import List +from App.controllers import ( + getAllAvailableCourseOptions + #add as needed +) -# Concrete Strategy: Fast +# Concrete Strategy: Easy class EasyCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]) -> CoursePlan: # implement logic diff --git a/App/models/ElectiveCoursePlanner.py b/App/models/ElectiveCoursePlanner.py index a4f037828..28b42e384 100644 --- a/App/models/ElectiveCoursePlanner.py +++ b/App/models/ElectiveCoursePlanner.py @@ -1,8 +1,12 @@ from App.database import db from App.models import CoursePlan, CoursePlannerStrategy from typing import List +from App.controllers import ( + getAllAvailableCourseOptions + #add as needed +) -# Concrete Strategy: Fast +# Concrete Strategy: Elective class ElectiveCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]) -> CoursePlan: # implement logic diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index 9ccf58f77..eb1c39546 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -1,6 +1,10 @@ from App.database import db from App.models import CoursePlan, CoursePlannerStrategy from typing import List +from App.controllers import ( + getAllAvailableCourseOptions + #add as needed +) # Concrete Strategy: Fast class FastCoursePlanner(CoursePlannerStrategy): diff --git a/App/views/student.py b/App/views/student.py index 4a0cb1e33..b8df7ab15 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -15,7 +15,7 @@ get_course_by_courseCode, addCoursetoHistory, getCompletedCourseCodes, - generator, + # generator, - addCourseToPlan, verify_student ) diff --git a/wsgi.py b/wsgi.py index f39b89865..f7f45f035 100644 --- a/wsgi.py +++ b/wsgi.py @@ -27,10 +27,10 @@ get_all_programCourses, addCoursetoHistory, getCompletedCourseCodes, - get_allCore, + # get_allCore, addCourseToPlan, get_student_by_id, - generator, + # generator, list_all_courses ) @@ -52,9 +52,9 @@ def initialize(): db.create_all() create_user('bob', 'bobpass') createCoursesfromFile('testData/courseData.csv') - create_program("Computer Science Major", 69, 15, 9) - create_student(816, "boo", "testing", "Computer Science Major") - create_staff("adminpass","999", "admin") + create_program("Testing", 69, 15, 9) + create_student(816, "testpass", "test", "Testing") + create_staff("staffpass","999", "staff") for c in test1: grade = random.choice(['A', 'B', 'C', 'F']) From ee285c5bf652451325fbbad34c1ca8f9062b3b89 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 19:17:21 +0000 Subject: [PATCH 33/44] update DP and wsgi, EasyCoursePlanner called --- App/models/CoursePlanner.py | 7 ++++--- App/models/CoursePlannerStrategy.py | 5 +++-- App/models/EasyCoursePlanner.py | 10 ++++++++-- App/models/courses.py | 2 +- wsgi.py | 28 ++++++++++++++++++++++++++-- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/App/models/CoursePlanner.py b/App/models/CoursePlanner.py index 1df2f4331..16ec96f34 100644 --- a/App/models/CoursePlanner.py +++ b/App/models/CoursePlanner.py @@ -1,6 +1,6 @@ from typing import List from App.database import db -from App.models import CoursePlannerStrategy, CoursePlan +from App.models import CoursePlannerStrategy, CoursePlan, student # Context class CoursePlanner: @@ -10,5 +10,6 @@ def __init__(self, strategy: CoursePlannerStrategy): def set_strategy(self, strategy: CoursePlannerStrategy): self._strategy = strategy - def plan_courses(self, data: List[str]) -> CoursePlan: - return self._strategy.search(data) \ No newline at end of file +#changed data : List[str] to int for studentID + def plan_courses(self, data: int) -> CoursePlan: + return self._strategy.planCourses(data) \ No newline at end of file diff --git a/App/models/CoursePlannerStrategy.py b/App/models/CoursePlannerStrategy.py index 32d3f8b4c..6de9b7a8f 100644 --- a/App/models/CoursePlannerStrategy.py +++ b/App/models/CoursePlannerStrategy.py @@ -6,5 +6,6 @@ # Strategy Interface class CoursePlannerStrategy(ABC): @abstractmethod - def planCourses(self, data: List[str]) -> CoursePlan: - pass \ No newline at end of file + def planCourses(self, data: int) -> CoursePlan: + pass + diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index fa5e663f4..290e0fd5f 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -1,5 +1,5 @@ from App.database import db -from App.models import CoursePlan, CoursePlannerStrategy +from App.models import CoursePlan, CoursePlannerStrategy, student from typing import List from App.controllers import ( getAllAvailableCourseOptions @@ -8,6 +8,12 @@ # Concrete Strategy: Easy class EasyCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str]) -> CoursePlan: + def planCourses(self, data: int) -> CoursePlan: # implement logic + + + print("Yes the easycourse planner is being called") + + + pass \ No newline at end of file diff --git a/App/models/courses.py b/App/models/courses.py index ed1701af3..f2fdfde4c 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -42,5 +42,5 @@ def get_json(self): 'Level: ': self.level, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, - 'Prerequisites: ': [prereq.get_json() for prereq in self.prerequisites] + 'Prerequisites: ': our } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index ad8c6a921..90811a0db 100644 --- a/wsgi.py +++ b/wsgi.py @@ -4,6 +4,10 @@ from flask import Flask from flask.cli import with_appcontext, AppGroup + +from App.models.EasyCoursePlanner import EasyCoursePlanner +from App.models.CoursePlanner import CoursePlanner + from App.database import db, get_migrate from App.main import create_app from App.controllers import ( @@ -31,7 +35,7 @@ addCourseToPlan, get_student_by_id, # generator, - list_all_courses + list_all_courses, ) test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] @@ -485,4 +489,24 @@ def get_plan_courses(student_id): # print(getPlanCourses(student_id)) -app.cli.add_command(course_plan) \ No newline at end of file +app.cli.add_command(course_plan) + + +''' +Course Plan Generator Commands +''' + +generate = AppGroup('generate', help = 'Generate a course plan based on strategy selected') + +@generate.command("easy") +# @click.argument('student_ID', type = int) +def easyPlan(): + strategy = EasyCoursePlanner() + context = CoursePlanner(strategy) + + + result = context.plan_courses(816) + + + +app.cli.add_command(generate) \ No newline at end of file From 88710940124fdc4c016d9f4a5d014edf0482c5b9 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 19:18:10 +0000 Subject: [PATCH 34/44] minor fix on wsgi function --- wsgi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wsgi.py b/wsgi.py index 90811a0db..6c7421e3c 100644 --- a/wsgi.py +++ b/wsgi.py @@ -499,13 +499,13 @@ def get_plan_courses(student_id): generate = AppGroup('generate', help = 'Generate a course plan based on strategy selected') @generate.command("easy") -# @click.argument('student_ID', type = int) -def easyPlan(): +@click.argument('student_id', type = int) +def easyPlan(student_id): strategy = EasyCoursePlanner() context = CoursePlanner(strategy) - result = context.plan_courses(816) + result = context.plan_courses(student_id) From 3b85b4f869466c7b1a65528c44d2f6f4f4d0ac78 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 21:13:56 +0000 Subject: [PATCH 35/44] latest changes --- App/controllers/program.py | 12 +++++++----- App/controllers/programCourses.py | 5 +++++ App/models/EasyCoursePlanner.py | 12 ++++++++++-- App/models/courses.py | 2 +- wsgi.py | 3 ++- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/App/controllers/program.py b/App/controllers/program.py index fa639cfe8..a0eac33a3 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -60,12 +60,14 @@ def get_foun_courses(programName): return courses if program else [] def get_all_courses(programName): - core_courses = get_core_courses(programName) - elective_courses = get_elective_courses(programName) - foun_courses = get_foun_courses(programName) + # core_courses = get_core_courses(programName) + # elective_courses = get_elective_courses(programName) + # foun_courses = get_foun_courses(programName) - all = core_courses + elective_courses + foun_courses - return all + # all = core_courses + elective_courses + foun_courses + # return all + program = get_program_by_name(programName) + return program.courses diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index a311bedc7..726434c6f 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -28,6 +28,11 @@ def get_all_programCourses(programName): program = get_program_by_name(programName) return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() + +def get_all_programCourses(program_id): + program = get_program_by_id(program_id) + return ProgramCourses.query.filter(ProgramCourses.program_id == program_id).all() + # new function to get core, elective or foun courses def getProgramCoursesByType(programName, type): program = get_program_by_name(programName) diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 290e0fd5f..57bf141cf 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -2,7 +2,9 @@ from App.models import CoursePlan, CoursePlannerStrategy, student from typing import List from App.controllers import ( - getAllAvailableCourseOptions + getAllAvailableCourseOptions, + get_student_by_id, + get_all_programCourses #add as needed ) @@ -10,9 +12,15 @@ class EasyCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: int) -> CoursePlan: # implement logic + student = get_student_by_id(data) + program = student.associated_program + program_courses = get_all_programCourses(program.id) + print (program.get_json()) + + for x in program_courses: + print(x.get_json()) - print("Yes the easycourse planner is being called") diff --git a/App/models/courses.py b/App/models/courses.py index f2fdfde4c..14a509e32 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -42,5 +42,5 @@ def get_json(self): 'Level: ': self.level, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, - 'Prerequisites: ': our + 'Prerequisites: ': "placeholder" } \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 6c7421e3c..48bec405a 100644 --- a/wsgi.py +++ b/wsgi.py @@ -365,7 +365,7 @@ def get_CoreCredits(programname): @click.argument('programname', type=str) def allCourses(programname): all = get_all_courses(programname) - print(f'All courses are = {all}') if credits else print(f'error') + print(all) @program.command('getprogram', help='Get a program by name') @click.argument('programname', type=str) @@ -507,6 +507,7 @@ def easyPlan(student_id): result = context.plan_courses(student_id) + app.cli.add_command(generate) \ No newline at end of file From e4eb3e33046b727bf79966947d9cda42b06f0432 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Sun, 3 Dec 2023 22:52:23 +0000 Subject: [PATCH 36/44] minor bug fixes --- App/controllers/program.py | 20 ++++++++-------- App/controllers/programCourses.py | 4 ++-- App/models/program.py | 2 +- wsgi.py | 38 ++++++++++++++++++++++--------- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/App/controllers/program.py b/App/controllers/program.py index fa639cfe8..bcf6ad23b 100644 --- a/App/controllers/program.py +++ b/App/controllers/program.py @@ -2,20 +2,20 @@ from App.database import db def create_program(name, core, elective, foun): - try: - program = Program.query.filter_by(name=name, core_credits=core, elective_credits=elective, foun_credits=foun).first() - if program is not None: - print("Program exits already") - return None - else: + program = Program.query.filter_by(name=name, core_credits=core, elective_credits=elective, foun_credits=foun).first() + if program is not None: + print("Program exits already") + return None + else: + try: newProgram = Program(name, core, elective, foun) db.session.add(newProgram) print("Program successfully created") db.session.commit() return newProgram - except Exception as e: - db.session.rollback() - print(f'Error occured when creating program: {e}') + except Exception as e: + db.session.rollback() + print(f'Error occured when creating program: {e}') def get_program_by_name(programName): return Program.query.filter_by(name=programName).first() @@ -67,5 +67,7 @@ def get_all_courses(programName): all = core_courses + elective_courses + foun_courses return all +def get_all_programs(): + return Program.query.all() diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index a311bedc7..68ce07d19 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -5,12 +5,12 @@ def create_programCourse(programName, code, num): try: program = get_program_by_name(programName) - if program: + if program is not None: course = get_course_by_courseCode(code) if course: proCourse = ProgramCourses.query.filter_by(program_id=program.id, code=code, courseType=num).first() if proCourse: - print("Course already added to program") + return "Course already added to program" else: proCourse = ProgramCourses(program.id, code, num) db.session.add(proCourse) diff --git a/App/models/program.py b/App/models/program.py index 322983bbe..fc5f651cc 100644 --- a/App/models/program.py +++ b/App/models/program.py @@ -1,7 +1,7 @@ from App.database import db class Program(db.Model): id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(50)) + name = db.Column(db.String(50), nullable=False, unique=True) core_credits = db.Column(db.Integer) elective_credits = db.Column(db.Integer) foun_credits = db.Column(db.Integer) diff --git a/wsgi.py b/wsgi.py index 96998d25e..d53b8254b 100644 --- a/wsgi.py +++ b/wsgi.py @@ -25,13 +25,14 @@ create_staff, get_program_by_name, get_all_programCourses, - # addCoursetoHistory, + addCoursetoHistory, getCompletedCourseCodes, # get_allCore, addCourseToPlan, get_student_by_id, # generator, - list_all_courses + list_all_courses, + get_all_programs ) test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] @@ -109,9 +110,7 @@ def list_user_command(format): else: print(get_all_users_json()) -app.cli.add_command(user_cli) # add the group to the cli - -@user_cli.command("getcourseoffering",help='testing remove courses offering feature') +@user_cli.command("getcourseoffering", help='testing get courses offerings by year and semester feature') @click.argument("year", type=str) @click.argument("sem", type=int) def get_course_offering(year, sem): @@ -120,6 +119,23 @@ def get_course_offering(year, sem): for offering in offerings: print(f'{offering.get_json()}') +@user_cli.command("getprograms", help='testing get all programs feature') +def get_programs(): + programs=get_all_programs() + if programs: + for program in programs: + print(f'{program.get_json()}') + +@user_cli.command("getprogramcourses", help='testing get courses for a program feature') +@click.argument("programname", type=str) +def get_program_courses(programname): + programCourses=get_all_programCourses(programname) + if programCourses: + for programCourse in programCourses: + print(f'{programCourse.get_json()}') + + +app.cli.add_command(user_cli) # add the group to the cli # ... (previous code remains the same) ''' @@ -195,12 +211,12 @@ def create_program_command(name,core,elective,foun): newprogram=create_program(name,core,elective,foun) print(f'{newprogram.get_json()}') -@staff_cli.command("addprogramcourse",help='testing add program feature') -@click.argument("name", type=str) -@click.argument("code", type=str) -@click.argument("num", type=int) -def add_program_requirements(name,code,num): - response=create_programCourse(name, code, num) +@staff_cli.command("addprogramcourse",help='testing add program course feature') +@click.argument("programname", type=str) +@click.argument("coursecode", type=str) +@click.argument("type", type=int) +def add_program_requirements(programname,coursecode,type): + response=create_programCourse(programname, coursecode, type) print(response) @staff_cli.command("addcourseoffering",help='testing add courses offering feature') From e3b490d147aee5c230bc6e91578f294f8c00e76d Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 22:52:49 +0000 Subject: [PATCH 37/44] current changes to easycourseplanner --- App/controllers/CoursePlanner.py | 13 ------------- App/controllers/programCourses.py | 8 ++++---- App/models/EasyCoursePlanner.py | 30 +++++++++++++++++++++++++----- App/models/coursesOfferedPerSem.py | 16 ---------------- testData/test.txt | 2 +- 5 files changed, 30 insertions(+), 39 deletions(-) delete mode 100644 App/controllers/CoursePlanner.py delete mode 100644 App/models/coursesOfferedPerSem.py diff --git a/App/controllers/CoursePlanner.py b/App/controllers/CoursePlanner.py deleted file mode 100644 index 153d66afc..000000000 --- a/App/controllers/CoursePlanner.py +++ /dev/null @@ -1,13 +0,0 @@ -from App.models import CoursePlan, Student -from App.database import db -from App.controllers import ( - get_student_by_id, - -) - -def createCoursePlan(student_id, Mode): #mode is easy, fastest or prioritise electives - student = get_student_by_id(student_id) - - - - diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 726434c6f..79ac9ed7f 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -29,9 +29,9 @@ def get_all_programCourses(programName): return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() -def get_all_programCourses(program_id): - program = get_program_by_id(program_id) - return ProgramCourses.query.filter(ProgramCourses.program_id == program_id).all() +# def get_all_programCourses(program_id): +# program = get_program_by_id(program_id) +# return ProgramCourses.query.filter(ProgramCourses.program_id == program_id).all() # new function to get core, elective or foun courses def getProgramCoursesByType(programName, type): @@ -70,7 +70,7 @@ def convertToList(programCourses): def getProgramCoursesByRating(programName, rating): courses = [] program = get_program_by_name(programName) - programCourses = ProgramCourses.query.all.filter_by(program_id=program.id).all() + programCourses = ProgramCourses.query.filter_by(program_id=program.id).all() for programCourse in programCourses: course = get_course_by_courseCode(programCourse.code) if course.rating == rating: diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 57bf141cf..430106069 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -4,7 +4,10 @@ from App.controllers import ( getAllAvailableCourseOptions, get_student_by_id, - get_all_programCourses + get_all_programCourses, + getCompletedCourses, + getProgramCoursesByRating, + getProgramCoursesByType #add as needed ) @@ -14,11 +17,28 @@ def planCourses(self, data: int) -> CoursePlan: # implement logic student = get_student_by_id(data) program = student.associated_program - program_courses = get_all_programCourses(program.id) - print (program.get_json()) + # program_courses = getProgramCoursesByRating(program.name, 5) + program_courses = get_all_programCourses(program.name) + core_courses = getProgramCoursesByType(program.name, 1) + courseHistory = getCompletedCourses(student.id) + completed_core_courses = [] + incomplete_core_courses = [] - for x in program_courses: - print(x.get_json()) + for pastCourse in courseHistory: + for core in core_courses: + if (core.code == pastCourse.code): + completed_core_courses.append(core) + else: + incomplete_core_courses.append(core) + + + + + + for x in completed_core_courses: + print( x.get_json()) + + diff --git a/App/models/coursesOfferedPerSem.py b/App/models/coursesOfferedPerSem.py deleted file mode 100644 index 59a919952..000000000 --- a/App/models/coursesOfferedPerSem.py +++ /dev/null @@ -1,16 +0,0 @@ -# from App.database import db - -# class CoursesOfferedPerSem(db.Model): -# id = db.Column(db.Integer, primary_key=True) -# code = db.Column(db.ForeignKey('course.courseCode')) - -# # associated_course = db.relationship('Course', back_populates='offered', overlaps="courses") - -# def __init__(self, courseCode): -# self.code = courseCode - -# def get_json(self): -# return{ -# 'ID:': self.id, -# 'Course Code:': self.code -# } diff --git a/testData/test.txt b/testData/test.txt index 427440bff..95611954d 100644 --- a/testData/test.txt +++ b/testData/test.txt @@ -1,4 +1,4 @@ -Computer Science Major +Testing COMP1600,1 COMP1601,1 COMP1602,1 From 63dad8f902dcb2bd5ac762e040868f3e51dd77b4 Mon Sep 17 00:00:00 2001 From: nicholasr74 Date: Sun, 3 Dec 2023 23:03:18 +0000 Subject: [PATCH 38/44] minor changes to easycourseplanner --- App/controllers/programCourses.py | 8 ++++---- App/models/EasyCoursePlanner.py | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 79ac9ed7f..7f7b3339b 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -37,10 +37,10 @@ def get_all_programCourses(programName): def getProgramCoursesByType(programName, type): program = get_program_by_name(programName) programCourses = ProgramCourses.query.filter_by(program_id=program.id, courseType=type).all() - courseCodes = [] - for programCourse in programCourses: - courseCodes.append(programCourse.code) - return courseCodes + # courseCodes = [] + # for programCourse in programCourses: + # courseCodes.append(programCourse.code) + return programCourses # repetitive # def get_allCore(programName): diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 430106069..d30303d0a 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -28,16 +28,16 @@ def planCourses(self, data: int) -> CoursePlan: for core in core_courses: if (core.code == pastCourse.code): completed_core_courses.append(core) - else: - incomplete_core_courses.append(core) - - - - - + + # for core in core_courses: + for x in completed_core_courses: print( x.get_json()) + print("Courses that need to be completed:") + + for i in incomplete_core_courses: + print(i.get_json()) From 008e6611248b96b1d893a706c8640032b389ecc7 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Mon, 4 Dec 2023 02:35:55 +0000 Subject: [PATCH 39/44] Co-authored-by: Nicholas Ramroop --- App/controllers/programCourses.py | 6 +- App/models/EasyCoursePlanner.py | 24 +++-- wsgi.py | 143 ++++++++++++++---------------- 3 files changed, 88 insertions(+), 85 deletions(-) diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index c08e742c4..81fe0231d 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -10,16 +10,16 @@ def create_programCourse(programName, code, num): if course: proCourse = ProgramCourses.query.filter_by(program_id=program.id, code=code, courseType=num).first() if proCourse: - return "Course already added to program" + print(f'Course already added to program') else: proCourse = ProgramCourses(program.id, code, num) db.session.add(proCourse) db.session.commit() return proCourse else: - return "Invalid course code" + print(f'Invalid course code') else: - return "Invalid program name" + print(f'Invalid program name') except Exception as e: db.session.rollback() print(f'Error occured when trying to add course to program: {e}') diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index d30303d0a..24459acf3 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -7,7 +7,8 @@ get_all_programCourses, getCompletedCourses, getProgramCoursesByRating, - getProgramCoursesByType + getProgramCoursesByType, + get_course_by_courseCode #add as needed ) @@ -23,21 +24,28 @@ def planCourses(self, data: int) -> CoursePlan: courseHistory = getCompletedCourses(student.id) completed_core_courses = [] incomplete_core_courses = [] + incomplete_count = 0 + complete_count = 0 + core_credits = 0 for pastCourse in courseHistory: for core in core_courses: if (core.code == pastCourse.code): completed_core_courses.append(core) + complete_count += 1 + core_credits += get_course_by_courseCode(core.code).credits + + for core in core_courses: + if core not in completed_core_courses: + incomplete_core_courses.append(core) + incomplete_count += 1 - # for core in core_courses: - - for x in completed_core_courses: - print( x.get_json()) - print("Courses that need to be completed:") - for i in incomplete_core_courses: - print(i.get_json()) + for course in incomplete_core_courses: + print(get_course_by_courseCode(course.code).get_json()) + + diff --git a/wsgi.py b/wsgi.py index a531eabcc..c07812247 100644 --- a/wsgi.py +++ b/wsgi.py @@ -31,18 +31,13 @@ get_all_programCourses, addCoursetoHistory, getCompletedCourseCodes, - # get_allCore, addCourseToPlan, get_student_by_id, - # generator, list_all_courses, - get_all_programs + get_all_programs, + getProgramCoursesByType ) -test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] - -file_path = "testData/test.txt" - # This commands file allow you to create convenient CLI commands for testing controllers @@ -57,15 +52,19 @@ def initialize(): db.create_all() create_user('bob', 'bobpass') createCoursesfromFile('testData/courseData.csv') - create_program("Testing", 69, 15, 9) + create_program("Testing", 30, 54, 9) create_student(816, "testpass", "test", "Testing") create_staff("staffpass","999", "staff") + + test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] for c in test1: grade = random.choice(['A', 'B', 'C', 'F']) addCoursetoHistory(816, c, grade) print('Student course history updated') + # add courses to program + file_path = "testData/test.txt" with open(file_path, 'r') as file: for i, line in enumerate(file): line = line.strip() @@ -74,16 +73,16 @@ def initialize(): else: course = line.split(',') create_programCourse(programName, course[0],int(course[1])) + print('Program courses updated') + # add course offerings for semester 1 of the year 2023/2024 file_path1='testData/test2.txt' with open(file_path1, 'r') as file: for i, line in enumerate(file): line = line.strip() - # addSemesterCourses(line) - - + createCourseOffering(line, "2023/2024", 1) + print('Course offerings created') - print('database intialized') ''' @@ -114,33 +113,8 @@ def list_user_command(format): else: print(get_all_users_json()) -@user_cli.command("getcourseoffering", help='testing get courses offerings by year and semester feature') -@click.argument("year", type=str) -@click.argument("sem", type=int) -def get_course_offering(year, sem): - offerings=getCourseOfferingsByYearAndSemester(year, sem) - if offerings: - for offering in offerings: - print(f'{offering.get_json()}') - -@user_cli.command("getprograms", help='testing get all programs feature') -def get_programs(): - programs=get_all_programs() - if programs: - for program in programs: - print(f'{program.get_json()}') - -@user_cli.command("getprogramcourses", help='testing get courses for a program feature') -@click.argument("programname", type=str) -def get_program_courses(programname): - programCourses=get_all_programCourses(programname) - if programCourses: - for programCourse in programCourses: - print(f'{programCourse.get_json()}') - app.cli.add_command(user_cli) # add the group to the cli -# ... (previous code remains the same) ''' Student @@ -175,7 +149,7 @@ def addCourse(ctx, student_id, code, grade): @student_cli.command("getCompleted", help="Get all of a student completed courses") @click.argument("student_id", type=str) def completed(student_id): - comp = getCompletedCourseCodes(student_id) + comp = getCompletedCourses(student_id) for c in comp: print(f'Course Code: {c.code}, Grade: {c.grade}') @@ -186,19 +160,25 @@ def completed(student_id): # addCourseToPlan(student, "COMP2611") -@student_cli.command("generate", help="Generates a course plan based on what they request") -@click.argument("student_id", type=str) -@click.argument("command", type=str) -def generatePlan(student_id, command): - student = get_student_by_id(student_id) - courses = generator(student, command) - for c in courses: - print(c) - -@student_cli.command("courseplan", help= "Get the current courseplan for a student") +# @student_cli.command("generate", help="Generates a course plan based on what they request") +# @click.argument("student_id", type=str) +# @click.argument("command", type=str) +# def generatePlan(student_id, command): +# student = get_student_by_id(student_id) +# courses = generator(student, command) +# for c in courses: +# print(c) + +@student_cli.command("getcourseplan", help= "Get the specified courseplan for the student") @click.argument("student_id", type=str) -def getcourseplan(student_id): - print(getCoursePlan(student_id)) +@click.argument("academic_year", type=str) +@click.argument("semester", type=str) +def getcourseplan(student_id, academic_year, semester): + plan = getCoursePlan(student_id, academic_year, semester) + if plan: + print(f'{plan.get_json()}') + else: + print(f'Course plan requested not found') app.cli.add_command(student_cli) @@ -207,12 +187,13 @@ def getcourseplan(student_id): Staff Commands ''' staff_cli = AppGroup('staff',help='testing staff commands') + @staff_cli.command("create",help="create staff") @click.argument("id", type=str) @click.argument("password", type=str) @click.argument("name", type=str) def create_staff_command(id, password, name): - newstaff=create_staff(password,id, name) + newstaff=create_staff(password, id, name) print(f'Staff {newstaff.name} created') @staff_cli.command("addprogram",help='testing add program feature') @@ -230,7 +211,8 @@ def create_program_command(name,core,elective,foun): @click.argument("type", type=int) def add_program_requirements(programname,coursecode,type): response=create_programCourse(programname, coursecode, type) - print(response) + if response is ProgramCourse: + print(f'{response.get_json()}') @staff_cli.command("addcourseoffering",help='testing add courses offering feature') @click.argument("code", type=str) @@ -239,7 +221,7 @@ def add_program_requirements(programname,coursecode,type): def add_course_offering(code, year, sem): offering=createCourseOffering(code, year, sem) if offering: - print(f'Course offering: {offering.get_json()}') + print(f'{offering.get_json()}') @staff_cli.command("removecourseoffering",help='testing remove courses offering feature') @click.argument("code", type=str) @@ -360,14 +342,20 @@ def courses_tests_command(type): def create_program_command(name, core, elective, foun): program = create_program(name, core, elective, foun) +@program.command("getprograms", help='Get all programs') +def get_programs(): + programs=get_all_programs() + if programs: + for program in programs: + print(f'{program.get_json()}') @program.command('core', help='Get program core courses') @click.argument('programname', type=str) def get_CoreCourses(programname): - create_programCourse("Computer Science Major", "COMP2611", 1) - create_programCourse("Computer Science Major", "COMP3605", 1) - create_programCourse("Computer Science Major", "COMP3610", 2) - core = get_allCore(programname) + # create_programCourse("Computer Science Major", "COMP2611", 1) + # create_programCourse("Computer Science Major", "COMP3605", 1) + # create_programCourse("Computer Science Major", "COMP3610", 2) + core = getProgramCoursesByType(programname, 1) for c in core: print({c.code}) @@ -394,7 +382,9 @@ def getProgram(programname): @click.argument('code', type=str) @click.argument('type', type=int) def addProgramCourse(programname, code, type): - create_programCourse(programname, code, type) + c = create_programCourse(programname, code, type) + if c: + print(f'Course:{c.code} Type:{c.courseType}') @program.command('getprogramCourses', help='Get all courses of a program') @click.argument('programname', type=str) @@ -409,8 +399,7 @@ def addProgramCourse(programname): ''' Course Commands ''' - -course = AppGroup('course', help = 'Program object commands') +course = AppGroup('course', help = 'Course object related commands') # @course.command('create', help='Create a new course') # @click.argument('file_path') @@ -432,15 +421,14 @@ def create_course_command(code): @click.argument('code', type=str) def get_course(code): course = get_course_by_courseCode(code) - course_json = course.get_json() - print(f'{course_json}') if course else print(f'error') + print(f'{course.get_json()}') if course else print(f'error') @course.command('getprereqs', help='Get all prerequistes for a course') @click.argument('code', type=str) -def get_course(code): +def get_course_prerequisites(code): prereqs = get_prerequisites(code) for r in prereqs: - print(f'{r.prereq_courseCode}') + print(f'{r.prereq_code}') # @course.command('nextsem', help='Add a course to offered courses') # @click.argument('code', type=str) @@ -448,17 +436,24 @@ def get_course(code): # course = addSemesterCourses(code) # print(f'Course Name: {course.courseName}') if course else print(f'error') -@course.command('getNextSemCourses', help='Get all the courses offered next semester') -def allSemCourses(): - courses = get_all_OfferedCodes() +# @course.command('getNextSemCourses', help='Get all the courses offered next semester') +# def allSemCourses(): +# courses = get_all_OfferedCodes() - if courses: - for c in courses: - print({c}) - else: - print("empty") +# if courses: +# for c in courses: +# print({c}) +# else: +# print("empty") - +@course.command("getcourseoffering", help='Get courses offerings for specified year and semester') +@click.argument("year", type=str) +@click.argument("sem", type=int) +def get_course_offering(year, sem): + offerings=getCourseOfferingsByYearAndSemester(year, sem) + if offerings: + for offering in offerings: + print(f'{offering.get_json()}') app.cli.add_command(course) @@ -469,7 +464,7 @@ def allSemCourses(): Course Plan Commands ''' -course_plan = AppGroup('course_plan', help = 'Program object commands') +course_plan = AppGroup('course_plan', help = 'Course plan object related commands') @course_plan.command('newPlan', help = 'create a new courseplan for a student') @click.argument('id', type=int) From 2aa8f9bb8741a53582fb386f05a808e25f065ddd Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:15:53 +0000 Subject: [PATCH 40/44] Co-authored-by: shanif --- .vscode/settings.json | 4 +- App/controllers/prerequistes.py | 15 +++++++ App/controllers/programCourses.py | 9 +++- App/models/EasyCoursePlanner.py | 75 ++++++++++++++++++++++++++----- App/models/FastCoursePlanner.py | 27 +++++++++-- testData/test.txt | 10 ++--- wsgi.py | 70 ++++++++++++++++++++++------- 7 files changed, 175 insertions(+), 35 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 86b58d041..619f65463 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "python.testing.unittestArgs": ["-v", "-s", "./App", "-p", "test_*.py"], "python.testing.pytestEnabled": false, - "python.testing.unittestEnabled": true + "python.testing.unittestEnabled": true, + "python.analysis.typeCheckingMode": "basic", + "python.analysis.autoImportCompletions": true } diff --git a/App/controllers/prerequistes.py b/App/controllers/prerequistes.py index 165f85c95..5661ff2c0 100644 --- a/App/controllers/prerequistes.py +++ b/App/controllers/prerequistes.py @@ -24,7 +24,22 @@ def create_prereq(course, prereqCode): print("There was an error...") print(e) +# check if a course is a prerequisite +def is_prerequisite(prereq_code): + prereq = Prerequisites.query.filter_by(prereq_code = prereq_code).first() + if prereq: + return True + else: + return False +#using a prerequisite, find courses that can be done as a result of having it +def get_prereq_course_options(prereq_code): + course_options = Prerequisites.query.filter_by(prereq_code = prereq_code).all() + for c in course_options: + codes = getPrereqCodes(c.course_code) + if len(codes) > 1: + course_options.remove(c) + return course_options def get_all_prerequisites(courseCode): return Prerequisites.query.filter_by(course_code = courseCode).all() diff --git a/App/controllers/programCourses.py b/App/controllers/programCourses.py index 81fe0231d..f63249f16 100644 --- a/App/controllers/programCourses.py +++ b/App/controllers/programCourses.py @@ -28,7 +28,10 @@ def get_all_programCourses(programName): program = get_program_by_name(programName) return ProgramCourses.query.filter(ProgramCourses.program_id == program.id).all() - +def get_program_course_by_code(code): + return ProgramCourses.query.filter_by(code = code).first() + + # def get_all_programCourses(program_id): # program = get_program_by_id(program_id) # return ProgramCourses.query.filter(ProgramCourses.program_id == program_id).all() @@ -79,6 +82,8 @@ def getProgramCoursesByRating(programName, rating): print("No courses found in the given program with the given rating") return courses if courses else [] + + # from previous code - not tested def programCourses_SortedbyRating(programid): program = get_program_by_id(programid) @@ -109,3 +114,5 @@ def programCourses_SortedbyHighestCredits(programid): highTolow.append(course.courseCode) return highTolow + + diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 24459acf3..c8284a572 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -8,7 +8,9 @@ getCompletedCourses, getProgramCoursesByRating, getProgramCoursesByType, - get_course_by_courseCode + get_course_by_courseCode, + get_program_course_by_code, + create_CoursePlan #add as needed ) @@ -21,34 +23,87 @@ def planCourses(self, data: int) -> CoursePlan: # program_courses = getProgramCoursesByRating(program.name, 5) program_courses = get_all_programCourses(program.name) core_courses = getProgramCoursesByType(program.name, 1) + elec_courses = getProgramCoursesByType(program.name, 2) + foun_courses = getProgramCoursesByType(program.name, 3) courseHistory = getCompletedCourses(student.id) completed_core_courses = [] incomplete_core_courses = [] - incomplete_count = 0 - complete_count = 0 + complete_electives = [] + complete_foun_courses = [] + core_credits = 0 + elec_credits = 0 + foun_credits = 0 for pastCourse in courseHistory: for core in core_courses: if (core.code == pastCourse.code): completed_core_courses.append(core) - complete_count += 1 core_credits += get_course_by_courseCode(core.code).credits + for elec in elec_courses: + if (elec.code == pastCourse.code): + complete_electives.append(elec) + elec_credits += get_course_by_courseCode(elec.code).credits + for foun in foun_courses: + if (foun.code == pastCourse.code): + complete_foun_courses.append(foun) + foun_credits += get_course_by_courseCode(foun.code).credits for core in core_courses: - if core not in completed_core_courses: + if (core not in completed_core_courses): incomplete_core_courses.append(core) - incomplete_count += 1 - + + + print(f'Program Core Credits: {program.core_credits}') + print(f'Program Elec Credits: {program.elective_credits}') + print(f'Program Foun Credits: {program.foun_credits}') + + print(f'Student Core Credits: {core_credits}') + print(f'Student Elec Credits: {elec_credits}') + print(f'Student Foun Credits: {foun_credits}') - for course in incomplete_core_courses: - print(get_course_by_courseCode(course.code).get_json()) + remaining_core_courses = (program.core_credits - core_credits)/3 + remaining_elec_courses = (program.elective_credits - elec_credits)/3 + remaining_foun_courses = (program.foun_credits- foun_credits)/3 + # print(int(remaining_core_courses)) + # print(int(remaining_elec_courses)) + # print(int(remaining_foun_courses)) - + #assuming the easiest courses get a higher rating, we take courses with ratings of 4 and 5 for the easy course plan + easy_core_courses = [] + easy_elec_courses = [] + easy_foun_courses = [] + + for i in range(5, 0, -1): + easy_program_courses = getProgramCoursesByRating(program.name, i) + + for course in easy_program_courses: + easy= get_program_course_by_code(course.courseCode) + if (easy.courseType == 1): + easy_core_courses.append(course) + if (easy.courseType == 2): + easy_elec_courses.append(course) + if (easy.courseType == 3): + easy_foun_courses.append(course) + + if (len(easy_core_courses)>= remaining_core_courses) and (len(easy_elec_courses)>=remaining_elec_courses) and (len(easy_foun_courses)>= remaining_foun_courses): + break + + # create_CoursePlan(student.id, ) + # for i in range(remaining_core_courses, 0, -1): + + + + # print(f'Easy Core Count: {len(easy_core_courses)}') + # print(f'Easy Elec Count: {len(easy_elec_courses)}') + # print(f'Easy Foun Count: {len(easy_foun_courses)}') + + # for i in easy_elec_courses: + # print(f'{i.courseCode} {i.rating}') diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index eb1c39546..95ff6d243 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -2,12 +2,33 @@ from App.models import CoursePlan, CoursePlannerStrategy from typing import List from App.controllers import ( - getAllAvailableCourseOptions + get_student_by_id, + get_program_by_id, + getPassedCourseCodes, + getProgramCoursesByType, + create_CoursePlan, + get_course_by_courseCode, + get_program_course_by_code #add as needed ) # Concrete Strategy: Fast class FastCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]) -> CoursePlan: - # implement logic - pass \ No newline at end of file + student_id = data[0] + current_year = data[1] + split_year = current_year.split("/") + next_year = split_year[1] + "/" + str(int(split_year[1])+1) + print(next_year) + student = get_student_by_id(student_id) + program = get_program_by_id(student.program_id) + program_core_courses = getProgramCoursesByType(program.name, 1) + program_elec_courses = getProgramCoursesByType(program.name, 2) + program_foun_courses = getProgramCoursesByType(program.name, 3) + passed_courses = getPassedCourseCodes(student_id) + program_course_plan = [] + + sem = 1 + # sem_course_plan = create_CoursePlan(student_id, current_year, sem) + + \ No newline at end of file diff --git a/testData/test.txt b/testData/test.txt index 95611954d..f67d7575d 100644 --- a/testData/test.txt +++ b/testData/test.txt @@ -6,20 +6,20 @@ COMP1603,1 COMP1604,1 INFO1600,1 INFO1601,1 -MATH1115,1 +MATH1115,2 COMP2601,1 COMP2602,1 COMP2603,1 COMP2604,1 -COMP2605,1 -COMP2606,1 +COMP2605,2 +COMP2606,2 COMP2611,1 COMP3601,1 COMP3602,1 COMP3603,1 INFO2602,1 -INFO2604,1 -INFO3604,1 +INFO2604,2 +INFO3604,2 MATH2250,1 COMP3605,2 COMP3606,2 diff --git a/wsgi.py b/wsgi.py index c07812247..fdde7d554 100644 --- a/wsgi.py +++ b/wsgi.py @@ -6,7 +6,10 @@ from App.models.EasyCoursePlanner import EasyCoursePlanner +from App.models.FastCoursePlanner import FastCoursePlanner +from App.models.ElectiveCoursePlanner import ElectiveCoursePlanner from App.models.CoursePlanner import CoursePlanner +from App.models.programCourses import ProgramCourses from App.database import db, get_migrate from App.main import create_app @@ -59,7 +62,7 @@ def initialize(): test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] for c in test1: - grade = random.choice(['A', 'B', 'C', 'F']) + grade = random.choice(['A', 'B', 'C', 'F1', 'F2', 'F3']) addCoursetoHistory(816, c, grade) print('Student course history updated') @@ -75,15 +78,28 @@ def initialize(): create_programCourse(programName, course[0],int(course[1])) print('Program courses updated') - # add course offerings for semester 1 of the year 2023/2024 - file_path1='testData/test2.txt' - with open(file_path1, 'r') as file: - for i, line in enumerate(file): - line = line.strip() - createCourseOffering(line, "2023/2024", 1) - print('Course offerings created') + # # add course offerings for semester 1 of the year 2023/2024 + # file_path1='testData/test2.txt' + # with open(file_path1, 'r') as file: + # for i, line in enumerate(file): + # line = line.strip() + # createCourseOffering(line, "2023/2024", 1) + - print('database intialized') + file_path = "testData/courseData.csv" + try: + with open(file_path, 'r') as file: + csv_reader = csv.DictReader(file) + for row in csv_reader: + courseCode = row["courseCode"] + semester = int(row["semster"]) + createCourseOffering(courseCode, "2023/2024", semester) + print('Course offerings for 2023/2024 created') + except FileNotFoundError: + print("File not found.") + except Exception as e: + print(f"An error occurred: {e}") + return False ''' User Commands @@ -446,14 +462,14 @@ def get_course_prerequisites(code): # else: # print("empty") -@course.command("getcourseoffering", help='Get courses offerings for specified year and semester') +@course.command("offering", help='Get courses offerings for specified year and semester') @click.argument("year", type=str) @click.argument("sem", type=int) def get_course_offering(year, sem): offerings=getCourseOfferingsByYearAndSemester(year, sem) if offerings: for offering in offerings: - print(f'{offering.get_json()}') + print(f'{offering.get_json()}') app.cli.add_command(course) @@ -509,16 +525,40 @@ def get_plan_courses(student_id): generate = AppGroup('generate', help = 'Generate a course plan based on strategy selected') -@generate.command("easy") +@generate.command('createplan', help = 'Generate a course plan based on strategy selected') +@click.argument('student_id', type=int) +@click.argument('strategy', type=str) +@click.argument('year', type=str) +def generate_plan(student_id, strategy, year): + if strategy.lower() == "easy": + strategy = EasyCoursePlanner() + params = [student_id] + elif strategy.lower() == "elective": + electives = input("Please enter the electives you wish to pursue (e.g. COMP3606, COMP3607): ") + strategy = ElectiveCoursePlanner() + params = [student_id, year, electives] + elif strategy.lower() == "fast": + strategy = FastCoursePlanner() + params = [student_id, year] + else: + print("Invalid planning strategy. Please choose 'easy', 'fast' or 'elective'.") + + context = CoursePlanner(strategy) + result = context.plan_courses(params) + + +@generate.command("easyplan") @click.argument('student_id', type = int) -def easyPlan(student_id): +def easyplantest(student_id): strategy = EasyCoursePlanner() context = CoursePlanner(strategy) + result = context.plan_courses(student_id) + + + - result = context.plan_courses(student_id) - app.cli.add_command(generate) \ No newline at end of file From d2563061caa2fac23961c1f00aba7dce1fb0841e Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Mon, 4 Dec 2023 19:05:36 +0000 Subject: [PATCH 41/44] fix problems --- App/controllers/coursePlan.py | 23 ++++---- App/controllers/studentCourseHistory.py | 4 +- App/models/CoursePlanner.py | 4 +- App/models/CoursePlannerStrategy.py | 2 +- App/models/EasyCoursePlanner.py | 5 +- App/models/ElectiveCoursePlanner.py | 2 +- App/models/FastCoursePlanner.py | 2 +- wsgi.py | 71 +++++++++++++++---------- 8 files changed, 65 insertions(+), 48 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index eda70e5bf..8116fc6ff 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -63,13 +63,13 @@ def possessPrereqs(studentId, courseCode): return True -def getPlanCourses(student_id): - plan = getCoursePlan(student_id) +def getPlanCourses(student_id, year, sem): + plan = getCoursePlan(student_id, year, sem) return get_all_courses_by_planid(plan.planId) -def addCourseToPlan(Student, courseCode): +def addCourseToPlan(studentId, courseCode, year, sem): course = get_course_by_courseCode(courseCode) if course: print("Course Found!") @@ -112,13 +112,13 @@ def getRemainingCoursesByType(student_id, type): required=getProgramCoursesByType(program.name, type) completed = getPassedCourseCodes(student_id) - if completed == []: - return required + if completed == []: + return required - remaining = required.copy() - for course in completed: - if course in required: - remaining.remove(course) + remaining = required.copy() + for course in completed: + if course in required: + remaining.remove(course) return remaining @@ -152,8 +152,9 @@ def getRemainingCreditsByCourseType(student_id, type): def getAllAvailableCourseOptions(student_id, year, sem): offerings = getCourseOfferingsByYearAndSemester(year, sem) offeringCourseCodes = [] - for offering in offerings: - offeringCourseCodes.append(offering.course_code) + if offerings: + for offering in offerings: + offeringCourseCodes.append(offering.course_code) student = get_student_by_id(student_id) program = get_program_by_id(student.program_id) diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index a88e99383..5c21a674c 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -59,7 +59,7 @@ def getPassedCourseCodes(id): passed = [] for course in completed: if course.grade != "F1" or course.grade != "F2" or course.grade != "F3": - passed.append(course.courseCode) + passed.append(course.code) return passed def getCompletedCourseCodes(id): @@ -67,6 +67,6 @@ def getCompletedCourseCodes(id): codes = [] for course in completed_courses: - codes.append(course.courseCode) + codes.append(course.code) return codes diff --git a/App/models/CoursePlanner.py b/App/models/CoursePlanner.py index 16ec96f34..3b147611d 100644 --- a/App/models/CoursePlanner.py +++ b/App/models/CoursePlanner.py @@ -10,6 +10,6 @@ def __init__(self, strategy: CoursePlannerStrategy): def set_strategy(self, strategy: CoursePlannerStrategy): self._strategy = strategy -#changed data : List[str] to int for studentID - def plan_courses(self, data: int) -> CoursePlan: + + def plan_courses(self, data: List[str]): return self._strategy.planCourses(data) \ No newline at end of file diff --git a/App/models/CoursePlannerStrategy.py b/App/models/CoursePlannerStrategy.py index 6de9b7a8f..9d112f61c 100644 --- a/App/models/CoursePlannerStrategy.py +++ b/App/models/CoursePlannerStrategy.py @@ -6,6 +6,6 @@ # Strategy Interface class CoursePlannerStrategy(ABC): @abstractmethod - def planCourses(self, data: int) -> CoursePlan: + def planCourses(self, data: List[str]): pass diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index c8284a572..8db8749b2 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -16,9 +16,10 @@ # Concrete Strategy: Easy class EasyCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: int) -> CoursePlan: + def planCourses(self, data: List[str]): # implement logic - student = get_student_by_id(data) + student_id = data[0] + student = get_student_by_id(student_id) program = student.associated_program # program_courses = getProgramCoursesByRating(program.name, 5) program_courses = get_all_programCourses(program.name) diff --git a/App/models/ElectiveCoursePlanner.py b/App/models/ElectiveCoursePlanner.py index 28b42e384..fa0d5dd90 100644 --- a/App/models/ElectiveCoursePlanner.py +++ b/App/models/ElectiveCoursePlanner.py @@ -8,6 +8,6 @@ # Concrete Strategy: Elective class ElectiveCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str]) -> CoursePlan: + def planCourses(self, data: List[str]): # implement logic pass \ No newline at end of file diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index 95ff6d243..da833344f 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -14,7 +14,7 @@ # Concrete Strategy: Fast class FastCoursePlanner(CoursePlannerStrategy): - def planCourses(self, data: List[str]) -> CoursePlan: + def planCourses(self, data: List[str]): student_id = data[0] current_year = data[1] split_year = current_year.split("/") diff --git a/wsgi.py b/wsgi.py index fdde7d554..0e6c7b566 100644 --- a/wsgi.py +++ b/wsgi.py @@ -33,12 +33,15 @@ get_program_by_name, get_all_programCourses, addCoursetoHistory, - getCompletedCourseCodes, + getCompletedCourses, addCourseToPlan, get_student_by_id, list_all_courses, get_all_programs, - getProgramCoursesByType + getProgramCoursesByType, + getCoursePlan, + getPlanCourses, + create_CoursePlan ) @@ -69,6 +72,7 @@ def initialize(): # add courses to program file_path = "testData/test.txt" with open(file_path, 'r') as file: + programName="" for i, line in enumerate(file): line = line.strip() if i ==0: @@ -212,14 +216,15 @@ def create_staff_command(id, password, name): newstaff=create_staff(password, id, name) print(f'Staff {newstaff.name} created') -@staff_cli.command("addprogram",help='testing add program feature') -@click.argument("name", type=str) -@click.argument("core", type=int) -@click.argument("elective", type=int) -@click.argument("foun", type=int) -def create_program_command(name,core,elective,foun): - newprogram=create_program(name,core,elective,foun) - print(f'{newprogram.get_json()}') +# @staff_cli.command("addprogram",help='testing add program feature') +# @click.argument("name", type=str) +# @click.argument("core", type=int) +# @click.argument("elective", type=int) +# @click.argument("foun", type=int) +# def create_program_command(name,core,elective,foun): +# newprogram=create_program(name,core,elective,foun) +# if newprogram: +# print(f'{newprogram.get_json()}') @staff_cli.command("addprogramcourse",help='testing add program course feature') @click.argument("programname", type=str) @@ -227,7 +232,7 @@ def create_program_command(name,core,elective,foun): @click.argument("type", type=int) def add_program_requirements(programname,coursecode,type): response=create_programCourse(programname, coursecode, type) - if response is ProgramCourse: + if response is ProgramCourses: print(f'{response.get_json()}') @staff_cli.command("addcourseoffering",help='testing add courses offering feature') @@ -278,7 +283,7 @@ def courses_tests_command(type): @test.command("coursePlan", help="Run Course Plan tests") @click.argument("type", default="all") -def courses_tests_command(type): +def course_plan_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/coursePlan.py::CoursePlanUnitTests"])) elif type == "int": @@ -289,7 +294,7 @@ def courses_tests_command(type): #CoursesOfferedPerSemUnitTests @test.command("coursesOffered", help="Run Courses Offered Per Sem tests") @click.argument("type", default="all") -def courses_tests_command(type): +def courses_offered_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/coursesOfferedPerSem.py::CoursesOfferedPerSemUnitTests"])) elif type == "int": @@ -300,7 +305,7 @@ def courses_tests_command(type): @test.command("program", help="Run Program tests") @click.argument("type", default="all") -def courses_tests_command(type): +def program_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) elif type == "int": @@ -311,7 +316,7 @@ def courses_tests_command(type): @test.command("staff", help="Run Staff tests") @click.argument("type", default="all") -def courses_tests_command(type): +def staff_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) elif type == "int": @@ -321,7 +326,7 @@ def courses_tests_command(type): @test.command("student", help="Run Program tests") @click.argument("type", default="all") -def courses_tests_command(type): +def student_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/student.py::StudentUnitTest"])) elif type == "int": @@ -331,7 +336,7 @@ def courses_tests_command(type): @test.command("studentCH", help="Run Student Course History tests") @click.argument("type", default="all") -def courses_tests_command(type): +def student_history_tests_command(type): if type == "unit": sys.exit(pytest.main(["App/tests/studentCourseHistory.py::CourseHistoryUnitTest"])) elif type == "int": @@ -356,7 +361,9 @@ def courses_tests_command(type): @click.argument('elective', type=int) @click.argument('foun', type=int) def create_program_command(name, core, elective, foun): - program = create_program(name, core, elective, foun) + newprogram=create_program(name,core,elective,foun) + if newprogram: + print(f'{newprogram.get_json()}') @program.command("getprograms", help='Get all programs') def get_programs(): @@ -404,7 +411,7 @@ def addProgramCourse(programname, code, type): @program.command('getprogramCourses', help='Get all courses of a program') @click.argument('programname', type=str) -def addProgramCourse(programname): +def getProgramCourses(programname): courses = get_all_programCourses(programname) for c in courses: print(f'{c.code} {c.courseType}') @@ -484,24 +491,29 @@ def get_course_offering(year, sem): @course_plan.command('newPlan', help = 'create a new courseplan for a student') @click.argument('id', type=int) -def new_course_plan(id): - create_CoursePlan(id) +@click.argument('year', type = str) +@click.argument('sem', type = int) +def new_course_plan(id, year, sem): + create_CoursePlan(id, year, sem) print("Course plan created!") @course_plan.command('getPlan', help = 'get a courseplan for a student') @click.argument('id', type=int) -def get_course_plan(id): - courseplan = getCoursePlan(id) +@click.argument('year', type = str) +@click.argument('sem', type = int) +def get_course_plan(id, year, sem): + courseplan = getCoursePlan(id, year, sem) print (courseplan.get_json()) @course_plan.command('AddCourse', help = 'add a new course for a student') @click.argument('id', type=int) @click.argument('courseCode', type = str) -def add_new_course(): - student = get_student_by_id("816") - plan = addCourseToPlan(student, "COMP2601") +@click.argument('year', type = str) +@click.argument('sem', type = int) +def add_new_course(id, courseCode, year, sem): + plan = addCourseToPlan(id, courseCode, year, sem) if (plan): print(plan.get_json()) else: @@ -509,8 +521,10 @@ def add_new_course(): @course_plan.command('getplancourses', help = "get a list of courses in the course plan") @click.argument('student_id', type = int) -def get_plan_courses(student_id): - plan_courses = getPlanCourses(student_id) +@click.argument('year', type = str) +@click.argument('sem', type = int) +def get_plan_courses(student_id, year, sem): + plan_courses = getPlanCourses(student_id, year, sem) for plan in plan_courses: print(plan.get_json()) # print(getPlanCourses(student_id)) @@ -542,6 +556,7 @@ def generate_plan(student_id, strategy, year): params = [student_id, year] else: print("Invalid planning strategy. Please choose 'easy', 'fast' or 'elective'.") + return context = CoursePlanner(strategy) result = context.plan_courses(params) From 38070aacbd561d4131e302fafa2414ce9c8a53b7 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Tue, 5 Dec 2023 01:15:28 +0000 Subject: [PATCH 42/44] Co-authored-by: Nicholas Ramroop --- App/controllers/coursePlan.py | 34 +++++-- App/controllers/studentCourseHistory.py | 2 +- App/models/EasyCoursePlanner.py | 82 ++++++++++++--- App/models/FastCoursePlanner.py | 129 ++++++++++++++++++++++-- wsgi.py | 12 ++- 5 files changed, 229 insertions(+), 30 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 8116fc6ff..46c9791e1 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -30,15 +30,15 @@ def create_CoursePlan(id, year, sem): plan = CoursePlan.query.filter_by(studentId=id, academic_year=year, semester=sem).first() if plan: print("Course plan exists already") - return None - else: + return plan + else: if CoursePlan.checkAcademicYearFormat(year): if sem == 1 or sem == 2 or sem == 3: plan = CoursePlan(id, year, sem) if plan: db.session.add(plan) db.session.commit() - print("Course offering created successfully") + print("New course plan created successfully") return plan else: print("The course plan could not be created") @@ -55,8 +55,16 @@ def getCoursePlan(studentid, year, sem): def possessPrereqs(studentId, courseCode): preqs = getPrereqCodes(courseCode) + # for i in preqs: + # print(f'PREREQ: {preqs}') + completed = getPassedCourseCodes(studentId) + + # for x in completed: + # print(f'COMPLETED: {x}') + for course in preqs: + # print(course) if course not in completed: return False @@ -67,17 +75,18 @@ def getPlanCourses(student_id, year, sem): plan = getCoursePlan(student_id, year, sem) return get_all_courses_by_planid(plan.planId) - +def numCoursesInPlan(plan_id): + courses = get_all_courses_by_planid(plan_id) + return len(courses) def addCourseToPlan(studentId, courseCode, year, sem): course = get_course_by_courseCode(courseCode) if course: - print("Course Found!") offered = isCourseOffered(courseCode) if offered: offering = isCourseOffering(courseCode, year, sem) if offering: - haveAllpreqs = possessPrereqs(studentId, course) + haveAllpreqs = possessPrereqs(studentId, course.courseCode) if haveAllpreqs: plan = getCoursePlan(studentId, year, sem) if plan: @@ -164,7 +173,7 @@ def getAllAvailableCourseOptions(student_id, year, sem): programCourseCodes.append(programCourse.code) passed = getPassedCourseCodes(student_id) - + available=[] for code in offeringCourseCodes: @@ -175,6 +184,17 @@ def getAllAvailableCourseOptions(student_id, year, sem): return available #returns an array of course codes +#same function as above but different parameters +def getCourseOptions(student_id, offeringCourseCodes, passed, programCourseCodes): + available=[] + + for code in offeringCourseCodes: + if code not in passed: + if code in programCourseCodes: + if possessPrereqs(student_id, code): + available.append(code) + + return available # previous code - seems unnecessary # def getTopfive(list): # return list[:5] diff --git a/App/controllers/studentCourseHistory.py b/App/controllers/studentCourseHistory.py index 5c21a674c..0ef795c6a 100644 --- a/App/controllers/studentCourseHistory.py +++ b/App/controllers/studentCourseHistory.py @@ -58,7 +58,7 @@ def getPassedCourseCodes(id): completed = getCompletedCourses(id) passed = [] for course in completed: - if course.grade != "F1" or course.grade != "F2" or course.grade != "F3": + if course.grade != "F1" and course.grade != "F2" and course.grade != "F3": passed.append(course.code) return passed diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index 8db8749b2..a3027c7f4 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -10,10 +10,14 @@ getProgramCoursesByType, get_course_by_courseCode, get_program_course_by_code, - create_CoursePlan + create_CoursePlan, + getCourseOfferingsByYearAndSemester, + addCourseToPlan, + getPlanCourses, + numCoursesInPlan #add as needed ) - + # Concrete Strategy: Easy class EasyCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]): @@ -64,16 +68,17 @@ def planCourses(self, data: List[str]): print(f'Student Foun Credits: {foun_credits}') - remaining_core_courses = (program.core_credits - core_credits)/3 - remaining_elec_courses = (program.elective_credits - elec_credits)/3 - remaining_foun_courses = (program.foun_credits- foun_credits)/3 + remaining_core_courses = int((program.core_credits - core_credits)/3) + remaining_elec_courses = int((program.elective_credits - elec_credits)/3) + remaining_foun_courses = int((program.foun_credits- foun_credits)/3) # print(int(remaining_core_courses)) # print(int(remaining_elec_courses)) # print(int(remaining_foun_courses)) - #assuming the easiest courses get a higher rating, we take courses with ratings of 4 and 5 for the easy course plan + #assuming the easiest courses get a higher rating, we take courses with ratings of 5 for the easy course plan + # if courses with a rating of 5, the next 'easiest' rating will be selected, and so on easy_core_courses = [] easy_elec_courses = [] easy_foun_courses = [] @@ -88,24 +93,75 @@ def planCourses(self, data: List[str]): easy_core_courses.append(course) if (easy.courseType == 2): easy_elec_courses.append(course) + # print(course.courseCode) if (easy.courseType == 3): easy_foun_courses.append(course) if (len(easy_core_courses)>= remaining_core_courses) and (len(easy_elec_courses)>=remaining_elec_courses) and (len(easy_foun_courses)>= remaining_foun_courses): break - # create_CoursePlan(student.id, ) - # for i in range(remaining_core_courses, 0, -1): + + counter = 0 + + # while(True): + + coursePlanList = [] + sem = 1 + year = "2023/2024" + + + + coursePlanList.append(create_CoursePlan(student.id, year, sem)) + offering = getCourseOfferingsByYearAndSemester(year,sem) + offered_courses = [] + + if offering: + for crs in offering: + offered_courses.append(get_course_by_courseCode(crs.course_code)) + + plan = coursePlanList[0] + + for i in range(remaining_core_courses, 0, -1): + if(numCoursesInPlan(plan.planId) >=5) or (core_credits >= program.core_credits): + break + popped = easy_core_courses.pop(0) + if(popped in offered_courses): + print("Adding core course") + core_credits += popped.credits + addCourseToPlan(student_id, popped.courseCode, year, sem) + + + + for i in range(remaining_elec_courses, 0, -1): + if(numCoursesInPlan(plan.planId) >=5): + break + popped = easy_elec_courses.pop(0) + + if(popped in offered_courses): + elec_credits += popped.credits + addCourseToPlan(student_id, popped.courseCode, year, sem) + + for i in range(remaining_foun_courses, 0, -1): + if(numCoursesInPlan(plan.planId) >=5): + break + popped = easy_foun_courses.pop(0) + + if(popped in offered_courses): + foun_credits = popped.credits + addCourseToPlan(student_id, popped.courseCode, year, sem) + - # print(f'Easy Core Count: {len(easy_core_courses)}') - # print(f'Easy Elec Count: {len(easy_elec_courses)}') - # print(f'Easy Foun Count: {len(easy_foun_courses)}') + print("\n\n") + print(f'Student Core Credits: {core_credits}') + print(f'Student Elec Credits: {elec_credits}') + print(f'Student Foun Credits: {foun_credits}') - # for i in easy_elec_courses: - # print(f'{i.courseCode} {i.rating}') + plancourses = getPlanCourses(student_id, "2023/2024", sem) + for i in plancourses: + print(f'{get_course_by_courseCode(i.code).courseCode} {get_course_by_courseCode(i.code).credits}') pass \ No newline at end of file diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index da833344f..a5f30c8e0 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -1,5 +1,5 @@ from App.database import db -from App.models import CoursePlan, CoursePlannerStrategy +from App.models import CoursePlan, CoursePlannerStrategy, Course from typing import List from App.controllers import ( get_student_by_id, @@ -7,28 +7,145 @@ getPassedCourseCodes, getProgramCoursesByType, create_CoursePlan, + getAllAvailableCourseOptions, + is_prerequisite, get_course_by_courseCode, - get_program_course_by_code + addCourseToPlan, + numCoursesInPlan, + get_program_course_by_code, + getCourseOfferingsByYearAndSemester, + get_all_programCourses, + possessPrereqs, + getCourseOptions #add as needed ) +from App.models.courses import Course # Concrete Strategy: Fast -class FastCoursePlanner(CoursePlannerStrategy): +class FastCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]): student_id = data[0] current_year = data[1] split_year = current_year.split("/") next_year = split_year[1] + "/" + str(int(split_year[1])+1) - print(next_year) student = get_student_by_id(student_id) program = get_program_by_id(student.program_id) program_core_courses = getProgramCoursesByType(program.name, 1) program_elec_courses = getProgramCoursesByType(program.name, 2) program_foun_courses = getProgramCoursesByType(program.name, 3) passed_courses = getPassedCourseCodes(student_id) + + programCourses = get_all_programCourses(program.name) + programCourseCodes = [] + for programCourse in programCourses: + programCourseCodes.append(programCourse.code) + + s1_offerings = getCourseOfferingsByYearAndSemester(current_year, 1) + s1_offeringCourseCodes = [] + if s1_offerings: + for offering in s1_offerings: + s1_offeringCourseCodes.append(offering.course_code) + + s2_offerings = getCourseOfferingsByYearAndSemester(current_year, 1) + s2_offeringCourseCodes = [] + if s2_offerings: + for offering in s2_offerings: + s2_offeringCourseCodes.append(offering.course_code) + + program_course_plan = [] + level_1_courses = [] + level_2_courses = [] + level_3_courses = [] + + + options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) + + y1s1_course_plan = create_CoursePlan(student_id, current_year, 1) + for course_code in options: + course = get_course_by_courseCode(course_code) + if course.level == 1 : + if numCoursesInPlan(y1s1_course_plan.planId) <= 5: + addCourseToPlan(student_id, course.courseCode, current_year, 1) + passed_courses.append(course_code) + else: + + print("adding this to make program happy") + options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) + + + + # for course_code in options: + # course = get_course_by_courseCode(course_code) + # if course.level == 1: + # print(course_code) + # level_1_courses.append(course) + # elif course.level == 2: + # level_2_courses.append(course) + # elif course.level == 3: + # level_3_courses.append(course) + + # if len(level_1_courses) != 0: + # + # for course in level_1_courses: + + # level_1_courses.remove(course) + # print(f'{course.courseCode} {current_year} {semester}') + # else: + # program_course_plan.append(y1s1_course_plan) + + # if len(level_1_courses) != 0: + # y1s1_course_plan = create_CoursePlan(student_id, current_year, semester) + # # for course in level_1_courses: + + + # if len(level_1_courses) != 0: + # split_year = current_year.split("/") + # current_year = split_year[1] + "/" + str(int(split_year[1])+1) + # y2s1_course_plan = create_CoursePlan(student_id, current_year, semester) + # for course in level_1_courses: + # if numCoursesInPlan(y2s1_course_plan.planId) <= 5: + # addCourseToPlan(student_id, course.courseCode, current_year, semester) + # level_1_courses.remove(course) + # print(f'{course.courseCode} {current_year} {semester}') + + # if len(level_1_courses) <= 5: + # for course in level_1_courses: + # course = get_course_by_courseCode(course.courseCode) + # if course.level == 1: + # addCourseToPlan(student_id, course.courseCode, current_year, semester) + # level_1_courses.remove(course) + # print(f'{course.courseCode} {current_year} {semester}') + + # # if() + + + # for course_code in options: + + # addCourseToPlan(student_id, course_code, current_year, semester) + # options.remove(course_code) + # elif is_prerequisite(course_code): + # addCourseToPlan(student_id, course_code, current_year, semester) + # options.remove(course_code) + # print(f'{course_code} {current_year} {semester}') + + # if num_courses > 5 and num_courses <= 10: + # split_year = current_year.split("/") + # current_year = split_year[1] + "/" + str(int(split_year[1])+1) + # addCourseToPlan(student_id, course_code, current_year, semester) + # options.remove(course_code) + # num_courses += 1 + # print(f'{course_code} {current_year} {semester}') + # elif num_courses > 5 and num_courses <= 10: + + # num_courses += 1 + # print(f'{course_code} {current_year} {semester}') + # for course_code + + + + + - sem = 1 - # sem_course_plan = create_CoursePlan(student_id, current_year, sem) \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 0e6c7b566..f6c9f3d47 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,3 +1,5 @@ + + import click, pytest, sys import random import csv @@ -60,12 +62,14 @@ def initialize(): createCoursesfromFile('testData/courseData.csv') create_program("Testing", 30, 54, 9) create_student(816, "testpass", "test", "Testing") + create_student(8160, "pass", "blank", "Testing") create_staff("staffpass","999", "staff") test1 = ["COMP1600", "COMP1601", "COMP1602", "COMP1603", "COMP1604", "MATH1115", "INFO1600", "INFO1601", "FOUN1101", "FOUN1105", "FOUN1301", "COMP3605", "COMP3606", "COMP3607", "COMP3608",] for c in test1: - grade = random.choice(['A', 'B', 'C', 'F1', 'F2', 'F3']) + # grade = random.choice(['A', 'B', 'C', 'F1', 'F2', 'F3']) + grade = 'A' addCoursetoHistory(816, c, grade) print('Student course history updated') @@ -105,6 +109,7 @@ def initialize(): print(f"An error occurred: {e}") return False + print('Database initialized') ''' User Commands ''' @@ -392,7 +397,8 @@ def get_CoreCredits(programname): @click.argument('programname', type=str) def allCourses(programname): all = get_all_courses(programname) - print(all) + for course in all: + print(course.code) @program.command('getprogram', help='Get a program by name') @click.argument('programname', type=str) @@ -495,7 +501,7 @@ def get_course_offering(year, sem): @click.argument('sem', type = int) def new_course_plan(id, year, sem): create_CoursePlan(id, year, sem) - print("Course plan created!") + # print("Course plan created!") @course_plan.command('getPlan', help = 'get a courseplan for a student') From 2f02e74f0e28cc60e369955cbccd556cf1737db1 Mon Sep 17 00:00:00 2001 From: Nicholas Ramroop <98179530+nicholasr74@users.noreply.github.com> Date: Tue, 5 Dec 2023 03:07:57 +0000 Subject: [PATCH 43/44] reafactored all major views --- App/controllers/courses.py | 2 +- App/models/EasyCoursePlanner.py | 2 +- App/models/courses.py | 2 +- App/views/courses.py | 26 +++---- App/views/staff.py | 128 ++++++++++++++++++++++++-------- App/views/student.py | 99 ++++++++++++++++++++---- wsgi.py | 12 +-- 7 files changed, 203 insertions(+), 68 deletions(-) diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 9c009be2b..a2961f93f 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -91,7 +91,7 @@ def get_all_OfferedCodes(): offeredcodes=[] for c in offered: - offeredcodes.append(c.code) + offeredcodes.append(c.courseCode) return offeredcodes diff --git a/App/models/EasyCoursePlanner.py b/App/models/EasyCoursePlanner.py index a3027c7f4..1246a3352 100644 --- a/App/models/EasyCoursePlanner.py +++ b/App/models/EasyCoursePlanner.py @@ -164,4 +164,4 @@ def planCourses(self, data: List[str]): for i in plancourses: print(f'{get_course_by_courseCode(i.code).courseCode} {get_course_by_courseCode(i.code).credits}') - pass \ No newline at end of file + return plancourses \ No newline at end of file diff --git a/App/models/courses.py b/App/models/courses.py index 14a509e32..279a3c3b9 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -42,5 +42,5 @@ def get_json(self): 'Level: ': self.level, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, - 'Prerequisites: ': "placeholder" + } \ No newline at end of file diff --git a/App/views/courses.py b/App/views/courses.py index 642fa828a..94dbc7350 100644 --- a/App/views/courses.py +++ b/App/views/courses.py @@ -21,19 +21,19 @@ def list_courses_json(): return jsonify(course_json) -@course_views.route('/course', methods = ['POST']) -def new_course(): - data = request.json - - course = create_course(data['code'], - data['name'], - data['credits'], - data['rating'], - data['semester'], - data['level'], - data['offered'], - data['prereqs']) - return "Successfully Created course!" +# @course_views.route('/course', methods = ['POST']) +# def new_course(): +# data = request.json + +# course = create_course(data['code'], +# data['name'], +# data['credits'], +# data['rating'], +# data['semester'], +# data['level'], +# data['offered'], +# data['prereqs']) +# return "Successfully Created course!" @course_views.route('/course/prereq', methods = ['POST']) def add_prereq(): diff --git a/App/views/staff.py b/App/views/staff.py index 19adf6d22..bbbbf6d05 100644 --- a/App/views/staff.py +++ b/App/views/staff.py @@ -3,6 +3,9 @@ from flask_login import current_user, login_required from App.models import Program, ProgramCourses + + + from.index import index_views from App.controllers import ( @@ -17,7 +20,12 @@ get_all_programCourses, verify_staff, createCourseOffering, - deleteCourseOffering + deleteCourseOffering, + getAllCourseOfferings, + getCourseOfferingsByYearAndSemester, + get_program_by_name, + list_all_courses, + create_course ) staff_views = Blueprint('staff_views', __name__, template_folder='../templates') @@ -29,8 +37,34 @@ def getOfferedCourses(): if not verify_staff(username): #verify that the user is staff return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - listing=get_all_OfferedCodes() - return jsonify({'message':'Success', 'offered_courses':listing}), 200 + # listing=get_all_OfferedCodes() + # listing = getAllCourseOfferings() + # offered_json = ([course.get_json() for course in listing]) + # return jsonify(offered_json), 200 + course_list = list_all_courses() + course_json = ([course.get_json() for course in course_list]) + + return jsonify(course_json) + + + + + +@staff_views.route('/staff/offeredCourses/yearsem', methods=['GET']) +@login_required +def getOfferedCoursesYearSem(): + data = request.json + year = data['year'] + sem = data['sem'] + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + # listing=get_all_OfferedCodes() + listing = getCourseOfferingsByYearAndSemester(year, sem) + offered_json = ([course.get_json() for course in listing]) + return jsonify(offered_json), 200 @@ -48,12 +82,13 @@ def addProgram(): if not verify_staff(username): #verify that the user is staff return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - #get all programs and check to see if it already exists - programs=Program.query.all() - programNames=[] - for p in programs: - programNames.append(p.name) - if name in programNames: + # get all programs and check to see if it already exists + programs=get_program_by_name(name) + # programNames=[] + # for p in programs: + # programNames.append(p.name) + # if name in programNames: + if programs: return jsonify({'message': 'Program already exists'}), 400 if not isinstance(core, int): @@ -110,30 +145,34 @@ def addProgramRequirements(): return jsonify({'message': response.get_json()}), 200 -@staff_views.route('/staff/addOfferedCourse', methods=['POST']) -@login_required -def addCourse(): - data=request.json - courseCode=data['code'] +# @staff_views.route('/staff/addOfferedCourse', methods=['POST']) +# @login_required +# def addCourse(): +# data=request.json +# courseCode=data['code'] - username=current_user.username - if not verify_staff(username): #verify that the user is staff - return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 +# username=current_user.username +# if not verify_staff(username): #verify that the user is staff +# return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 - offeredCourses=get_all_OfferedCodes() - courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format +# offeredCourses=get_all_OfferedCodes() +# courseCode=courseCode.replace(" ","").upper() #ensure consistent course code format - #check if course code is already in the list of offered courses - if courseCode in offeredCourses: - return jsonify({'message': f"{courseCode} already exists in the list of offered courses"}), 400 +# #check if course code is already in the list of offered courses +# if courseCode in offeredCourses: +# return jsonify({'message': f"{courseCode} already exists in the list of offered courses"}), 400 - course = addSemesterCourses(courseCode) - if course: - return jsonify(course.get_json()), 200 - else: - return jsonify({'message': "Course addition unsucessful"}), 400 - -@staff_views.route('/staff/addCourseOffering', methods=['POST']) +# course = addSemesterCourses(courseCode) +# if course: +# return jsonify(course.get_json()), 200 +# else: +# return jsonify({'message': "Course addition unsucessful"}), 400 + + + + + +@staff_views.route('/staff/addOfferedCourse', methods=['POST']) @login_required def addCourseOffering(): data=request.json @@ -150,7 +189,11 @@ def addCourseOffering(): return jsonify(offering.get_json()), 200 else: return jsonify({'message': "Course offering creation unsucessful"}), 400 - + + + + + @staff_views.route('/staff/removeCourseOffering', methods=['DELETE']) @login_required def removeCourseOffering(): @@ -168,4 +211,27 @@ def removeCourseOffering(): if deleted: return jsonify({'message:': "Course offering deletion succesful"}), 200 else: - return jsonify({'message': "Course offering deletion unsucessful"}), 404 \ No newline at end of file + return jsonify({'message': "Course offering deletion unsucessful"}), 404 + + + + +@staff_views.route('/staff/createcourse', methods=['POST']) +@login_required +def new_course(): + data = request.json + + username=current_user.username + if not verify_staff(username): #verify that the user is staff + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Staff credentials.'}), 401 + + + course = create_course(data['code'], + data['name'], + data['credits'], + data['rating'], + data['semester'], + data['level'], + data['offered'], + data['prereqs']) + return jsonify("Successfully Created course!") \ No newline at end of file diff --git a/App/views/student.py b/App/views/student.py index 6e711fb8a..67001733c 100644 --- a/App/views/student.py +++ b/App/views/student.py @@ -3,6 +3,13 @@ from flask_login import current_user, login_required from.index import index_views + +from App.models.EasyCoursePlanner import EasyCoursePlanner +from App.models.FastCoursePlanner import FastCoursePlanner +from App.models.ElectiveCoursePlanner import ElectiveCoursePlanner +from App.models.CoursePlanner import CoursePlanner +from App.models.programCourses import ProgramCourses + from App.controllers import ( create_user, jwt_authenticate, @@ -13,11 +20,13 @@ get_program_by_name, get_student_by_id, get_course_by_courseCode, - # addCoursetoHistory, + addCoursetoHistory, getCompletedCourseCodes, # generator, - addCourseToPlan, - verify_student + verify_student, + getCompletedCourses + ) student_views = Blueprint('student_views', __name__, template_folder='../templates') @@ -51,6 +60,7 @@ def create_student_route(): def add_course_to_student_route(): student_id = request.json['student_id'] course_code = request.json['course_code'] + grade = request.json['grade'] username=current_user.username if not verify_student(username): #verify that the user is logged in @@ -74,38 +84,97 @@ def add_course_to_student_route(): return jsonify({'Error': 'Course already completed'}), 400 # addCoursetoHistory(student_id, course_code) + addCoursetoHistory(student_id, course_code, grade) return jsonify({'Success!': f"Course {course_code} added to student {student_id}'s course history"}), 200 + +@student_views.route('/student/get_history', methods=['GET']) +@login_required +def get_student_course_history(): + username=current_user.username + if not verify_student(username): #verify that the user is logged in + return jsonify({'message': 'You are unauthorized to perform this action. Please login with Student credentials.'}), 401 + + student_id = request.json['student_id'] + completed = getCompletedCourses(student_id) + completed_json = ([course.get_json() for course in completed]) + # course_json = ([course.get_json() for course in course_list]) + + return jsonify(completed_json) + + + + + + + ##Add course plan @student_views.route('/student/create_student_plan', methods=['POST']) @login_required def create_student_plan_route(): student_id = request.json['student_id'] - command = request.json['command'] + strategy = request.json['command'] + year = request.json['year'] username=current_user.username if not verify_student(username): #verify that the student is logged in return jsonify({'message': 'You are unauthorized to perform this action. Please login with Student credentials.'}), 401 - student = get_student_by_id(student_id) +# def generate_plan(student_id, strategy, year): + if strategy.lower() == "easy": + strategy = EasyCoursePlanner() + params = [student_id] + elif strategy.lower() == "elective": + electives = input("Please enter the electives you wish to pursue (e.g. COMP3606, COMP3607): ") + strategy = ElectiveCoursePlanner() + params = [student_id, year, electives] + elif strategy.lower() == "fast": + strategy = FastCoursePlanner() + params = [student_id, year] + else: + print("Invalid planning strategy. Please choose 'easy', 'fast' or 'elective'.") + return + + context = CoursePlanner(strategy) + result = context.plan_courses(params) + + course_json = ([course.get_json() for course in result]) - if not student: - return jsonify({'Error': 'Student not found'}), 400 - valid_command = ["electives", "easy", "fastest"] - if command in valid_command: - courses = generator(student, command) - return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}), 200 - course = get_course_by_courseCode(command) - if course: - addCourseToPlan(student, command) - return jsonify({'Success!': f"Course {command} added to student {student_id} plan"}), 200 + + + + + + + + + + + + + + # student = get_student_by_id(student_id) + + # if not student: + # return jsonify({'Error': 'Student not found'}), 400 + + # valid_command = ["electives", "easy", "fastest"] + + # if command in valid_command: + # courses = generator(student, command) + # return jsonify({'Success!': f"{command} plan added to student {student_id} ", "courses" : courses}), 200 + + # course = get_course_by_courseCode(command) + # if course: + # addCourseToPlan(student, command) + # return jsonify({'Success!': f"Course {command} added to student {student_id} plan"}), 200 - return jsonify("Invalid command. Please enter 'electives', 'easy', 'fastest', or a valid course code."), 400 + # return jsonify("Invalid command. Please enter 'electives', 'easy', 'fastest', or a valid course code."), 400 diff --git a/wsgi.py b/wsgi.py index f6c9f3d47..0c76c398c 100644 --- a/wsgi.py +++ b/wsgi.py @@ -568,12 +568,12 @@ def generate_plan(student_id, strategy, year): result = context.plan_courses(params) -@generate.command("easyplan") -@click.argument('student_id', type = int) -def easyplantest(student_id): - strategy = EasyCoursePlanner() - context = CoursePlanner(strategy) - result = context.plan_courses(student_id) +# @generate.command("easyplan") +# @click.argument('student_id', type = int) +# def easyplantest(student_id): +# strategy = EasyCoursePlanner() +# context = CoursePlanner(strategy) +# result = context.plan_courses(student_id) From 21a5cc2932925ed7e514cdc26f693e706d361a02 Mon Sep 17 00:00:00 2001 From: shanif <97924668+salamandur@users.noreply.github.com> Date: Tue, 5 Dec 2023 03:21:21 +0000 Subject: [PATCH 44/44] fast semester course plan added --- App/controllers/coursePlan.py | 14 ++-- App/models/FastCoursePlanner.py | 142 ++++++++++++++++++++++++-------- wsgi.py | 5 +- 3 files changed, 116 insertions(+), 45 deletions(-) diff --git a/App/controllers/coursePlan.py b/App/controllers/coursePlan.py index 46c9791e1..767b39d51 100644 --- a/App/controllers/coursePlan.py +++ b/App/controllers/coursePlan.py @@ -186,15 +186,15 @@ def getAllAvailableCourseOptions(student_id, year, sem): #same function as above but different parameters def getCourseOptions(student_id, offeringCourseCodes, passed, programCourseCodes): - available=[] + available=[] - for code in offeringCourseCodes: - if code not in passed: - if code in programCourseCodes: - if possessPrereqs(student_id, code): - available.append(code) + for code in offeringCourseCodes: + if code not in passed: + if code in programCourseCodes: + if possessPrereqs(student_id, code): + available.append(code) - return available + return available # previous code - seems unnecessary # def getTopfive(list): # return list[:5] diff --git a/App/models/FastCoursePlanner.py b/App/models/FastCoursePlanner.py index a5f30c8e0..b34b41b0e 100644 --- a/App/models/FastCoursePlanner.py +++ b/App/models/FastCoursePlanner.py @@ -1,3 +1,4 @@ +from App.controllers.coursePlan import getPlanCourses from App.database import db from App.models import CoursePlan, CoursePlannerStrategy, Course from typing import List @@ -26,6 +27,7 @@ class FastCoursePlanner(CoursePlannerStrategy): def planCourses(self, data: List[str]): student_id = data[0] current_year = data[1] + semester = data[2] split_year = current_year.split("/") next_year = split_year[1] + "/" + str(int(split_year[1])+1) student = get_student_by_id(student_id) @@ -34,45 +36,115 @@ def planCourses(self, data: List[str]): program_elec_courses = getProgramCoursesByType(program.name, 2) program_foun_courses = getProgramCoursesByType(program.name, 3) passed_courses = getPassedCourseCodes(student_id) - - programCourses = get_all_programCourses(program.name) - programCourseCodes = [] - for programCourse in programCourses: - programCourseCodes.append(programCourse.code) - - s1_offerings = getCourseOfferingsByYearAndSemester(current_year, 1) - s1_offeringCourseCodes = [] - if s1_offerings: - for offering in s1_offerings: - s1_offeringCourseCodes.append(offering.course_code) + added = [] + course_plan = create_CoursePlan(student_id, current_year, semester) + options = getAllAvailableCourseOptions(student_id, current_year, semester) + if options: + altered = False + for course_code in options: + course = get_course_by_courseCode(course_code) + if numCoursesInPlan(course_plan.planId) < 5: + if course.level == 1 : + addCourseToPlan(student_id, course_code, current_year, semester) + added.append(course_code) + altered = True + # print(f'{course_code} {current_year} 1') + if altered == True: + for a in added: + options.remove(a) + altered = False + for course_code in options: + if numCoursesInPlan(course_plan.planId) < 5: + if is_prerequisite(course_code): + addCourseToPlan(student_id, course_code, current_year, semester) + added.append(course_code) + altered = True + # print(f'{course_code} {current_year} 1') + if altered == True: + for a in added: + options.remove(a) + for course_code in options: + if numCoursesInPlan(course_plan.planId) < 5: + if is_prerequisite(course_code): + addCourseToPlan(student_id, course_code, current_year, semester) + added.append(course_code) + # print(f'{course_code} {current_year} 1') + + codes=[] + plan_courses = getPlanCourses(student_id, current_year, semester) + if plan_courses: + print("Courses in plan:") + for pc in plan_courses: + codes.append(pc.code) + print(pc.code) + return codes + # programCourses = get_all_programCourses(program.name) + # programCourseCodes = [] + # for programCourse in programCourses: + # programCourseCodes.append(programCourse.code) + + # s1_offerings = getCourseOfferingsByYearAndSemester(current_year, semester) + # s1_offeringCourseCodes = [] + # if s1_offerings: + # for offering in s1_offerings: + # s1_offeringCourseCodes.append(offering.course_code) - s2_offerings = getCourseOfferingsByYearAndSemester(current_year, 1) - s2_offeringCourseCodes = [] - if s2_offerings: - for offering in s2_offerings: - s2_offeringCourseCodes.append(offering.course_code) + # s2_offerings = getCourseOfferingsByYearAndSemester(current_year, semester) + # s2_offeringCourseCodes = [] + # if s2_offerings: + # for offering in s2_offerings: + # s2_offeringCourseCodes.append(offering.course_code) - program_course_plan = [] - level_1_courses = [] - level_2_courses = [] - level_3_courses = [] + # program_course_plan = [] + # level_1_courses = [] + # level_2_courses = [] + # level_3_courses = [] - options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) + # options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) + # if options: + # for o in options: + # print(o) + # y1s1_course_plan = create_CoursePlan(student_id, current_year, 1) + # for course_code in options: + # course = get_course_by_courseCode(course_code) + # if course.level == 1 : + # if numCoursesInPlan(y1s1_course_plan.planId) <= 5: + # addCourseToPlan(student_id, course.courseCode, current_year, 1) + # passed_courses.append(course_code) + # print(f'{course.courseCode} {current_year} 1') + # else: + # program_course_plan.append(y1s1_course_plan) + # print("y1s1 full") + # options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) - y1s1_course_plan = create_CoursePlan(student_id, current_year, 1) - for course_code in options: - course = get_course_by_courseCode(course_code) - if course.level == 1 : - if numCoursesInPlan(y1s1_course_plan.planId) <= 5: - addCourseToPlan(student_id, course.courseCode, current_year, 1) - passed_courses.append(course_code) - else: - - print("adding this to make program happy") - options = getCourseOptions(student_id, passed_courses, s1_offeringCourseCodes, programCourseCodes) - + # if len(program_course_plan) == 1: + # split_year = current_year.split("/") + # current_year = split_year[1] + "/" + str(int(split_year[1])+1) + # y2s1_course_plan = create_CoursePlan(student_id, current_year, 1) + # for course_code in options: + # course = get_course_by_courseCode(course_code) + # if course.level == 1 : + # if numCoursesInPlan(y2s1_course_plan.planId) <= 5: + # addCourseToPlan(student_id, course.courseCode, current_year, 1) + # passed_courses.append(course_code) + # print(f'{course.courseCode} {current_year} 1') + # else: + # program_course_plan.append(y2s1_course_plan) + # print("y2s1 full") + # else: + # for course_code in options: + # course = get_course_by_courseCode(course_code) + # if course.level == 1 : + # if numCoursesInPlan(y1s1_course_plan.planId) <= 5: + # addCourseToPlan(student_id, course.courseCode, current_year, 1) + # passed_courses.append(course_code) + # print(f'{course.courseCode} {current_year} 1') + # else: + # program_course_plan.append(y1s1_course_plan) + # print("y1s1 full") + # for course_code in options: @@ -100,9 +172,7 @@ def planCourses(self, data: List[str]): # if len(level_1_courses) != 0: - # split_year = current_year.split("/") - # current_year = split_year[1] + "/" + str(int(split_year[1])+1) - # y2s1_course_plan = create_CoursePlan(student_id, current_year, semester) + # # for course in level_1_courses: # if numCoursesInPlan(y2s1_course_plan.planId) <= 5: # addCourseToPlan(student_id, course.courseCode, current_year, semester) diff --git a/wsgi.py b/wsgi.py index f6c9f3d47..341dc66e4 100644 --- a/wsgi.py +++ b/wsgi.py @@ -549,7 +549,8 @@ def get_plan_courses(student_id, year, sem): @click.argument('student_id', type=int) @click.argument('strategy', type=str) @click.argument('year', type=str) -def generate_plan(student_id, strategy, year): +@click.argument('semester', type=int) +def generate_plan(student_id, strategy, year, semester): if strategy.lower() == "easy": strategy = EasyCoursePlanner() params = [student_id] @@ -559,7 +560,7 @@ def generate_plan(student_id, strategy, year): params = [student_id, year, electives] elif strategy.lower() == "fast": strategy = FastCoursePlanner() - params = [student_id, year] + params = [student_id, year, semester] else: print("Invalid planning strategy. Please choose 'easy', 'fast' or 'elective'.") return