Changelog
Check this section for updates to the assignment spec
- 2025-09-29: Initial release
- 2025-10-02: Fixed typo in
ClassSwapstruct definition ininclude/types.hpp(changedoldClassIdfromstd::stringtostd::optional<std::string>) - 2025-10-02: Specify that
getClassIds()andgetClassesAtTime()should return ids in lexicographical order - 2025-10-06: Adding the “transferring student unenrols from old class” description to Stage 4, as clarified on the forum.
- 2025-10-06: Clarified that classes cannot last longer than a week by updating the description of the
TimeSpanstruct ininclude/types.hpp.
Background
You have been tasked with creating a new system to support the management of classes at a university. The system should allow for the management of classes, students, and class enrolments. We also want to be able to identify schedule conflicts and available classes for students, as well as support waitlists for classes that are full.
Learning Outcomes
The purpose of this assignment is to consolidate the C++ concepts taught in weeks 1-4. The main learning outcomes are:
- Appreciate the effectiveness of classes in encapsulating behaviour.
- Understand the different types of constructors, how they are implemented, and used.
- Appreciate operator overloading, and understand how these functions are implemented and used.
- Differentiate between const and non-const methods, how they are implemented, and their significance.
- Appreciate STL data structures and algorithms and their appropriateness over for loops.
- Know how to write exceptions and appreciate their effectiveness in writing correct code.
- Know how to implement unit testing to write tests with good coverage that ensures code correctness.
Summary
contributes 20% of your final mark
Due DateWeek 7 Monday, 10:00am
Late Penalty5% per day, submissions later than 5 days not accepted without approved special consideration
Prerequisite Knowledge
- C++ classes, structs and enums
std::string,std::vector,std::pair- Exceptions
- Operator overloading (Stage 2 onwards)
- Move and copy constructors (Stage 2 onwards)
- C++ STL (Stage 2 onwards)
- Lambda functions (Stage 4)
Setting up…
Ensure you have followed the VSCode/C++ and git guides on EdStem to set up your environment.
To check that your environment is set up correctly, you should be able to run the following commands in the terminal:
cmake --version # should be 3.28 or higher
make --version
g++ --version
git --version
Getting Started
Retrieving the starter code
To get the assignment starter code, use the GitHub classroom link on Moodle to gain access to your assignment repository and clone the repo locally. (You can use the git clone command in the terminal).
If you have any questions/issues, ask your lab demonstrator.
Examining the starter code
Have a look at the following files in the starter code:
| File | Description |
|---|---|
include/timetable_manager.hpp | Header file for the TimetableManager class. You will need to submit this file. |
src/timetable_manager.cpp | Implementation file for the TimetableManager class. You will need to submit this file. |
src/main.cpp | A main file that you can modify to manually test your code. You won’t need to submit this file. |
test/timetable_manager_test.cpp | A test file that contains unit tests for the TimetableManager class. You are strongly encouraged to add additional tests to check the correctness of your code. You won’t need to submit this file. |
include/types.hpp | A header file containing type definitions. DO NOT MODIFY THIS FILE. You won’t need to submit this file. |
A deeper dive into the include/types.hpp file
The include/types.hpp file contains the following type definitions:
- An enum class
Daythat represents the days of the week. The days are ordered from Monday to Sunday.
enum class Day {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
- A struct
Timethat represents a time of the week. The struct has three members:day,hourandminute. You may assume that thehourandminutevalues are always valid (i.e.houris between 0 and 23, andminuteis between 0 and 59).
struct Time {
Day day;
int hour; // 0 to 23
int minute; // 0 to 59
};
- A struct
TimeSpanthat represents a time span. The struct has two members:startandend, both of typeTime. The time range is inclusive of the start time and exclusive of the end time. The time span can span across days (e.g., from Friday 23:00 to Saturday 01:00) and can wrap around the week (e.g., from Sunday 22:00 to Monday 02:00). You may assume that no time-span lasts longer than a week.
struct TimeSpan { // a time span across [start, end)
Time start;
Time end;
};
- A struct
Classthat represents a class. The struct has four members:id,capacity,instructor, andtimeSpan. Theidis astd::stringthat uniquely identifies the class. Thecapacityis an integer that represents the maximum number of students that can enrol in the class. Theinstructoris astd::stringthat represents the instructor of the class. ThetimeSpanis aTimeSpanthat represents the time span of the class.
struct Class {
std::string id;
int capacity;
std::string instructor;
TimeSpan time;
};
- [STAGE 4 ONLY] A struct
ClassSwapthat represents when a student moves off a waitlist to become enrolled in a class. The struct has three members:studentId,oldClassId, andnewClassId. ThestudentIdis astd::stringthat uniquely identifies the student. TheoldClassIdis astd::optional<std::string>that represents the class the student was previously enrolled in (orstd::nulloptif this is not a transfer). ThenewClassIdis astd::stringthat represents the class the student is now enrolled in.
struct ClassSwap {
std::string studentId;
std::optional<std::string> oldClassId;
std::string newClassId;
};
Compiling, running and testing your code
Open up a terminal and use the cd command to change into your assignment directory.
You have been provided a script to compile your code: build.sh. You can run this script by typing the following into the terminal:
./build.sh
This script will compile your code and create two executable files in the build directory: PrimaryMain and TestSuite.
You can run the PrimaryMain executable to run your code in the src/main.cpp file:
./build/PrimaryMain
You can run the TestSuite executable to run the test suite in the test/timetable_manager_test.cpp file:
./build/TestSuite
You should see most of the tests fail (obviously, since we haven’t implemented anything yet!)
Task
The following section details the requirements for each method in the TimetableManager class that you must implement. The method type signature, description and an example usage in the style of a Catch2 test has been provided.
Stage 1
In this stage, we will implement functionality in the TimetableManager class to manage classes. We should be able to add / remove classes and get information about the classes in the timetable manager.
TimetableManager();A constructor for the TimetableManager class that initialises a timetable manager with no classes.
TimetableManager(const std::vector<Class>& classes);A constructor for the TimetableManager class that initialises a timetable manager with the classes in the vector classes.
Throws a std::invalid_argument exception if any classes in the vector have the same id.
~TimetableManager();A destructor for the TimetableManager class. You should ensure that any allocated memory is correctly freed.
void addClass(const Class& c);Adds a class c to the timetable manager.
If a class with the same id already exists, does not add the class and throws a std::invalid_argument exception.
void addClass(const std::string& id, int capacity, const std::string& instructor, Time startTime, Time endTime);Adds a class to the timetable manager, with id id, capacity capacity, instructor instructor, and a time spanning from startTime to endTime.
If a class with the same id already exists, does not add the class and throws a std::invalid_argument exception.
void removeClass(const std::string& id);Removes a class from the timetable manager with id id.
If no class with the given id exists, does not remove any classes and throws a std::invalid_argument exception.
void setClassCapacity(const std::string& id, int capacity);Sets the capacity of the class with id id to capacity.
Throws a std::invalid_argument exception if no class with the given id exists or if capacity is not a positive integer.
[STAGE 2] Throws a std::logic_error if the capacity is less than the number of students enrolled in the class.
void setClassInstructor(const std::string& id, const std::string& instructor);Sets the instructor of the class with id id to instructor.
Throws a std::invalid_argument exception if no class with the given id exists.
int getNumClasses() const;Returns the number of classes in the timetable manager.
int getClassCapacity(const std::string& id) const;Returns the capacity of the class with id id.
Throws a std::invalid_argument exception if no class with the given id exists.
std::string getClassInstructor(const std::string& id) const;Returns the instructor of the class with id id.
Throws a std::invalid_argument exception if no class with the given id exists.
std::vector<std::string> getClassIds() const;Returns a vector of all ids of classes in the timetable manager, sorted lexicographically.
std::string getEarliestClass() const;Returns the id of the class with the earliest start time of the day (i.e., ignoring the day of the week and only considering the time of day). If there are multiple classes with the same earliest start time, return the id of the class that comes first lexicographically.
Throws a std::logic_error exception if there are no classes in the timetable manager.
std::string getLatestClass() const;Returns the id of the class with the latest start time of the day (i.e., ignoring the day of the week and only considering the time of day). If there are multiple classes with the same latest start time, return the id of the class that comes first lexicographically.
Throws a std::logic_error exception if there are no classes in the timetable manager.
std::string getLongestClass() const;Returns the id of the class with the longest duration. If there are multiple classes with the same longest duration, return the id of the class that comes first lexicographically.
Throws a std::logic_error exception if there are no classes in the timetable manager.
std::vector<std::string> getClassesAtTime(Time time) const;Returns a vector of ids of all classes that are running at the given time time, sorted lexicographically.
void printClasses(std::ostream& os) const;Prints information about all classes in the timetable manager to the output stream os. The classes should be ordered lexicographically by id.
Each class should be printed on a new line in the format Class <id> has capacity <capacity> and is taught by <instructor>.
Stage 2
In this stage we will add functionality to enrol students in classes. We will identify students by their student id (a std::string).
void enrolStudent(const std::string& classId, const std::string& studentId);Enrols a student with id studentId in the class with id classId.
If the class with the given id does not exist, throws a std::invalid_argument exception. If the class is full (i.e. the number of students enrolled is equal to the capacity), does not enrol the student and throws a std::logic_error exception.
Does nothing if the student is already enrolled in the class.
void unenrolStudent(const std::string& classId, const std::string& studentId);Unenrols a student with id studentId from the class with id classId.
If the student with the given id is not enrolled in the class, or the classId is invalid, does not unenrol the student and throws a std::invalid_argument exception.
int getNumStudents() const;Returns the number of students enrolled in any class.
int getNumEnrollments(const std::string& classId) const;Returns the number of students enrolled in the class with id classId.
Throws a std::invalid_argument exception if the class with the given id does not exist.
std::vector<std::string> getEnrolledStudents(const std::string& classId) const;Returns a vector of student ids enrolled in the class with id classId. The ids should be returned in lexicographical order.
Throws a std::invalid_argument exception if the class with the given id does not exist.
std::vector<std::string> getEnrolledClasses(const std::string& studentId) const;Returns a vector of class ids that the student with id studentId is enrolled in. The ids should be returned in lexicographical order.
std::vector<std::string> getAllStudents() const;Returns a vector of all student ids enrolled in any class, ordered lexicographically.
std::vector<std::string> getAllStudents(const std::string& instructor) const;Returns a vector of all student ids enrolled in any class taught by the instructor instructor, ordered lexicographically.
TimetableManager& operator+=(const Class& c);Adds a class c to the timetable manager.
If a class with the same id already exists, does not add the class and throws a std::invalid_argument exception.
TimetableManager& operator-=(const std::string& id);Removes a class with id id from the timetable manager.
If no class with the given id exists, does not remove any classes and throws a std::invalid_argument exception.
TimetableManager& operator+=(const TimetableManager& other);Adds all classes and enrollments from the timetable manager other to the current timetable manager. Does NOT add classes (and enrollments to classes) with the same id.
TimetableManager operator+(const TimetableManager& other);Returns a new timetable manager that contains all classes and enrollments from the current timetable manager and the timetable manager other. If both timetable managers contain classes with the same id, the class from the current timetable manager should be included.
TimetableManager(const TimetableManager& other);A copy constructor for the TimetableManager class. Creates a new timetable manager that is a copy of the timetable manager other but with no enrollments.
TimetableManager(TimetableManager&& other);A move constructor for the TimetableManager class. Moves the contents of the timetable manager other to the new timetable manager.
TimetableManager& operator=(const TimetableManager& other);A copy assignment operator for the TimetableManager class. Creates a new timetable manager that is a copy of the timetable manager other but with no enrollments. If the current timetable manager already has classes, they should be cleared before copying the classes from other.
TimetableManager& operator=(TimetableManager&& other);A move assignment operator for the TimetableManager class. Moves the contents of the timetable manager other to the current timetable manager.
If the current timetable manager already has classes, they should be cleared before moving the classes from other.
Stage 3
In this stage, we will add more operators to the TimetableManager class to compare timetable managers and get information about schedule conflicts and available classes.
bool operator==(const TimetableManager& other) const;Returns true if the timetable manager is equal to the timetable manager other. Two timetable managers are equal if they contain the same classes and enrollments.
Classes are considered equal if they have the same id, capacity, instructor, and time range. Enrollments are considered equal if the same students are enrolled in the same classes.
bool operator!=(const TimetableManager& other) const;Returns true if the timetable manager is not equal to the timetable manager other.
Two timetable managers are not equal if they contain different classes or enrollments.
bool operator<(const TimetableManager& other) const;Returns true if the total duration of all classes in the timetable manager is strictly less than the total duration of all classes in the timetable manager other.
bool operator>(const TimetableManager& other) const;Returns true if the total duration of all classes in the timetable manager is strictly greater than the total duration of all classes in the timetable manager other.
std::vector<std::pair<std::string, std::string>> getScheduleConflicts(
const std::string& studentId) const;Returns a vector of pairs of class ids that the student with id studentId is enrolled in that have overlapping times. You can return the pairs in any order.
std::vector<std::string> getAvailableClasses(
const std::string& studentId) const;Returns a vector of class ids that the student with id studentId is not enrolled in and that do not have overlapping times with classes that the student is enrolled in.
std::vector<TimeSpan> getFreeTimes(
const std::set<std::string>& studentIds,
Time start, Time end) const;Returns a vector of time spans that are free for all students in the set studentIds between the times start and end. A time span is free if no students have classes that are running at that time. The time spans should be ordered by start time.
You may assume that start will be earlier (in the week) than end.
Stage 4 (Advanced Task)
In this stage, we will add functionality to allow students to waitlist for classes
and request a class swap, via the enrolOrWaitlistStudent and transferOrWaitlistStudent methods.
If a class is full, instead of throwing an error, the student is added to a ‘waitlist’ for the class. When a spot becomes available (e.g. another student unenrols or transfers out of the class), the next student on the waitlist should be automatically enrolled in the class.
You may additionally need to extend the functionality of previous methods to handle these new features.
The timetable manager should also notify a handler function whenever a student is moved from a waitlist
to an enrolled list.
The setClassSwapHandler method can be used to set a handler function that will
be called whenever a student is moved from a waitlist to an enrolled list. The
handler function should take a vector of ClassSwap objects as an argument.
The TimetableManager class should call this handler function whenever a student
is moved from a waitlist to an enrolled list.
An example of how this “callback pattern” can be used is shown here:
TimetableManager manager{};
// set the handler to a callback that prints class swaps to stdout (std::cout)
manager.setClassSwapHandler([](const std::vector<ClassSwap>& swaps) {
for (auto& s : swaps) {
std::cout << s.studentId << " has successfully enrolled in "
<< s.newClassId << "\n";
}
});
// add a class with capacity 1
manager.addClass("MTRN2500", 1, "John Doe",
{Day::Monday, 9, 0}, {Day::Monday, 10, 0});
// enrol a student
manager.enrolOrWaitlistStudent("MTRN2500", "z0000000");
// try to enrol another student (but class is full, so they get "waitlisted")
manager.enrolOrWaitlistStudent("MTRN2500", "z1111111");
// first student unenrols -> we expect the TimetableManager to call the handler
// with a vector {{"MTRN2500", std::nullopt, "z1111111"}} since z1111111 should
// be moved off the waitlist for MTRN2500
manager.unenrolStudent("MTRN2500", "z0000000"); // handler called
Output to stdout:
z1111111 has successfully enrolled in MTRN2500
void setClassSwapHandler(
std::function<void(const std::vector<ClassSwap>&)> handler);Sets a handler function that will be called whenever a student is moved from a waitlist to an enrolled list. The handler function should take a vector of ClassSwap objects as an argument.
void enrolOrWaitlistStudent(const std::string& classId,
const std::string& studentId);Enrols a student with id studentId in the class with id classId. If the class is full, the student should be added to a ‘waitlist’.
If the class with the given id does not exist, throws a std::invalid_argument exception.
void transferOrWaitlistStudent(const std::string& studentId,
const std::string& oldClassId,
const std::string& newClassId);Requests to transfer a student with id studentId from the class with id oldClassId to the class with id newClassId.
If the class with id newClassId is full, the student should be added to a ‘waitlist’ for that class. If the class is not full, the student should be moved from oldClassId to newClassId.
If the class with the given id (either oldClassId or newClassId) does not exist, throws a std::invalid_argument exception.
If the student is not enrolled in the class with id oldClassId, or is already enrolled in newClassId, does nothing.
Stage 4 Special Cases
Behvaiour for various complex cases regarding waitlists and transfers are listed here. If any cases are not covered, feel free to post on EdStem in the clarifications thread.
Transferring student unenrols from old class
If a student requests to transfer from class A to class B, and then unenrols from class A before the transfer is completed, if the student eventually gets a spot in class B, they should be enrolled in class B, with the oldClassId field of the ClassSwap object set to std::nullopt (i.e., they are not transferring from any class).
TimetableManager manager{};
manager.setClassSwapHandler([](const std::vector<ClassSwap>& swaps) {
// ...
});
// classes with capacity 1 each
manager.addClass("MTRN2500", 1, "John Doe", {Day::Monday, 9, 0}, {Day::Monday, 10, 0});
manager.addClass("MTRN3500", 1, "Jane Doe", {Day::Tuesday, 10, 0}, {Day::Tuesday, 11, 0});
// students are enrolled in MTRN2500 and MTRN3500, making both classes full
manager.enrolOrWaitlistStudent("MTRN2500", "z0000000");
manager.enrolOrWaitlistStudent("MTRN3500", "z1111111");
// student requests to transfer to MTRN3500
manager.transferOrWaitlistStudent("z0000000", "MTRN2500", "MTRN3500");
// student unenrols from MTRN2500 before the transfer is completed
manager.unenrolStudent("MTRN2500", "z0000000");
// student unenrols from MTRN3500, creating a spot
manager.unenrolStudent("MTRN3500", "z1111111"); // handler called with {{"z0000000", std::nullopt, "MTRN3500"}}
Resolving Waitlist Deadlocks
This case is quite difficult and is meant as a fun challenge for top students. It will be worth very few marks.
Suppose two students are enrolled in two full classes, and both students request to transfer to the other class. For example:
TimetableManager manager{};
// classes with capacity 1 each
manager.addClass("MTRN2500", 1, "John Doe", {Day::Monday, 9, 0}, {Day::Monday, 10, 0});
manager.addClass("MTRN3500", 1, "Jane Doe", {Day::Tuesday, 10, 0}, {Day::Tuesday, 11, 0});
// both students are enrolled in their respective classes
manager.enrolOrWaitlistStudent("MTRN2500", "z0000000");
manager.enrolOrWaitlistStudent("MTRN3500", "z1111111");
// both students request to transfer to the other class
manager.transferOrWaitlistStudent("z0000000", "MTRN2500", "MTRN3500");
manager.transferOrWaitlistStudent("z1111111", "MTRN3500", "MTRN2500");
In this case, the TimetableManager should resolve the deadlock by moving both students to the other class, effectively swapping them. The class swap handler function (if set) should be called appropriately as well.
REQUIRE(manager.getNumEnrollments("MTRN2500") == 1);
REQUIRE(manager.getNumEnrollments("MTRN3500") == 1);
// After the transfers, z0000000 should be in MTRN3500 and z1111111 should be in MTRN2500
REQUIRE(manager.getEnrolledStudents("MTRN2500") == std::vector<std::string>{"z1111111"});
REQUIRE(manager.getEnrolledStudents("MTRN3500") == std::vector<std::string>{"z0000000"});
This scenario could be extended to more than two students and classes, but the basic principle remains the same.
Any time it is possible to resolve a deadlock by swapping students between classes, the TimetableManager should do so. If there are multiple possible ways to resolve the deadlock, the TimetableManager can choose any of them.
Other Requirements
Using libraries
You may #include any standard C++ libraries that you require. You should not use any other libraries (note that you only submit the TimetableManager.cpp and TimetableManager.hpp files).
Move Semantics
After an object has been moved (using the move constructor) it must be invalidated. We define invalidation of the TimetableManager class as
containing no classes or enrollments. Once moved, the original object should
no longer be used and any other behaviour is undefined.
Throwing Exceptions
For several of the methods in the TimetableManager class, you will need to throw exceptions. When throwing exceptions, you should throw the appropriate exception type and include a meaningful error message. The autotests will check that you are throwing the correct exception type and will ignore the error message.
e.g. For the addClass method, you should throw a std::invalid_argument exception if a class with the same id already exists. This could be implemented as
throw std::invalid_argument("A class with the same id already exists");
Hard Coding
Hard coding will not be accepted for any of the functions. Any function that is found to be implemented via hard coding will receive a result of zero.
An example of hard coding would be:
// This code does not actually compute the longest class, it just returns a hard-coded value
// based on the number of classes (probably to pass as many tests as possible)
std::string TimetableManager::getLongestClass() const {
if (numClasses == 0) {
return "";
} else if (numClasses == 1) {
return "MTRN2500";
} else if (numClasses == 2) {
return "MTRN3500";
}
return "MTRN4500";
}
C++ Version
This assignment should be written with modern C++ principles (see the style guide). The starter code and environment supplied is running C++17. You should be writing all code that is supported by this version of C++.
Version Control
As part of this assignment, you will be required to use GitHub classroom. A repository has been established for all students and the starter code has been placed within this (it will NOT be released on Moodle). You will be expected to meaningfully use this version control platform as it is widely used in industry and provides a means of retrieving code in case of computer issues or getting old revisions of your work.
Testing
You have been provided with a testing suite that you can use to sanity-check your code. This is not exhaustive and you are strongly encouraged to write your own tests to ensure your code is correct. You can do this by adding to the given test suite.
The tests have been written using the Catch2 framework.
Your “correctness” marks for this assignment will be based on a combination of the provided tests and additional tests that we will run on your code.
Marking Criteria
The assignment will be marked out of 20 marks. The “correctness” of your assignment will be automatically marked based on the provided tests and additional tests that we will run on your code. The “style” of your code will be manually marked according to the style rubric below.
| Component | Weighting |
|---|---|
| Correctness - Stage 1 | 4 marks |
| Correctness - Stage 2 | 5 marks |
| Correctness - Stage 3 | 3 marks |
| Correctness - Stage 4 | 3 marks |
| Style | 5 marks |
Style Rubric
Please refer to the C++ Style Guide for the detailed style guide. Your code style will be manually marked according to the following criteria:
| Criteria | Marks | Description |
|---|---|---|
| function use | 0.8 | effective use of functions to avoid repeated code, no overly deep nesting |
| commenting | 0.8 | effective use of comments to describe purpose of code, helper functions have comments explaining the purpose of the function |
| naming style | 0.4 | consistent naming style (camelCase OR snake_case) |
| descriptive function + variable names | 0.4 | all function and variables names are descriptive and appropriate |
| passing by reference | 0.2 | non-primitive types are consistently passed by reference |
| move semantics | 0.4 | correct application of move semantics (see “Other Requirements > Move Semantics” section above) |
| class access specifiers and const correctness | 0.2 | effective use of public and private specifiers for abstraction, defining helper functions as const wherever possible |
| spacing | 0.8 | consistent spacing, no whitespace errors |
| C++ style | 0.4 | effective use of C++ features (e.g. std::array, new, delete, constexpr, const, static_cast, nullptr) |
| loops and algorithms | 0.6 | effective use of in-built C++ STL algorithms where appropriate and good loop choices |
| penalties (negative marks applied) | - | failing to avoid using using namespace, void*, #define |
In order to be eligible to receive full marks for style, you must make a reasonable attempt at Stage 1 and 2. If you only attempt Stage 1, your style mark will be capped at 3/5.
Submission
The assignment is due by 10:00am on Monday Week 7 (27 Oct 2025). It should be submitted via the submission box provided on Moodle under the “Assessments Hub” section. You will need to submit 2 files: timetable_manager.cpp and timetable_manager.hpp.
You must also ensure that you have pushed the final version of your assignment to GitHub.
Compiling code
You must ensure that your code will compile by adhering to the public interface specified in the assignment spec. Only the functions listed in the spec (above) will be called by the autotests. Please do not delete the function declarations or change the function signatures, as your code will not compile with the tests.
Submitting non-compiling code will lead to a 10% penalty.
Late Penalty
UNSW has a standard late submission penalty of: 5% per day, for all assessments where a penalty applies, capped at five days (120 hours) from the assessment deadline, after which a student cannot submit an assessment.
Plagiarism
If you are unclear about the definition of plagiarism, please refer to What is Plagiarism? | UNSW Current Students.
You could get zero marks for the assignment if you were found:
- Knowingly providing your work to anyone and it was subsequently submitted (by anyone), or
- Copying or submitting any other persons’ work, including code from previous students of this course (except general public open-source libraries/code). Please cite the source if you refer to open source code.
You will be notified and allowed to justify your case before such a penalty is applied.
AI Policy
You are only permitted to use AI to the level of “simple editing assistance” (defined here) for this assignment. You should NOT use AI to generate code for you. Using functionality that generates code can be grounds for academic misconduct.