共计 13389 个字符,预计需要花费 34 分钟才能阅读完成。
CSE 332 Lab 5: OOP Design
Due by Wednesday December 12th at 11:59 pm
Final grade percentage: 20 percent – 15 percent implementation, 5 percent Readme
Objective:
This lab is intended to extend your understanding and use of C++ object-oriented programming
techniques, and to give you more experience using common design patterns.
To complete this lab, you will be given some starter code in your repository. You should build
additional functionality from there, documenting your thought process for each implementation
decision you make in your Readme. The project we will be working on is a Calendar
Application(I know 330 already has a calendar project…sorry!), however the goal is to design
the software to be very extensible. For this lab, your documentation will be worth much more
than in previous labs. Make sure you think through your design decisions thoroughly and
document them thoroughly as well. The code I’ve provided is a very bare bones calendar, with
currently very little functionality. You will be adding functionality is this lab. Below is a brief
description of the provided code.
- The application makes use of the composite pattern. This allows objects to be stored in
tree-like structures, creating hierarchical structures of objects(a year has 12 months, a
month has __ days, etc.). The composite pattern also allows us to treat leaf
objects(objects that do not have any children) and composite objects(objects that may
contain children) identically, because all objects in the composite define the same
interface. The abstract base class“DisplayableComponent”defines the interface that all
calendar objects inherit from, including days, months, years, and the calendar itself. The
majority of the concrete classes that define the“DisplayableComponent”interface can be
found in calendarcomponents.h and calendarcomponents.cpp. - The application makes use of the builder pattern for managing the construction of a
Calendar. This allows the Calendar to remain unaware of how its internal state is
constructed, allowing different builders to be used to construct the calendar in varying
ways. The abstract base class“CalendarBuilder”declares the interface that a builder
must define. FullCalendarBuilder is a concrete class defining that interface.
FullCalendarBuilder works by constructing the entire calendar at once. - The CalendarInterface class is the client using a Calendar object. The code is designed
with separation of concerns in mind. CalendarInterface manages input/output from the
user(the user interface). The calendar object stores the data of our Calendar, and the
builder is responsible for managing the construction process of our calendar and adding
new components to it.declares and defines the interface presented by a calendar.
Currently, the CalendarInterface class is very simple. It displays the calendar and gives
the user a few options like zooming in or out on a particular object in the calendar and
that’s about it. Throughout the rest of this lab, you will be expanding on that functionality. - Designpatterns.cpp gives a main function that initializes a CalendarInterface object and
calls into it, allowing for user interaction. You should not write any significant code in this
file, although you may end up changing the string passed as an argument to the
CalendarInterface constructor.
For this lab, you may work individually or in a 2-person or 3-person group. If you choose to
work in a group, you work within a single repository, but in the ReadMe.txt file you then must:
(1) indicate who the members of the group are, and
(2) explain in some detail how you divided up the work (reasonably) evenly between you in
designing and implementing your lab solution – i.e., who did which parts, etc.
Assignment:
Part I – Resources and Guidelines: - The constructor, destructor, operator, accessor, and mutator method examples in the C++
classes lecture slides give an overview of the kind of class syntax and structure you may
need for this lab. - The examples on C++ subclassing and inheritance polymorphism in these slides also
may be useful for thinking about how to structure your classes. Reviewing chapters 12,
13, and 15 from [LLM] can certainly be helpful as well. - Reviewing chapter 1 from [GHJV] can be helpful in thinking about different ways to create
flexible, extensible code. Particularly, reviewing encapsulation, interface inheritance,
composition, and delegation may be useful. Chapters 2 – 5 should be very useful as
references when thinking about which design patterns may be applicable to problems you
may encounter in your work, and thinking about the benefits of one pattern over another. - Please review the CSE 332 Programming Guidelines, all of which may be relevant to this
lab. Please follow them as you implement your solution.
Part II – Required Functionality:
Your Readme.txt file for this lab should include the typical information:
● Group member names
● Any errors, warnings you ran into while working
● Test cases you ran to test the functionality of your Calendar
In the Readme.txt file you will also find a series of questions that should be answered as well.
Below is a list of functional requirements that should be added to your Calendar application. You
are required to implement all functionality in this list. Exactly how you choose to do that is up to
you, but I will make some suggestions as we go. There will be questions in the Readme.txt file
associated with each piece of added functionality, you must answer them thoughtfully.
NOTE: I have provided interfaces for particular classes. These are simply starting suggestions,
you may change these interfaces if needed. - Implement functionality for creating and adding Events to the Calendar. Here are
some requirements:
a. An Event has a name, and a date/time(of type struct tm), as well as anything
else it may inherit from base classes.
b. Event objects can only be added to Days (DisplayableDay objects). Events
should only be added to the day that the event occurs in.
c. Recurring and multi day events should be supported(recur every __ days, event
lasts for __ days). Each day an event falls on should contain a shared_ptr to a
unique Event object. You should not share the same event object between days.
d. Events may be created in future years as well (up to the number of years stored
in the calendar). Events may not be created in years prior to the current year.
e. A day may contain multiple events. Those events should be sorted by their start
time.
Things to think about and suggestions:
f. How can you determine what day an event occurs in?
g. What object or objects should be responsible for this? What objects contain the
necessary information to determine this?
h. Should an event inherit from any of the given classes?
Question 1 in the Readme pertains to the above functionality. - Make the Calendar interactive. Each time the Calendar is displayed, a set of options
should be given. The user should be prompted to choose an option, and that request
should be handled appropriately. A user should be given options pertaining to the
current object being displayed as well as a set of global options:
a. Global options(available each time the Calendar is displayed)
i. Create a new Event - Should be handled by prompting the user for information about the
Event, creating an event, and adding it to the calendar
ii. Search for an Event by name - Should display details of the event if found by updating the current
view of the Calendar to display the event
a. If multiple Events have the same name, a list of all Events
with the matching name should be displayed. The user can
then choose one to display. - If no event matches the name, a message should be printed to
alert the user. - For full credit, this should be done efficiently. What STL containers
can be useful here? There is no need to iterate through or search
the entire calendar.
iii. Jump to a specific date and select the granularity to view in the calendar - Ex: a user may specify August 10th, 2018 and“day”as the
granularity, the display should then update its current view to the
DisplayableDay object representing August 10th, 2018. If the user
specifies“month”as the granularity, the display should update its
current view to the DisplayableMonth object containing the
DisplayableDay object for August 10th in its component subtree. - If the date does not exist in the calendar, a useful message should
be printed to notify the user and the current view should be
displayed again.
iv. Save the Calendar to a file so that it may be restored later, make sure to
save/restore the calendar’s name as well - Could an iterator be useful for traversing the objects in the
Calendar in order? - Does the entire state of a Calendar need to be written to the file to
be able to fully restore it later?
v. Restore a Calendar from a file - This should overwrite the contents of the current Calendar
- Perhaps a new concrete Builder would work well here
vi. Change the Calendar’s current view by zooming in and out 1 level at a
time (zoom functions are already given).
b. Local options: local to the currently displayed object
i. If the object is an event, the user should be able to edit it, including
changing the date or deleting the event. This may cause the event to
have to be moved.
Question 2 in the Readme pertains to the above functionality. - Update the display: Currently, how the calendar is displayed is not very useful. Modify
what information is displayed about an object at run-time to create a more readable
output.
a. If the Calendar’s current view is the Calendar itself:
i. Display a list of years the calendar contains and their corresponding
indices in the Calendars vector of children. A user can use these indices
to zoom in on a particular year.
b. If the Calendar’s current view is a DisplayableYear object:
i. Display the current year
ii. For each month the Year contains: - Display the name of the month
- Output the first letter of each day of the week
- For each week, output the day of the month associated with each
day contained in the week. Each day should be aligned with the
first letter of its weekday that was output in step 2.
The output for a single month(let’s say February, and the 1st falls
on a Tuesday) should look like this:
February
S M T W T F S - 2 3 4 5
- 7 8 9 10 11 12
- 14 15 16 17 18 19
- 21 22 23 24 25 26
- 28
c. If a month is the top level object being displayed:
i. Display a line containing the name of each weekday, evenly spaced from
each other. Let each column be about 11 characters wide.
ii. For each week contained in the month: - Display a line containing the day of the month associated with
each day in the week, aligned properly with its associated
weekday printed in step i. - Display a line containing the name of the first Event contained in
each day of the week, once again columns should be spaced
evenly with the weekday names above. If an event name is longer
than the column width allows, truncate the event name. - Repeat with the second event in each day on a new line. If at any
point a Day does not contain anymore events, fill its column with
spaces. Continue this process until all events of each day are
printed - Output a blank line
The output for the first couple of weeks of the month should look like:
Sunday
6
Event 1
Event 2
Monday
7
Tuesday
1
Event 1
Event 2
8
Event 1
Wednesday
2
9
Thursday
3
10
Event 1
Friday
4
Event 1
11
Event 1
Saturday
5
Event 1
Event 2
Event 3
12
d. If a day is the top level object being displayed:
i. Print the name of the weekday and the days date on a single line
ii. Print the events contained in that day, 1 event per line. The event name
and time should be printed. The events should be printed in sorted order
based on their time.
iii. Output for a day may look something like (you can display the time
however you would like):
Monday 2/21/2018 - event 1
- event 2
- event 3
Updating the DisplayableComponent interface may be useful here. Particularly, you need to
modify how display() behaves for a component depending on its depth from the current view.
Design patterns that may help here: Strategy, State, Visitor, Chain of Responsibility
Part III: Implement 2 of the following options:
(Extra credit: 5 points – implement the 3rd)
In your Readme, document which piece of functionality you chose to implement. Document how
the chosen design pattern works, and how it is used to implement the specified functionality. - Implement functionality to merge one calendar into another. Each merged Calendar
should be given a unique name (chosen by the user when specifying which text file to
load and merge). The structure of the Calendar should not change in any way, only the
Events of the Calendar should be merged in. When displayed, an Event should specify
which calendar it is associated with. Any number of Calendars should be able to be
merged into 1. For instance, we may merge 3 calendars together with names C1, C2,
and C3. The output when a day is displayed may look something like:
Monday 2/21/2018 - C1::Event1
- C2::Event1
- C1:: Event2
- C3::Event1
When an event is displayed directly, the Calendar it belongs to should be listed as well.
For full credit you must use the Decorator design pattern. - Implement functionality to add a TODO list within a DisplayableDay object in the
Calendar. You should use the singleton pattern to ensure that each Day has only a
single TODO list. A TODO list contains some number of Tasks. Each Task has at a
minimum a name. When a Day is displayed directly, a user should be able to:
a. Add a TODO list to the day, if a TODO list does not already exist for that day
b. Zoom in on the TODO list if it exists
c. A TODO list should be displayed below the events for a given day and marked
“TODO list”when displayed
d. When a user is currently displaying a TODO list, the user should be able to:
i. Add tasks to the TODO list
ii. Mark tasks as complete
iii. Each task should be displayed and marked with either“TODO”or
“COMPLETE”
iv. A user does not need to be able to zoom in on a particular task
TODO list should not be displayed in any other view, only when a Day containing a TODO list is
being displayed directly or the TODO list itself is being displayed directly.
Design Patterns to consider: Singleton, Strategy, Decorator
For full credit, the singleton pattern must be used to ensure only a single TODO list exists for
each day. - Incremental builder: Currently the FullCalendarBuilder constructs the entire calendar at
once, which allocates a lot of objects and uses a lot of memory. In this part, you will
implement an incremental builder. The goal is to construct components of the calendar on
demand as they are needed. Your IncrementalCalendarBuilder class should inherit from
CalendarBuilder. Initially, only a Calendar object should be constructed along with the
current year, month, and day(the day, month, and year associated with the current date).
As the user zooms in/out or jumps to a particular date and granularity, components of the
calendar should be constructed and added to the calendar as needed by the builder. A
user should be able to zoom in to a child that does not exist yet, so you may need to
update the zoom functions accordingly.
GETTING STARTED:
Decide if you are working alone or in a team of 2 or 3. Decide on a team name. One member
of your team should accept the assignment link here and create a team for their group. Now,
the other members of the group should visit the assignment link, select the correct team
name, and accept the assignment. A repository will be created for your team that is pre
populated with the starter code for lab 5. You should create a VS solution within the repository
and add the provided code into the solution to get started.
SUBMISSION:
Complete the additional functionality as described. Document your work as typical in the
Readme.txt file associated with the project. Answer all additional question in the Readme.txt
file as well. Commit and push your final code to Github. There may be a demonstration
process soon after the due date. This will give you a chance to demonstrate the functionality
you implemented to a TA directly. Details on this to come.
WX:codehelp