Subsections of Spring & Summer 2021
Final Project
This page lists the milestone requirements for the Final Project in CC 410. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
This assignment allow students to exercise their programming skills by building a project of their own design. Ideally, the project will be something related to the student’s personal interests or area of study. All the requirements listed below are considered flexible and can be adapted to fit the individual project and student.
General Requirements
All projects must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- All projects must include automation for testing, style checking, and documentation generation.
- Java: Use Gradle with the
application
,jacoco
, andcheckstyle
plugins. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile and be executable.
- Java: It must compile and execute using Gradle.
- Python: It must execute using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
A complete final project should include the following features:
- Satisfy all general requirements listed above.
- Several object-oriented classes, separated across at least two packages.
- It is recommended, but not required, that applications follow the Model-View-Controller or MVC architecture.
- Some use of inheritance between classes.
- This could be done direct subclassing or the use of interfaces.
- A user interface.
- This could be a graphical user interface (GUI), the text console, or a web-based interface.
- The use of an external library or web API.
- Unit tests to adequately test that the code works properly.
- A high level of code coverage should be achieved.
- Some user interface code may be omitted from unit testing if it is impractical to test.
- Proper documentation comments in code.
- A complete UML Class Diagram.
- At least one cool feature not listed above.
As of January 2021, this list is subject to change as the course progresses, depending on how far into the content we get. - Russ
Time Requirements
Completing this project is estimated to require 25-50 hours depending on familiarity with the tools involved. Spread across the entire semester, this equates to roughly 1-3 hours of work each week.
Milestones
The final project in this course will consist of several different milestones. Each milestone will require students to schedule a short meeting with the instructor or GTA to review the project as it stands and get feedback. The milestones are meant to roughly correspond to content being covered in this class.
- Milestone 1 (Week 1) - Discuss possible project topics and class structures.
- Milestone 2 (Week 5) - Discuss classes and inheritance, review existing unit tests and documentation. Discuss possible user interfaces.
- Milestone 3 (Week 10) - Discuss user interfaces, review existing code against requirements. Discuss possible external libraries or APIs.
- Milestone 4 (Week 14) - Discuss use of external library or API, review existing code against requirements. Discuss final steps and presentation.
- Milestone 5 (Week 16) - Present project to class, submit final code for review.
Deliverables
- Create a Release Tag on GitHub - Your final submission to Canvas should include a release tag on GitHub to the final version of your project. Ensure that it meets the requirements listed above, including a full UML Class Diagram.
- Code Documentation - Your code should include full documentation comments that can be used to generate developer documentation. Optionally, you may choose to deploy that documentation to GitHub pages.
- README File (optional) - You are encouraged to create a
README
file that describes your project, including how to compile and run it. - User Documentation (optional) - You may also include some user documentation describing how to use the project from a user’s perspective. This may be included as part of your
README
file as well. - Presentation - Please include any presentation materials (slides, etc.) in your git repository and make sure they are uploaded to GitHub as part of your release tag.
Suggested Presentation Outline
- Introduction - Introduce yourself and the project
- Background - Give information on the project’s inspiration and any related work to be aware of
- Implementation - Discuss how the project was designed and developed (should be the bulk of the presentation)
- Evaluation - Briefly evaluate how well your project met the original goal and how it compares to similar projects, if applicable
- Future Work - Share ways you would improve this project if given the opportunity to continue working on it
- Conclusion - Summarize what you learned
- Demo - Open your application and show us how it works, and also open the source code and share interesting portions of it as well
Grading Rubric
This assignment will be graded following the concept of criterion grading, an approach that only assigns points for completing the full requirements. However, the requirements will be brief and straightforward, and will be treated as such. Projects that meet the requirements listed above will, at a minimum, earn a passing grade of 70%.
Projects that go above and beyond the requirements in various ways will be graded higher. In general, the goal of this project is to build a program that is interesting and engaging to the user, but also demonstrates the student’s ability to develop professional code. So, projects that are easy to use, interesting, demonstrate good design and coding standards, and fit well within the student’s defined interests are likely to earn additional points.
Throughout the semester, students will have a chance to work with an instructor or GTA to get feedback on the project while it is being developed. These meetings allow the student to get information about which requirements have been met and which ones have not, as well as general overview of the project from the reviewer.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Hello Real World
This page lists the milestone requirements for the Example 1 - Hello Real World project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
This assignment mimics the traditional “Hello World” project that most programmers learn as their first program, but done following professional coding standards and guidelines. In effect, this is how a professional coder would write “Hello World” as a project for work.
General Requirements
All projects must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- All projects must include automation for testing, style checking, and documentation generation.
- Java: Use Gradle with the
application
,jacoco
, andcheckstyle
plugins. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile and be executable.
- Java: It must compile and execute using Gradle.
- Python: It must execute using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This project should include the following features:
- A
HelloWorld
class that contains amain
method.- The
main
method should print “Hello World” if no command line arguments are received. - The
main
method should print “Hello {arg}” if a command line argument is received.
- The
- Unit tests that achieve 100% code coverage in the
HelloWorld
class, properly testing both with and without command-line arguments. - Documentation comments following the language’s documentation standards for each class, method, and any class attributes.
- Python: All
.py
files should also include a file docstring, including__init__.py
and__main__.py
files for packages.
- Python: All
- All variables and methods in the
HelloWorld
class must include explicit data types- Java: no changes are needed since Java already requires this.
- Python: add type hints to all methods and variables. Type hints in the
HelloWorld
class must not useAny
as a type.
Time Requirements
Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
Grading Rubric
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%- Unit Tests - 30%
- Documentation - 20%
- Automation - 20%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
- Any portion of the project that does not pass a style check will have its grade reduced by 30% of the total points available on that portion.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Restaurant Classes
This page lists the milestone requirements for Milestone 1 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
This first milestone involves building the classes that represent items on the restaurant’s menu. In a traditional Model-View-Controller software design pattern, these classes would make up the core of the model. This content should be mostly review of concepts learned in prior CC courses with the addition of enumerations (enums). It should not be particularly difficult, but it may be repetitive and time consuming.
Specifically, we’ll focus primarily on data encapsulation by storing attributes about each menu item in the class. We’ll also learn how to combine state and behavior by modifying the string representation of the object based on the current state, or the combined values stored in the attributes.
In future milestones, we’ll focus on adding inheritance to simplify the code and structure in these classes. We’ll also add proper unit tests and documentation to these classes. For now, our only focus is on building the classes themselves.
General Requirements
The first couple of milestones only require a subset of the general requirements introduced in the “Hello Real World” project. Read this section carefully to see what is required for this particular milestone.
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries. You may include a main class in a separate package for testing purposes only.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
The following requirements ARE NOT enforced for this milestone, but will be enforced in later milestones that use the same code. We will focus on learning to meet each of these requirements in future modules. However, you are welcome to “plan ahead” by minimizing the number of style errors in your code and adding some basic documentation where desired.
You can make things easier on yourself by following proper naming standards for your language of choice, even though we aren’t enforcing a style guide for this milestone.
- Java - All names are in CamelCase. Classes start with uppercase, like
ClassName
, methods and attributes start with lowercase likemethodName
. See the Google Style Guide. - Python - All names are lowercase with underscores like
method_name
, with the exception of classes, which are named in CamelCase starting with an uppercase letter likeClassName
. See the Google Style Guide.
It is easier to get this correct from the start, then having to refactor your code later. Of course, major refactoring is also a good lesson that guarantees you’ll get it right in the future!
- (Milestone 3) All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- (Milestone 2) Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- (Milestone 2) Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
Assignment Requirements
This milestone should include the following features:
- Entrée classes - 7
- Declared in the
starfleetsubs.data.entrees
package
- Declared in the
- Side classes - 4
- Declared in the
starfleetsubs.data.sides
package
- Declared in the
- Drink classes - 5
- Declared in the
starfleetsubs.data.drinks
package
- Declared in the
- Enumeration classes - 3
- Declared in the
starfleetsubs.data.enums
package
- Declared in the
See the Starfleet Subs Menu section below for descriptions of what each class should contain.
Python - these files should include complete type annotations and achieve a low imprecision percentage in Mypy using strict type checking.
In my testing, the only imprecision in type checking should be the first line of the __eq__
method since it must accept an imprecise object
type until the isinstance()
method call. It will also mark the @property.setter
annotations, but they don’t count toward the imprecision total and can be ignored. The total imprecision should be less than 5% overall, and will probably be less than 2% in most cases. -Russ
Time Requirements
Completing this project is estimated to require 3-8 hours.
In my testing, this milestone requires around 1000-1500 lines of pure code without documentation, or around 2000-2500 lines including documentation comments that will be included as part of milestone 2. Much of the code can be carefully copy-pasted between files with similar attributes. My best suggestion is to do the enumerations first, then pick one of the complex entrées like TheRiker
and start there. Once you have the entrées all working, the sides and drinks are pretty easy and use much of the same structure. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Entrée classes - 30%
- Side classes - 30%
- Drink classes - 30%
- Enumeration classes - 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Starfleet Subs Menu
our motto: to boldly eat a sandwich where no sandwich has been eaten before
Each attribute described below should be implemented as a private variable within the class. Most attributes will also include a getter method, and sometimes a setter method, following this naming scheme (using Price as an example):
- Java - The private
price
attribute would have agetPrice
getter andsetPrice
setter method. - Python - The private
__price
attribute would have a getter and setter namedprice
implemented as a Python Property.
Entrées
Each entrée should be stored in an appropriately named class in the starfleetsubs.data.entrees
package. Each entrée should include an attribute for the following data:
- Bread - a
Bread
value (see below). It should have a getter and setter method. - Condiments - a Java HashSet or a Python set of
Condiment
values (see below).- This attribute should have a getter method that returns a shallow copy of the set to prevent external modification. See HashSet’s Copy Constructor (Java) or set.copy (Python).
- This attribute should also have methods for Add Condiment and Remove Condiment to modify the list of condiments.
In addition, each entrée should have the ability to return the following data through an appropriate getter method. The data may be stored as attributes or hard coded directly into the method.
- Price - a Java
double
or Pythonfloat
value. - Calories - an
int
value. It should have a getter method. - Special Instructions - a Java LinkedList of
String
values or a Python list ofstr
values.- If stored as an attribute, it should return a shallow copy of the list to prevent external modification. See LinkedList’s Copy Constructor (Java) or list.copy (Python).
Unfortunately, the Java clone()
methods can cause an unchecked cast exception when used on Java Collections classes with generics. See this StackOverflow question for a discussion of how to get around that using a copy constructor.
Each entrée class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the entrée. The string should be formatted as “{sandwich name} on {bread}”, such as “The Kirk on White Bread”.
It should also override the default equality method (equals()
in Java or __eq__()
in Python). Two items should be considered equal only if the values of all attributes are equal.
Each entrée description will include a list of ingredients included on the sandwich. Those ingredients should be represented using Boolean attributes that are set to true
by default, with appropriate getter and setter methods. Changing any of these to false
will cause a “Hold {ingredient}” message, such as “Hold Ham”, to be added to the Special Instructions list. Likewise, changing it back to true
will remove the appropriate message. If all ingredients are at their default values, the Special Instructions list should be empty.
Likewise, each entrée description will include a Price, number of Calories, a default value for Bread and a default set of Condiments. Those attributes should be populated appropriately in the constructor for the entrée. Changes to the Bread and Condiments attributes will not affect the Special Instructions attribute. Likewise, the Price and number of Calories will remain constant, regardless of other attributes.
The Kirk (Ham & Cheese)
just like the man himself, this sandwich “hams” it up and is super “cheesy”
starfleetsubs.data.entrees.TheKirk
- The price is $6.35 and it is 650 calories. Served on White Bread with Ham and Cheese. Comes with Lettuce, Tomato, and Mayo.
The Scotty (Ham, Turkey, Bacon & Cheese)
a heartier sandwich, with turkey and bacon to keep your ship in top shape
starfleetsubs.data.entrees.TheScotty
- The price is $7.65 and it is 800 calories. Served on Wheat Bread with Ham, Turkey, Bacon and Cheese. Comes with Lettuce, Tomato, Onion, Mustard and Mayo.
The Janeway (Italian)
a sandwich tasty enough for any “voyager” to enjoy
starfleetsubs.data.entrees.TheJaneway
- The price is $9.35 and it is 950 calories. Served on White Bread with Ham, Pepperoni, Salami and Cheese. Comes with Lettuce, Tomato, Onion, Pickles, Peppers, and Mayo.
The Q (BBQ)
the ultimate judgement of humanity, a “continuum” of meats
starfleetsubs.data.entrees.TheQ
- The price is $11.25 and it is 1375 calories. Served on White Bread with Brisket, Pulled Pork, Sausage, and Bacon. Comes with Onion, Pickles, and BBQ Sauce.
The Gagh (Meatball)
a Klingon delicacy to feed a true warrior’s hunger
starfleetsubs.data.entrees.TheGagh
- The price is $8.45 and it is 1020 calories. Served on Sourdough Bread with Meatballs, Marinara and Cheese. Comes with no condiments by default.
The Riker (Nearly Everything)
our “number one” sandwich
starfleetsubs.data.entrees.TheRiker
- The price is $17.01 and it is 1701 calories. Served on Wheat Bread with Ham, Turkey, Pepperoni, Salami, Brisket, Pulled Pork, Bacon and Cheese. Comes with Lettuce, Tomato, Onion, Pickles, Peppers, Olives, Mayo, Mustard, and BBQ Sauce
The Spock (Vegetarian)
a most logical choice
starfleetsubs.data.entrees.TheSpock
- The price is $5.50 and it is 700 calories. Served on Wheat Bread with Cheese. Comes with Lettuce, Tomato, Onion, Pickles, Peppers, Olives, and Mayo.
Sides
Each side should be stored in an appropriately named class in the starfleetsubs.data.sides
package. Each side should include an attribute for the following data:
- Size - a
Size
value (see below). It should have a getter and setter method.
In addition, each side should have the ability to return the following data through an appropriate getter method. The data may be stored as attributes or hard coded directly into the method.
- Price - a Java
double
or Pythonfloat
value. - Calories - an
int
value. It should have a getter method.
Each side class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the side. The string should be formatted as “{size} {side name}”, such as “Small Data Chips”.
It should also override the default equality method (equals()
in Java or __eq__()
in Python). Two items should be considered equal only if the values of all attributes are equal.
Each side description will include a Price and number of Calories for each Size. The sides will have a default size of Small
. Those attributes should be populated appropriately in the constructor for the side, and should be updated if the Size attribute changes.
Data Chips (Potato Chips)
crispy, crunchy potato chips seeking to understand human emotions
starfleetsubs.data.sides.DataChips
- Small: $1.75 and 250 calories. Medium: $2.25 and 350 calories. Large: $3.50 and 550 calories.
Enterprise (Cookie & 2 Pickles)
a round cookie and two gherkin “nacelles” in honor of the best ship in the fleet
starfleetsubs.data.sides.Enterprise
- Small: $1.98 and 170 calories. Medium: $3.77 and 340 calories. Large: $5.55 and 510 calories.
Borg (Pretzel Bites)
it is “futile” to “resist” these identical square pretzel bites wrapped in foil
starfleetsubs.data.sides.Borg
- Small: $2.55 and 375 calories. Medium: $4.15 and 565 calories. Large: $6.65 and 780 calories.
Bones McCoy (Chicken Wings)
these wings are the best “bones” in the galaxy
starfleetsubs.data.sides.BonesMcCoy
- Small: $3.75 and 545 calories. Medium: $5.45 and 785 calories. Large: $6.75 and 925 calories.
Drinks
Each drink should be stored in an appropriately named class in the starfleetsubs.data.drinks
package. Each drink should include an attribute for the following data:
- Size - a
Size
value (see below). It should have a getter and setter method.
In addition, each drink should have the ability to return the following data through an appropriate getter method. The data may be stored as attributes or hard coded directly into the method.
- Price - a Java
double
or Pythonfloat
value. - Calories - an
int
value. It should have a getter method. - Special Instructions - a Java LinkedList of
String
values or a Python list ofstr
values.- If stored as an attribute, it should return a shallow copy of the list to prevent external modification. See LinkedList’s Copy Constructor (Java) or list.copy (Python).
Each drink class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the drink. The string should be formatted as “{size} {drink name}”, such as “Small Picard”.
It should also override the default equality method (equals()
in Java or __eq__()
in Python). Two items should be considered equal only if the values of all attributes are equal.
Each drink description may include a list of ingredients it includes by default. Those ingredients should be represented using Boolean attributes that are set to true
by default, with appropriate getter and setter methods. Changing any of these to false
will cause a “Hold {ingredient}” message, such as “Hold Whipped Cream”, to be added to the Special Instructions list. Likewise, changing it back to true
will remove the appropriate message.
In addition, drinks may include optional ingredients that should be represented using Boolean attributes that are set to false
by default, with appropriate getter and setter methods. Changing any of these to true
will cause a “Add {ingredient}” message, such as “Add Ice”, to be added to the Special Instructions list. Likewise, changing it back to false
will remove the appropriate message. If all ingredients are at their default values, the Special Instructions list should be empty.
Each drink description will include a Price and number of Calories for each Size. The drinks will have a default size of Small
. Those attributes should be populated appropriately in the constructor for that class, and should be updated if the Size attribute changes. Changes to the Size attribute will not affect the Special Instructions attribute.
The Picard (Hot Tea)
tea, Earl Grey, hot
starfleetsubs.data.drinks.ThePicard
- Tea served with Lemon. Can optionally add Ice. Small: $0.95 and 5 calories. Medium: $1.65 and 10 calories. Large: $2.25 and 15 calories.
The Troi (Latte/Mocha)
the ultimate comfort drink inspired by a chocolate sundae
starfleetsubs.data.drinks.TheTroi
- Espresso served with Chocolate, Whipped Cream and a Cherry. Can optionally add Extra Espresso Shot. Small: $3.75 and 300 calories. Medium: $4.35 and 425 calories. Large: $5.25 and 600 calories.
The Worf (Prune Juice)
a warrior’s drink
starfleetsubs.data.drinks.TheWorf
- Prune Juice. Can optionally add Ice. Small: $1.25 and 150 calories. Medium: $1.75 and 225 calories. Large: $2.55 and 415 calories.
The Guinan (Lemonade)
a refreshing drink for a mysterious connoisseur
starfleetsubs.data.drinks.TheGuinan
- Lemonade served with Ice. Can optionally add Strawberry and/or Cherry. Small: $2.30 and 150 calories. Medium: $3.45 and 225 calories. Large: $4.65 and 395 calories.
Altair Water
the ultimate in hydration, direct from Altair IV
starfleetsubs.data.drinks.AltairWater
- Can optionally add Ice and/or Lemon. All sizes are $0.50 and 0 calories.
Enumerations
Each enumeration should be stored in an appropriately named class in the starfleetsubs.data.emnums
package. Each enumeration class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the item. Python developers may also wish to override the __repr__()
method to return this value as well.
Bread
an upper deck and a lower deck is important for any sub
starfleetsubs.data.enums.Bread
- White Bread, Wheat Bread, Sourdough Bread
Size
options to fit any appetite
starfleetsubs.data.enums.Size
- Small, Medium, Large
Condiments
don’t forget your KHAAAAAANNNNN!-diments
starfleetsubs.data.enums.Condiment
- Lettuce, Tomato, Onion, Pickles, Peppers, Olives, Mayo, Mustard, BBQ Sauce
Special thanks to Nathan, Stephen, Sarah, Kellie, Dan, Jack, Josh, Pascal, Beth, and Vince for inspiration and menu suggestions!
Documentation & Testing
This page lists the milestone requirements for Milestone 2 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The second milestone involves writing documentation and unit tests for our existing code base. Our goal is to adequately test each part of our code via unit tests, reaching 100% code coverage at a minimum. In addition, we’ll add all of the required documentation comments in our existing code.
General Requirements
The first couple of milestones only require a subset of the general requirements introduced in the “Hello Real World” project. Read this section carefully to see what is required for this particular milestone.
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries. You may include a main class in a separate package for testing purposes only.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check.
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
The following requirements ARE NOT enforced for this milestone, but will be enforced in later milestones that use the same code. We will focus on learning to meet each of these requirements in future modules. However, you are welcome to “plan ahead” by minimizing the number of style errors in your code and adding some basic documentation where desired.
You can make things easier on yourself by following proper naming standards for your language of choice, even though we aren’t enforcing a style guide for this milestone.
- Java - All names are in CamelCase. Classes start with uppercase, like
ClassName
, methods and attributes start with lowercase likemethodName
. See the Google Style Guide. - Python - All names are lowercase with underscores like
method_name
, with the exception of classes, which are named in CamelCase starting with an uppercase letter likeClassName
. See the Google Style Guide.
It is easier to get this correct from the start, then having to refactor your code later. Of course, major refactoring is also a good lesson that guarantees you’ll get it right in the future!
- (Milestone 3) All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
Assignment Requirements
This milestone should include the following features:
- Each Entrée, Side, and Drink class should contain complete typing information.
- Java - this is already handled by the compiler, so no changes are needed.
- Python - the code should contain complete type annotations and achieve low imprecision percentage in Mypy using strict type checking.
- Each Entrée, Side, and Drink class should have a corresponding class of unit tests that achieve 100% code coverage and adequately test all features of those classes.
- See the discussion below for more information on unit tests to be included.
- Each unit test should be in a matching package in the
test
directory for the class it is testing. - Python - unit tests do not require type annotations.
- Where possible, use parameterized unit tests to reduce the number of individual tests written.
- You may use any form of assertions, including the Hamcrest library.
- Each Entrée, Side, Drink, and Enumeration class should have all required documentation comments.
- Checkstyle/Flake8 should not give any errors related to documentation in the
src
directory. - You are encouraged, but not required, to create documentation comments for unit tests.
- You should be able to generate documentation using javadoc/pdoc3 as shown in the “Hello Real World” project.
- You will be graded on the content of the comments - make sure they are descriptive and succinct, with the appropriate sections/tags.
- Checkstyle/Flake8 should not give any errors related to documentation in the
- Create a UML Class Diagram representing the structure of this program.
- Store the UML diagram as an image file (PNG preferred).
- Place the image in the root of the project directory (directly inside the
java
orpython
folder). - Make sure it is committed to GitHub and included in your project release.
- You may include additional materials, such as the source file used to create the image.
Some quick tips from when I did this milestone:
- DO NOT COPY FROM YOUR SOURCE CODE FROM MILESTONE 1! Write your unit tests solely using the menu on the previous milestone and the list of tests needed on this milestone. In that way, you will confirm that your tests match the specification and confirm the code is correct, not that your tests match your existing code! Even I found a few errors in my code through writing these unit tests.
- You may wish to create global attributes in your unit test classes and then generalize your unit tests. For example, add a global
PRICE = 0.50
attribute, and then use that value in your unit test. In that way, when you copy and paste unit test code, you can simply change the global attributes to match the item being tested. Many tests can be generalized in that way such that all entrée test classes share the same code for many tests, referring to global attributes that are changed in each class. The same works for drinks and sides. - Generalizing the tests for individual ingredients in entrées and drinks (such as
ham
orlemon
) can be done using reflection or metaprogramming, but I don’t recommend it. Since each ingredient is an individual attribute, generalization is very complex and prone to errors. Those tests were hard-coded for each individual ingredient in my solution. - Java users may wish to review the EnumSource option for parameterized tests using enums.
- Python users can use enums directly in parameterized tests, as in
@pytest.mark.parametrize("bread", Bread)
. - When following Google’s style for Java, you are required to include
default
branches in switch statements across enums, which will be unreached in code coverage. This is fine, but a good reason to avoid switch statements, as you will never get 100% code coverage! I ended up changing my model solution to remove switch statements.
-Russ
Time Requirements
Completing this project is estimated to require 3-8 hours.
In my testing, this milestone requires around 3500-4000 lines of code (including very rudimentary documentation comments) in the unit tests directory. As with the prior milestone, much of the code can be carefully copy-pasted between files with similar attributes. My best suggestion is to pick one of the complex entrées like TheRiker
and start there writing unit tests. Once you have the entrées all working, the sides and drinks are pretty easy and use much of the same structure. There are 423 unit tests in my model solution. I ended up finding half a dozen errors in my model solution for milestone 1, showing the importance of unit testing! -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Unit Tests - 60%
- Entrée Classes - 30%
- Side Classes - 10%
- Drink Classes - 20%
- Documentation Comments - 30%
- Entrée Classes - 8%
- Side Classes - 8%
- Drink Classes - 8%
- Enumeration Classes - 6%
- UML Class Diagram - 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Unit Tests
Entrées
Each entrée test class should contain unit tests for the following:
SpecialInstructionsInitiallyEmpty()
- theSpecialInstructions
list should be empty when the object is createdHasCorrectBreadInitially()
- theBread
attribute is initially set correctlyHasCorrectPrice()
- theprice
is correctHasCorrectCalories()
- thecalories
is correctNameIsCorrectForBread(Bread)
- call thetoString()
or__str__()
method with each type of bread and verify the output.IncludesCorrectCondimentsByDefault(Condiment)
- for each condiment, check if it is included or not by default.- You may modify the arguments to accept a
boolean
value indicating if the condiment should be included by default.
- You may modify the arguments to accept a
AddRemoveCondiments(Condiment)
- for each condiment, check that it can be added and removed, and theCondiments
set will change accordingly.Has<Ingredient>ByDefault()
- for each ingredient, check to see that it is included by default (returns true).- For example,
TheKirk
would have a test methodHasHamByDefault()
.
- For example,
Change<Ingredient>SetsSpecialInstructions()
- for each ingredient, check that changing it from and to the default value will add and remove the correct item from theSpecialInstructions
list.- For example,
TheKirk
would haveChangeHamSetsSpecialInstructions()
that would confirm settingham
tofalse
would add"Hold Ham"
to the list ofSpecialInstructions
.
- For example,
ChangeMultipleIngredientSpecialInstructions()
- confirm that changing multiple ingredients from their default values will add multiple items to theSpecialInstructions
list.- This test may be omitted on items that only have one ingredient.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal usingequals()
(Java) or==
(Python).DifferentBreadNotEqual()
- generate two different instances of the item using different bread, and confirm that they are not equal usingequals()
(Java) or==
(Python).DifferentIngredientsNotEqual()
- generate two different instances of the item using different sets of ingredients, and confirm that they are not equal usingequals()
(Java) or==
(Python).DifferentCondimentsNotEqual()
- generate two different instances of the item using different sets of condiments, and confirm that they are not equal usingequals()
(Java) or==
(Python).WrongObjectNotEqual()
- generate an instance of the item and an instance of a different menu item, and confirm that they are not equal usingequals()
(Java) or--
(Python). This should not throw an exception.
Sides
Each side test class should contain unit tests for the following:
DefaultSizeCorrect()
- each side should have the default size ofSmall
when initially created.HasCorrectNameForSize(Size)
- call thetoString()
or__str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- theprice
is correct for each sizeHasCorrectCaloriesForSize(Size)
- thecalories
is correct for each sizeSameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal usingequals()
(Java) or==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal usingequals()
(Java) or==
(Python).WrongObjectNotEqual()
- generate an instance of the item and an instance of a different menu item, and confirm that they are not equal usingequals()
(Java) or--
(Python). This should not throw an exception.
Drinks
Each drink test class should contain unit tests for the following:
SpecialInstructionsInitiallyEmpty()
- theSpecialInstructions
list should be empty when the object is createdDefaultSizeCorrect()
- each drink should have the default size ofSmall
when initially created.HasCorrectNameForSize(Size)
- call thetoString()
or__str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- theprice
is correct for each sizeHasCorrectCaloriesForSize(Size)
- thecalories
is correct for each sizeHas<Ingredient>ByDefault()
- for each ingredient included by default, check to see that it is included (returns true). For example,ThePicard
would have a test methodHasLemonByDefault()
.DoesNotHave<Ingredient>ByDefault()
- for each optional ingredient not included by default, check to see that it is not included (returns false).- For example,
ThePicard
would have a test methodDoesNotHaveIceByDefault()
.
- For example,
Change<Ingredient>SetsSpecialInstructions()
- for each ingredient, check that changing it from and to the default value will add and remove the correct item from theSpecialInstructions
list.- For example,
ThePicard
would haveChangeIceSetsSpecialInstructions()
that would confirm settingice
totrue
would add"Add Ice"
to the list ofSpecialInstructions
.
- For example,
ChangeMultipleIngredientSpecialInstructions()
- confirm that changing multiple ingredients from their default values will add multiple items to theSpecialInstructions
list.- This test may be omitted on items that only have one ingredient.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal usingequals()
(Java) or==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal usingequals()
(Java) or==
(Python).DifferentIngredientsNotEqual()
- generate two different instances of the item using different sets of ingredients, and confirm that they are not equal usingequals()
(Java) or==
(Python).WrongObjectNotEqual()
- generate an instance of the item and an instance of a different menu item, and confirm that they are not equal usingequals()
(Java) or--
(Python). This should not throw an exception.
Extra Credit: After writing all of the unit tests listed above, feel free to suggest any unit tests you feel are missing. Email your added tests to the course help email address and you may earn bug bounty points for your suggestions!
Inheritance
This page lists the milestone requirements for Milestone 3 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The third milestone involves refactoring our code to take advantage of inheritance and the use of interfaces. We’ll also need to update our documentation and unit tests accordingly.
General Requirements
This project is the first that requires ALL general requirements introduced in the “Hello Real World” project. Read this section carefully to see what is required for this particular milestone.
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries. You may include a main class in a separate package for testing purposes only.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone should include the following features:
- A new
starfleetsubs.data.menu.OrderItem
interface that is implemented by all entrée, side, and drink classes- See below for the description of what this interface should contain
- New abstract base classes for each type of menu item:
- Entrées should inherit from
starfleetsubs.data.entrees.Entree
base class - Sides should inherit from the
starfleetsubs.data.sides.Side
base class - Drinks should inherit from the
starfleetsubs.data.drinks.Drink
base class
- Entrées should inherit from
- Each new base class should contain all elements that are shared by each type of menu item
- See below for the description of what the base classes should contain
- A new static class
starfleetsubs.data.menu.Menu
that contains the full menu- See below for the description of what this
Menu
class should contain
- See below for the description of what this
- Updated unit tests for each menu item to check for proper typing
- Each menu item should implement the
OrderItem
interface - Each menu item should inherit from the correct parent class
- Each class except
Menu
andOrderItem
should report near 100% code coverage.
- Each menu item should implement the
- Add a unit test class for
Menu
to confirm that each possible menu item is present in the menu. - Update the UML Class Diagram to represent the new structure of the code.
- Make sure all code is free from style errors using Checkstyle/Flake8.
Time Requirements
Completing this project is estimated to require 3-8 hours.
A rough estimate for this milestone would be around 1000 lines of new or updated code, and around 500 lines of redundant code removed. It could vary widely based on how you choose to implement the inheritance between the base classes and the interface. My model solution for this milestone now contains 526 unit tests in total. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
OrderItem
Interface - 25%- Base Classes - 30%
Entree
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%
Menu
Class - 20%- Updated Unit Tests - 10%
Menu
Unit Tests - 10%- UML Class Diagram - 5%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
New Classes
OrderItem Interface
The starfleetsubs.data.menu.OrderItem
class should be created as an interface that can be implemented by all other menu items. It should contain the following elements as abstract methods/properties:
- A getter for Price
- A getter for Calories
- A getter for Special Instructions
Each menu item (entrées, sides, and drinks) should be refactored to implement this interface. This will require some changes:
- Price and Calories is straightforward
- Special Instructions requires some modification
- Entrées - the Special Instructions list should now include each of the Condiments on the entrée. This could be done via the new
Entree
base class. - Sides - the Special Instructions getter will need to be added, and it should just return an empty list since sides do not have special instructions. This can be done via the new
Side
base class. - Drinks - no changes needed
- Entrées - the Special Instructions list should now include each of the Condiments on the entrée. This could be done via the new
Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Base Classes
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
starfleetsubs.data.entrees.Entree
is the base class for all entrée items. It should include the following elements that are common to all entrée classes:- Bread - attribute with getter and setter.
- Condiments - attribute with getter, Add Condiment and Remove Condiment methods.
- Price - abstract getter. This should be overridden in the subclass to return the correct price.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories.
- Special Instructions - getter. This should be overridden in the subclass to return the correct list of special instructions.
- One easy way to do this: the method in the superclass could be used to add the list of condiments to the list, and then the subclass method could call the superclass method as part of its code.
starfleetsubs.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:- Size - getter and setter.
- Price - abstract getter. This should be overridden in the subclass to return the correct price based on the size.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories based on the size.
- Special Instructions - getter. This should simply return an empty list, and does not need overridden.
starfleetsubs.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:- Size - getter and setter.
- Price - abstract getter. This should be overridden in the subclass to return the correct price based on the size.
- Calories - abstract getter. This should be overridden in the subclass to return the correct calories based on the size.
- Special Instructions - abstract getter. This should be overridden in the subclass to return the correct list of special instructions.
You may choose to implement the OrderItem
interface on the three base classes described below, which will then be inherited by each menu item, instead of explicitly implementing the interface on each menu item itself. Some of the elements described on these base classes are already defined in the OrderItem
interface, so if you implement the interface at the base class level you do not need to redefine the abstract methods from the interface within the abstract base classes. Either approach is valid!
If you choose to inherit from the OrderItem
interface in the base classes in Python, the base class should not inherit from ABC
- that is already covered as part of the interface. If you do, Mypy will present an error stating that it “cannot determine consistent method resolution order.”
You may also need to refactor some private
attributes (with double underscores in Python) to protected
attributes (single underscores in Python) as they move from the subclass to the superclass. In Java, these are just attributes as expected. In Python, it is simplest to declare those in the constructor of the superclass (such as self._size = Size.SMALL
), then make sure you call that constructor using super().__init__()
in the subclass’ constructor.
Menu Class
The starfleetsubs.data.menu.Menu
class should be a class that has static getter methods for these four elements:
entrees
- a list ofOrderItem
elements containing an instance of all available entrées (7 in total).sides
- a list ofOrderItem
elements containing an instance of all available sides. Since each side is available in three sizes, the list should include an instance of all three sizes of each side item (12 in total).drinks
- a list ofOrderItem
elements containing an instance of all available drinks. Since each drink is available in three sizes, the list should include an instance of all three sizes of each drink item (15 in total).fullmenu
- a combined list of all menu items (34 in total).
In Java, these lists should use a subclass of the List interface. In Python, these methods should use the built-in Python list data type. Since they are static methods, they cannot be constructed as Python properties using the @property
decorator.
Unit Tests
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Entrées
Add:
InheritsFromEntree()
- check if a given object inherits from the baseEntree
class.ImplementsOrderItem()
- check if a given object implements the interfaceOrderItem
.ChangeCondimentSetsSpecialInstructions(Condiment)
- for each condiment, check that changing it from and to the default value will add and remove the correct item from theSpecialInstructions
list.
Update:
SpecialInstructionsInitiallyEmpty()
should be renamedSpecialInstructionsInitiallyCondiments()
and should now verify that the initial set of condiments is in the special instructions list.
Sides
Add:
InheritsFromSide()
- check if a given object inherits from the baseSide
class.ImplementsOrderItem()
- check if a given object implements the interfaceOrderItem
.SpecialInstructionsEmpty()
- check that the Special Instructions list is always empty.
Drinks
Add:
InheritsFromDrink()
- check if a given object inherits from the baseDrink
class.ImplementsOrderItem()
- check if a given object implements the interfaceOrderItem
.
To check for type compatibility, use the object instanceof Class
operator in Java, or the isinstance(object, Class)
method in Python as part of an assertion statement. Hamcrest also includes a few matchers for this, such as isA
(Java) or instance_of()
(Python).
Menu
Create a new test class for the Menu
static class:
IncludesAllEntrees()
- test that theentrees
list contains an instance of each entrée classIncludesAllSides()
- test that thesides
list contains an instance of each side class for each sizeIncludesAllDrinks()
- test that thedrinks
list contains an instance of each drink class for each sizeIncludesAllItems()
- test that thefullmenu
list contains an instance of every menu item.
GUI Basics
This page lists the milestone requirements for Milestone 4 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The fourth milestone involves creating the various GUI windows and panels required for this project. The next milestone will involve adding functionality to these GUI elements beyond the ability to load different panels into the main window area.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone should include the following features:
- A
starfleetsubs.Main
class that properly loads and displays the program’s GUI. - A
starfleetsubs.gui.MainWindow
class that represents the main GUI window.- It should contain two panels - a main panel and a sidebar panel.
- It should also contain two methods: one to load a particular panel into the main panel, and another to load the order screen into the main panel.
- A
starfleetsubs.gui.OrderPanel
class to represent the main order screen panel.- It should contain three panels of buttons, one each for entrées, sides, and desserts. They may be automatically generated from the menu.
- Each entrée will be listed once, but each side and drink will have 3 buttons - one for each size.
- When clicked, those buttons should call a method to load the appropriate panel in to the main panel.
- A
starfleetsubs.gui.SidebarPanel
class to represent the sidebar panel.- It should contain labels for order number, subtotal, tax, and total.
- It should contain an “Edit” button, that does nothing when clicked.
- It should also include a list box as a placeholder that can be used to keep track of the order. The list box should expand to fill all remaining vertical space in the window.
- A panel class in the
starfleetsubs.gui.entrees
package for each entrée item.- It should include appropriate controls for modifying the ingredients, bread, and condiments.
- When given an instance of the item as a parameter to the constructor, the values of the controls should be set to match the values in the instance.
- It should include a “Save” button that, when clicked, will replace the main panel with the order screen.
- You may include a parent
EntreePanel
class to reduce the amount of duplicate code.
- A SINGLE panel class
SidePanel
in thestarfleetsubs.gui.sides
package.- It should include appropriate controls for modifying the size of the item.
- When given an instance of the item as a parameter to the constructor, the values of the controls should be set to match the values in the instance.
- It should include a “Save” button that, when clicked, will replace the main panel with the order screen.
- Since each side only has a single option, this panel can be generalized to work with the parent
Side
class. However, when buttons on the OrderPanel are clicked, you’ll need to make sure an instance of the correct item is generated.
- A panel class in the
starfleetsubs.gui.drinks
package for each drink item.- It should include appropriate controls for modifying the ingredients and size.
- When given an instance of the item as a parameter to the constructor, the values of the controls should be set to match the values in the instance.
- It should include a “Save” button that, when clicked, will replace the main panel with the order screen.
- You may include a parent
DrinkPanel
class to reduce the amount of duplicate code.
- Classes in the
starfleetsubs.gui
package do not require unit tests. - Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored. - Classes in the
starfleetsubs.gui
package do require all appropriate documentation comments, and must be free of style errors. - Update the UML Diagram Contained in this project to match the updated structure of the project.
You are welcome to add additional methods to the existing content in the starfleetsubs.data
package. If so, make sure you include appropriate type checking and unit tests.
See below for a few sketches of what your GUI might look like.
You are encouraged to use the code from Example 6 as a basis for this GUI, or you may create a different design. There are no set requirements for the design other than what is listed above, and the overall focus in this milestone is on simply getting the content on the screen and the ability to move between the various panels. You are welcome to spend additional time on the design if desired, but focus on getting the the content on the screen before doing any design work.
Time Requirements
Completing this project is estimated to require 3-8 hours.
A rough estimate for this milestone would be around 1500 lines of new code. It could vary widely based on how you choose to implement the various portions of the GUI. I was able to reuse many portions of the example project and expand on them to build this milestone. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
Main
class - 2%MainWindow
class - 4%SidebarPanel
class - 4%OrderPanel
class - 20%- Entrée Panel classes - 40%
SidePanel
class - 5%- Drink Panel classes - 15%
- Updated UML diagram - 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
GUI Sketches
Below are some GUI sketches to help you visualize one possible GUI for this project. You do not have to match this design at all, but this is at least a good starting point that you can reach based on what you learned in Example 6.
I chose to increase the default size of my GUI to 1024x740 pixels, as that made the buttons fit better into the window. - Russ
Main Window
Entree Panel
Side Panel
Drink Panel
Helpful Hints & Code
Here are a couple of helpful pieces of code that you may wish to use in your project.
Java
In many cases, I found it easiest to create private or protected methods that will construct my GridBagConstraints
objects, either within the class I was working in or in a parent class in the case of entrée and drink panels. Here’s an example:
/**
* Construct a GridBagConstraints object.
*
* @param y the y coordinate of the object
* @param start set anchor to LINE_START
* @return the constructed GridBagConstraints object
*/
protected GridBagConstraints makeGbc(int y, boolean start) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = y;
if (start) {
gbc.anchor = GridBagConstraints.LINE_START;
}
gbc.insets = new Insets(2, 2, 2, 2);
return gbc;
}
Then, when I want to place something in my layout using a GridBagConstraints
object build from this method, I can use this:
this.add(check, this.makeGbc(i++, true));
The biggest benefit to this approach is that I can easily adjust all of the buttons by changing this one method. This is a great example of the “Don’t Repeat Yourself” or DRY principle.
Python
In many cases, I found it helpful to create a dictionary of settings that I’d like use with the grid()
method, and then pass that entire dictionary as keyword arguments to the method. I usually did this either in a helper method within the class itself, or in a parent class in the case of entrée and drink panels. Here’s an example:
def _grid_dict(self, row: int, sticky: str) -> Mapping[str, Any]:
"""Create a dictionary of settings.
Args:
row: the row for the item
sticky: the sticky settings
"""
settings: Dict[str, Union[str, int]] = dict()
settings["row"] = row
settings["column"] = 1
settings["padx"] = 2
settings["pady"] = 2
settings["sticky"] = sticky
return settings
Then, when I want to place something in my layout using the grid()
method with these settings, I can use this:
checkbutton.grid(**self._grid_dict(i, "W"))
Notice that I have to place two asterisks **
before the method. That tells Python to “unpack” the dictionary returned by that method so that it can be read as individual keyword parameters. A deeper explanation is found here.
The biggest benefit to this approach is that I can easily adjust all of the buttons by changing this one method. This is a great example of the “Don’t Repeat Yourself” or DRY principle.
I also had to tell Mypy to ignore the lambda expressions used in the OrderPanel
class, as it cannot properly determine the type of the lambda. You can do this by adding a # type: ignore
comment at the end of the offending line.
button = Button(master=side_frame, text=str(side),
command=lambda x=str(side): # type: ignore
self.action_performed(x))
If anyone is able to figure out exactly how to properly get Mypy to handle this, there are major Bug Bounty points available!
Event-Driven Programming
This page lists the milestone requirements for Milestone 5 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The fifth milestone involves dealing with the various events generated by the GUI and constructing a list of items that represent an order.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone should include the following new GUI features:
- Changes to the previous milestone:
- Add a “Cancel” button to each of the entrée, side, or drink panels.
- Add a “Delete” button to the
SidebarPanel
panel. - Switch the list box in the
SidebarPanel
to a tree element (JavaJTree
or tkinterTreeview
). See the associated example project for code you can use for this.
See the updated GUI mockups below for some design ideas.
Once the entire project is working, you should observe the following behavior on the new tree element.
- When an item is added to the tree element in the
SidebarPanel
, the following should happen:- The item’s string representation should be a top-level node in the tree.
- Any special instructions for that item should be represented as child nodes of the top-level node.
- The item should be shown fully expanded by default.
- The tree element should only allow the user to select one item at a time.
It may be helpful to maintain a hash map or dictionary in the SidebarPanel
class that associates nodes in the GUI tree element with the actual OrderItem
instances that they represent.
In addition, the following events should be implemented in the GUI:
- When the “Save” button in any of the entrée, side, or drink panels is clicked, the following should happen:
- The item currently represented by the panel should be updated such that each attribute matches the current status of the associated GUI element.
- The item should be placed into the tree in the
SidebarPanel
if it is a new item, or the item should be updated if it is being edited. - The main panel in
MainWindow
should be replaced with theOrderScreen
(this was part of the previous milestone).
- When the “Cancel” button in any of the entrée, side, or drink panels is clicked, the following should happen:
- If an item is being edited, any changes made in the GUI should be discarded (the item should not be changed).
- The main panel in
MainWindow
should be replaced with theOrderScreen
(this was part of the previous milestone).
- When the “Edit” button in the
SidebarPanel
is clicked, the following should happen:- The
OrderItem
that is currently selected should be determined. If the selection is an ingredient of that item, the code should work upwards in the tree to find theOrderItem
. - The appropriate entrée, side, or drink panel should be loaded into the main panel in
MainWindow
and populated with the current status of the item (most of this should work from the previous milestone). - If the item is saved via the “Save” button, it’s entry in the tree element should be updated without changing the order of the items in the tree.
- If the changes are cancelled via the “Cancel” button, no changes should be made.
- The
- When the “Delete” button in the
SidebarPanel
is clicked, the following should happen:- The
OrderItem
that is currently selected should be determined. If the selection is an ingredient of that item, the code should work upwards in the tree to find theOrderItem
. - That item should be removed from the tree element and any other relevant data structures in the
SidebarPanel
class.
- The
Unit tests should be added to the corresponding test package for the following classes:
- Each entrée panel in
starfleetsubs.gui.entrees
- Each drink panel in
starfleetsubs.gui.drinks
- The single side panel in
starfleetsubs.gui.sides.SidePanel
See below for a list of suggested unit tests. You should achieve at or near 100% coverage on these classes. We will not unit test the MainWindow
, OrderPanel
, or SidebarPanel
classes in this milestone.
Python users: See the section at the bottom of this milestone for updates to the tox.ini
file to enable full unit testing via tox.
Finally, the following requirements from the previous milestone are continued:
- Classes in the
starfleetsubs.gui
base package do not require unit tests, but all entrée, drink, and side panels require unit tests as outlined above. - Classes and unit tests in the
starfleetsubs.gui
package and sub-packages do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored. - Classes and unit tests in the
starfleetsubs.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors. - Update the UML Diagram Contained in this project to match the updated structure of the project. There will most likely not be any new classes, but new associations between existing classes.
Time Requirements
Completing this project is estimated to require 3-8 hours.
A rough estimate for this milestone would be around 3000-3500 lines of new or updated code. It could vary widely based on how you choose to implement the various portions of the GUI. Most of the new code (around 2000-2500 lines) is contained in the unit tests, which are highly redundant. It took me less than an hour to take a working set of unit tests for TheRikerPanel
and use that as a template to create the rest of the unit tests. My current model solution contains 849 unit tests, and I was able to achieve 100% code coverage on all GUI OrderItem
panels. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- New GUI elements (“Cancel”, “Delete” and tree element): 5%
- Tree element displays order items correctly: 5%
- “Save” buttons work properly for all items: 25%
- “Cancel” buttons work properly for all items: 5%
- “Edit” button works properly for all items: 25%
- “Delete” button works properly for all items: 5%
- Unit Tests: 20%
- Updated UML Diagram: 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Updated GUI Sketches
Below are some GUI sketches to help you visualize one possible GUI for this project. You do not have to match this design at all, but this is at least a good starting point that you can reach based on what you know so far.
Main Window
Entree Panel
Helpful Methods
I found these methods helpful in my solution:
MainWindow.addItem(item)
- basically a pass-through method that calls theSidebarPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to theMainWindow
instance.SidebarPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.- You must check that the two elements are the same instance, not just that they are equal. Otherwise, two items with the same ingredients and condiments will be regarded as the same item, preventing the user from ordering more than one of them. This can be done using the
==
operator in Java, or theis
operator in Python. This means that you won’t be able to use the normalcontains()
orin
method for determining if the item is already in a list - you must iterate through the list directly. SidebarPanel.updateTree(item, node)
- handles actually updating the tree. Ifnode
isnull
or not provided, it creates a new one, otherwise it uses the existingnode
and updates it. It should return thenode
or that node’sid
when complete.
Unit Tests
Entrée Panels
Each entrée panel test class should contain unit tests for the following:
testDefaultConstructor()
- create the panel without providing an existing element, and assert that it creates a new instance of the correct item.testBadActionCommand()
- call theactionPerformed()
method with a bad action command, and assert that an exception is not thrown.testBreadComboBox(Bread)
- instantiate a panel with an existing item, change the value of the bread combo box in the GUI to thebread
value, and fire a “save” action, then verify that the item has the correct bread value.testBreadComboBoxSetCorrectly(Bread)
- instantiate a panel with an existing item using the givenbread
, and assert that the bread combo box is set to the correct value.test<Ingredient>CheckBox()
- instantiate a panel with an existing item, change the value of the ingredient check box in the GUI to a value, and fire a “save” action, then verify that the item has the correct value. Do this for bothtrue
andfalse
.test<Ingredient>CheckBoxSetCorrectly()
- instantiate a panel with an existing item with a given value for ingredient, and assert that the ingredient checkbox is set to the correct value. Do this for bothtrue
andfalse
.testCondimentCheckBox(Condiment)
- instantiate a panel with an existing item, change the value of the condiment check box in the GUI to a value, and fire a “save” action, then verify that the item has the correct value. Do this for bothtrue
andfalse
.testCondimentCheckBoxSetCorrectly(Condiment)
- instantiate a panel with an existing item with a given value for condiment, and assert that the condiment checkbox is set to the correct value. Do this for bothtrue
andfalse
.testCancelButton()
- instantiate a panel with an existing item, change several values in the GUI, and fire a “cancel” action, then assert that the item is unchanged from its previous state.
Side Panels
Each side panel test class should contain unit tests for the following:
testDefaultConstructor<Side>()
- create the panel by providing an instance of each side class, and test that its item is set to an instance of that class.testBadActionCommand()
- call theactionPerformed()
method with a bad action command, and assert that an exception is not thrown.testSizeComboBox(Size)
- instantiate a panel with an existing item, change the value of the size combo box in the GUI to thesize
value, and fire a “save” action, then verify that the item has the correct size value.testSizeComboBoxSetCorrectly(Size)
- instantiate a panel with an existing item using the givensize
, and assert that the size combo box is set to the correct value.testCancelButton()
- instantiate a panel with an existing item, change several values in the GUI, and fire a “cancel” action, then assert that the item is unchanged from its previous state.testConstructorEmptyItem()
- create the panel by passing a null item, and verify that an exception is thrown.
Drink Panels
Each drink panel test class should contain unit tests for the following:
testDefaultConstructor()
- create the panel without providing an existing element, and assert that it creates a new instance of the correct item.testBadActionCommand()
- call theactionPerformed()
method with a bad action command, and assert that an exception is not thrown.testSizeComboBox(Size)
- instantiate a panel with an existing item, change the value of the size combo box in the GUI to thesize
value, and fire a “save” action, then verify that the item has the correct size value.testSizeComboBoxSetCorrectly(Size)
- instantiate a panel with an existing item using the givensize
, and assert that the size combo box is set to the correct value.test<Ingredient>CheckBox()
- instantiate a panel with an existing item, change the value of the ingredient check box in the GUI to a value, and fire a “save” action, then verify that the item has the correct value. Do this for bothtrue
andfalse
.test<Ingredient>CheckBoxSetCorrectly()
- instantiate a panel with an existing item with a given value for ingredient, and assert that the ingredient checkbox is set to the correct value. Do this for bothtrue
andfalse
.testCancelButton()
- instantiate a panel with an existing item, change several values in the GUI, and fire a “cancel” action, then assert that the item is unchanged from its previous state.
To allow proper unit testing, you may need to relax the permissions on several elements inside of your GUI classes. I recommend using package-private
in Java, with no modifier - see this document. Then, any unit tests that are in the same package can have access to those members. For Python, switching from double underscore private attributes to single underscore protected attributes is sufficient.
Python tox Updates
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
- Because tox runs in a virtual environment by default, it is unable to construct the graphical tkinter elements for testing. This can be resolved by passing through the
DISPLAY
environment variable. - Because pytest is apparently very memory inefficient, the unit tests are killed by Codio once they consume too much memory. To work around this, we’ll run our unit tests in batches.
An updated tox.ini
file is given below. I recommend replacing your file with this one:
[tox]
envlist = py39
skipsdist = True
[testenv]
deps = -rrequirements.txt
passenv = DISPLAY
ignore_errors = True
commands = python3 -m mypy -p src --html-report reports/mypy
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees --html=reports/pytest-entrees/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/drinks test/starfleetsubs/gui/sides --html=reports/pytest-side-drinks/index.html
python3 -m coverage combine
python3 -m coverage html -d reports/coverage
python3 -m flake8 --docstring-convention google --format=html --htmldir=reports/flake
python3 -m pdoc --html --force --output-dir reports/doc .
The major changes:
passenv = DISPLAY
will tell the tox environment which display to use when loading tkinter elements.- We now run coverage in parallel mode, and specify the test folders in the pytest command. This will run three separate sets of tests.
- Notice that the test reports will now be in different folders. The old
reports/pytest
folder will no longer be updated. - We added a
coverage combine
command to combine the coverage data from multiple executions of pytest.
Orders & Combos
This page lists the milestone requirements for Milestone 6 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The sixth milestone involves creating combo meals and orders from the items selected in the GUI. We’ll use this milestone to explore some software design patterns in our code, as well as learn about using test doubles in our unit tests. With this milestone, most of the work on the core functionality of the GUI will be complete.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
New Classes
starfleetsubs.data.menu.Order
- this class should represent a collection of OrderItem
objects that make up an order.
- It should implement the Iterator Pattern, such that it can be used in a for each loop or enhanced for loop to iterate through all items in the list.
- It should also support standard collection methods such as:
- Getting the number of items in the collection (
size()
in Java or__len__()
in Python). - Determining if a given instance of an
OrderItem
object is contained in the collection (contains(item)
in Java or__contains__(item)
in Python). Recall that this should use the identity test, not the equality test. - Getting a single item from the collection based on the index of that item (either a
get(i)
method in Java or__getitem__(i)
in Python). - Any other standard collection methods that you feel are helpful. See the Collection interface in Java or Emulating Container Types in Python for additional methods that may be useful.
- Getting the number of items in the collection (
- It should have the following attributes:
- A private list
items
ofOrderItems
, with methods to add and remove items, as well as the iterator pattern methods discussed above.- NOTE - in most languages, the default method to remove an item from a collection will rely on equality testing, not instance testing. So, you may wish to write this method yourself instead of relying on the underlying collection, in order to keep this and the GUI in sync.
- A private integer representing the
orderNumber
for this order. It will be generated using theOrderNumberSingleton
class discussed below. It should only include a getter. - A private static float for the
taxRate
, which is set to 0.12 (12%) by default. It should include static methods to get and set the tax rate, which will be used by allOrder
objects. The tax rate must be a valid percentage value ranging from 0.0 to 1.0, inclusive.
- A private list
- It should also have getters for these three virtual attributes or properties:
- float
subtotal
- the total sum of the prices for each item in the order. - float
tax
- thesubtotal
multiplied by thetaxRate
- float
total
- thesubtotal
plus thetax
. - int
calories
- the total number of calories in the order.
- float
- All dollar amounts should not be rounded to two decimal places by this class. that will be handled by the GUI.
starfleetsubs.data.menu.Combo
- this class should implement the OrderItem
interface, and represent a combo meal consisting of an entrée, side, and drink.
- It should have the following attributes:
- A string
name
- the name of the combo, which does not require a getter (you may add one) or setter. This attribute can be set tonull
orNone
. - An
Entree
namedentree
- the entrée in the combo, which does not require a getter (you may add one) or setter. This attribute can be set tonull
orNone
. It should include aremoveEntree()
method to set the value tonull
orNone
. - A
Side
namedside
- the side in the combo, which does not require a getter (you may add one) or setter. This attribute can be set tonull
orNone
. It should include aremoveSide()
method to set the value tonull
orNone
. - A
Drink
nameddrink
- the drink in the combo, which does not require a getter (you may add one) or setter. This attribute can be set tonull
orNone
. It should include aremoveDrink()
method to set the value tonull
orNone
. - A static float
discount
- it has a value 0.5 ($0.50) by default. It should include static methods to get and set the discount, which will be used by allCombo
objects.
- A string
- It should also comply with the
OrderItem
interface:- A getter for
price
that returns the sum of the prices of each item. If all three items in the combo are populated, the discount is applied to this total. Otherwise, no discount is applied. - A getter for
calories
that returns the sum of the calories of each item. - A getter for
specialInstructions
that returns the name of the combo, if set, followed by the line"$0.50 Discount Applied"
if all three items are populated. It should not include any other items. (The discount value should be updated to match the staticdiscount
attribute.)
- A getter for
- It should also include the following methods:
- A constructor that accepts a string for the
name
. The constructor should allow the name to be omitted or set tonull
orNone
. Thename
will only be set by theComboBuilder
class discussed below, but users will also be able to configure a custom combo via the GUI that does not include a name. The constructor should set theentree
,side
anddrink
attributes tonull
orNone
initially. - An
addItem()
method that accepts anOrderItem
object and places it in the appropriate attribute (entree
,side
ordrink
). It should replace the existing item in that attribute, if any. If theOrderItem
is not one of the three types listed above, it should throw an appropriate exception. - A
getItems()
method that returns list of the items included in the combo, if any. If none are included, then return an empty list. - An implementation of the
equals()
or__eq__()
method to check for equality. Two combos are considered equal if their entree, side, drink, and name are equal (they do not have to be the same instances, just equal). If any attribute in this object isnull
orNone
, it is considered equal if the matching attribute is alsonull
orNone
.- This presents a real problem in Java, because calling the
equals()
method on anull
object will result in an exception. So, you’ll have to check if each attribute in this object isnull
first. If so, and the other object’s attribute is notnull
, then they are not equal. If this object’s attribute is notnull
, you can safely callequals()
on it, regardless of the other object’s attribute.
- This presents a real problem in Java, because calling the
- A constructor that accepts a string for the
starfleetsubs.data.menu.ComboBuilder
- a class that implements the Builder Pattern to build the available combos described below.
- It should include a single public static method
buildCombo()
that accepts an integer as input, and builds and returns theCombo
object indicated by the integer. - For simplicity, it may also include a public static getter for the number of combos available.
starfleetsubs.data.menu.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
- The class should have a non-static integer
nextOrderNumber
attribute, which is initially set to 1 - It should have one public static method
getNextOrderNumber()
that will return the next order number.- This method should call a private
getInstance()
method to get the actual singleton instance stored as a static attribute in the class. - It should access the
nextOrderNumber
attribute through that singleton instance. - This method should also use thread synchronization techniques to ensure that only a single thread can actually access and update the
nextOrderNumber
attribute (asynchronized
statement in Java or a lock in awith
statement in Python).
- This method should call a private
starfleetsubs.gui.PanelFactory
- a class that implements the Factory Method Pattern to return an instance of a GUI panel for a given entrée, side, or drink.
- It should include one public static method that is overloaded to accept two different sets of parameters:
getPanel(String name, MainWindow parent)
should accept the name of a menu item item as a string, and return a panel that represents a new instance of that item, with theparent
GUI element as its parent. You should be able to directly feed an action command from a button click in the GUI directly to this method and get the appropriate panel. If thename
is not recognized, an exception should be thrown.getPanel(OrderItem item, MainWindow parent)
should accept an instance of anOrderItem
and return a panel that represents that item, with theparent
GUI element as its parent. If theitem
is not recognized, an exception should be thrown.
- For now, do not worry about updating this class to handle
Combos
asOrderItems
. We’ll address that in the next milestone.
Updated Classes
Menu
- update to include the following items:
- A
getCombos()
method that returns all pre-configured combos described below. This method should use theComboBuilder
class discussed below. - Updated the
getFullMenu()
method to include the combos returned fromgetCombos()
in its output.
OrderPanel
- update to include the following items:
- The
actionPerformed
method should be updated to use thePanelFactory
class to acquire the appropriate GUI panel based on the action command received from button that was clicked.
SidebarPanel
- update to include the following items:
- When clicking the “Edit” button, it should use the
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree. - This class should now include a private
Order
attribute that stores the items in the order.- It should be instantiated by the
SidebarPanel
constructor. - It should be kept up to date as items are added to and removed from the order.
- Whenever the order is changed, it should update the order number, subtotal, tax, and total elements in the GUI. Prices should be properly formatted as currency values.
- See Currencies for Java.
- It should be instantiated by the
- The GUI should include two new buttons:
- “New Order” - clicking this button will create a new
Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.- You may wish to implement a modal dialog that asks the user to confirm before deleting the existing order. See How to Make Dialogs for Java or Dialog Windows for Python. This is not required but highly recommended!
- “Checkout” - clicking this button will have no effect at this time. It will be implemented in the next milestone.
- “New Order” - clicking this button will create a new
Unit Tests
All new classes except PanelFactory
should include full unit tests that achieve at or near 100% code coverage and adequately test all aspects of the class. In addition, some previous tests may need to be updated to match new requirements.
Java Only: You should also update the unit tests for each of the GUI panels created in the previous milestone to use a fake MainWindow
object instead of creating one in the test. This should make the tests run much faster, and you should be able to see that the code in MainWindow
is not executing in the code coverage report.
Python Only: Sadly, I have yet to figure out if it is possible to properly fake parts of tkinter
such that the MainWindow
class can be properly substituted with a fake. No changes are required at this time.
Once this milestone is complete, all classes in the following packages should have unit tests that achieve at or near 100% code coverage:
starfleetsubs.data.*
starfleetsubs.gui.drinks.*
starfleetsubs.gui.entrees.*
starfleetsubs.gui.sides.*
The only classes that do not meet this requirement are MainWindow
, OrderPanel
, PanelFactory
, and SidebarPanel
in the starfleetsubs.gui
package.
Time Requirements
Completing this project is estimated to require 3-8 hours.
A rough estimate for this milestone would be around 2000 lines of new or updated code. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- New Classes: 40%
Order
- 10%Combo
- 10%ComboBuilder
- 10%OrderNumberSingleton
- 5%PanelFactory
- 5%
- Unit Tests: 40%
Order
- 15%Combo
- 15%ComboBuilder
- 5%OrderNumberSingleton
- 5%
- Class Updates: 20%
Menu
and unit tests: 5%OrderPanel
: 5%SidebarPanel
: 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Combos
1 - Original Series
The Kirk, Bones McCoy, Altair Water
2 - Next Generation
The Riker, Data Chips, The Picard
3 - Voyage Beyond
The Janeway, Enterprise, The Guinan
4 - Warrior’s Way
The Gagh, Borg, The Worf
5 - Galaxy Class
The Scotty, Enterprise, The Troi
6 - Judgement of Humanity
The Q, Borg, The Picard
Unit Tests
This is a suggested list of unit tests you may wish to implement to test your new and updated classes in this milestone. You should be able to reach 100% code coverage in each of these classes.
Order
SizeIs0Initially()
- the size of the order is initially 0.TotalsAre0Initially()
- the subtotal, tax, and total are 0 initially.NegativeTaxRateThrowsException()
- setting the tax rate to a negative value throws an exception.TaxRateOver100ThrowsException()
- setting the tax rate to a value over 1.0 throws an exception.AddItemsUpdatesSize()
- add three fake items one at a time and check size after each one.AddItemsUpdatesTotals()
- add three fake items one at a time and check subtotal, tax, and total after each one.AddItemsUpdatesCalories()
- add three fake items one at a time and check calories after each one.ContainsUsesInstanceComparison()
- confirm that thecontains
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true whenequals()
is called. Place one in the order, and use them to confirm thatcontains
returns both true and false when given two items that are equal but not the same instance.RemoveUsesInstanceComparison()
- confirm that theremoveItem
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true whenequals()
is called. Place both in in the order, then remove one and confirm that the correct one was removed using contains. You may wish to do this twice, removing the first one added once and the second one added the second time.OrderNumberFromSingleton()
- confirm that theOrder
class is usingOrderNumberSingleton
. Create a fakeOrderNumberSingleton
that returns a value for an order number, then instantiate anOrder
and verify that it received the given order number.TaxRateSetGlobally()
- create twoOrder
instances, change the tax rate, and confirm that both use the new tax rate. This is best done by adding an item to each order and checking thetax
virtual attribute.RemoveMissingItemDoesNotThrow()
- removing an item not in the order should not throw an exception.IteratorContainsItems()
- add fake items to the order, get the iterator, and confirm that the fake items are returned in order.GetItemsByIndex()
- add fake items to the order, and confirm that each one can be accessed via its index.
Combo
ConstructorSetsName()
- the constructor should set the name. This is visible as the first element in the special instructions list.ConstructorAcceptsNullName()
- the constructor should acceptnull
orNone
for the name.ConstructorSetsItemsToNull()
- the constructor should set the entree, side, and drink elements tonull
orNone
.SetDiscountToNegativeThrowsException()
- setting the discount to a negative value throws an exception.CanSetDiscountToZero()
- setting the discount to 0 does not throw an exception.PriceZeroNoItems()
- the price should be 0 if all items arenull
orNone
.CaloriesZeroNoItems()
- the calories should be 0 if all items arenull
orNone
.PriceAllItems()
- add fake entree, side, and drink to combo and verify that the price is summed correctly (remember to take off the discount).CaloriesAllItems()
- add fake entree, side, and drink to combo and verify that the calories is summed correctly.NoDiscountWhenItemMissing()
- add two of the three items to the combo and verify that the price is correct and does not include discount.DiscountSetGlobally()
- create twoCombo
instances, change the discount, and confirm that both use the new discount. This is best done by adding three items to each combo and checking the total price.AddEntreeUpdatesEntree()
- add anEntree
to the combo usingaddItem()
and verify that it is placed in theentree
attribute. You may need to make the attribute visible to the test.AddSideUpdatesSide()
- add aSide
to the combo usingaddItem()
and verify that it is placed in theside
attribute. You may need to make the attribute visible to the test.AddDrinkUpdatesDrink()
- add aDrink
to the combo usingaddItem()
and verify that it is placed in thedrink
attribute. You may need to make the attribute visible to the test.ItemsListCorrect()
- add fake items to the combo and verify that the list returned bygetItems()
contains them.ItemsListEmpty()
- getting a list when the combo is empty results in an empty list.SpecialInstructionsHasDiscount()
- special instructions should contain “$0.50 Discount Applied” if all three items are populated.AddingComboToComboThrowsException()
- adding a combo as an item to a combo throws an exception.TwoCombosEqual()
- create two combos containing the same name and fake objects and test that they are equal.TwoCombosNotEqual()
- create two combos with different names but the same fake objects, and test that they are not equal.TwoEmptyCombosEqual()
- create two empty combos withnull
orNone
names and test that they are equal.TwoCombosOneEmptyNotEqual()
- create two combos, one empty, one not, and test that they are not equal.DifferentObjectNotEqual()
- confirm that equality test will returnfalse
when given a different type of object.
You may need to add additional tests of the equals()
method in Java to achieve 100% code coverage.
ComboBuilder
For these tests, I recommend just checking the types of the entree, side, and drink item in the Combo returned, as well as the name, rather than using any fake objects. As before, you may wish to make these attributes visible to the test.
Combo1()
- Combo 1 is built correctlyCombo2()
- Combo 2 is built correctlyCombo3()
- Combo 3 is built correctlyCombo4()
- Combo 4 is built correctlyCombo5()
- Combo 5 is built correctlyCombo6()
- Combo 6 is built correctlyBadComboThrowsException()
- a bad combo number should throw an exception
OrderNumberSingleton
SequentialOrderNumbers
- callgetNextOrderNumber()
several times and make sure each one is sequential.
Python tox Updates
I ran into even more issues with Python not running unit tests in tox properly on this assignment. As before, it seems to be the same cause:
- Because pytest is apparently very memory inefficient, the unit tests are killed by Codio once they consume too much memory. To work around this, we’ll run our unit tests in batches.
An updated tox.ini
file is given below. I recommend replacing your file with this one:
[tox]
envlist = py39
skipsdist = True
[testenv]
deps = -rrequirements.txt
passenv = DISPLAY
ignore_errors = True
commands = python3 -m mypy -p src --html-report reports/mypy
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheGaghPanel.py --html=reports/pytest-entrees1/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheJanewayPanel.py --html=reports/pytest-entrees2/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheKirkPanel.py --html=reports/pytest-entrees3/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheQPanel.py --html=reports/pytest-entrees4/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheRikerPanel.py --html=reports/pytest-entrees5/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheScottyPanel.py --html=reports/pytest-entrees6/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/entrees/test_TheSpockPanel.py --html=reports/pytest-entrees7/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/starfleetsubs/gui/drinks test/starfleetsubs/gui/sides --html=reports/pytest-side-drinks/index.html
python3 -m coverage combine
python3 -m coverage html -d reports/coverage
python3 -m flake8 --docstring-convention google --format=html --htmldir=reports/flake
python3 -m pdoc --html --force --output-dir reports/doc .
The major changes:
- We now run coverage in parallel mode, and specify the test folders in the pytest command. This will run several separate sets of tests. I had to move each large GUI panel to its own test, as I couldn’t run them all in a single batch.
- Notice that the test reports will now be in different folders. The old
reports/pytest
folder will no longer be updated. - We added a
coverage combine
command to combine the coverage data from multiple executions of pytest.
Checkout
This page lists the milestone requirements for Milestone 7 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The seventh milestone involves finalizing the GUI for creating combos, and handling the steps to check out and pay for an order, including printing a receipt. The purpose is to continue to learn how to use and modify an existing GUI and interface with an external library.
Fewer hints will be given as to the overall structure of your implementation for this milestone. Therefore, you will have to make some decisions about how you feel this milestone should be best achieved and the overall structure of your code!
When in doubt, feel free to contact the course instructor to discuss possible ideas. You may also choose to write small “demo” implementations either in this project or one of the related example projects before committing to a particular solution.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
It is best to think of this assignment as one consisting of two distinct parts.
Part 1 - Update GUI Panels to Handle Combos
Add updated buttons and panels to the GUI to facilitate creation and customization of combos created as part of the previous milestone. It should have the following features:
- Users should be able to directly select one of the pre-built combos included in the previous milestone and add it to the order.
- Users should be able to create a custom combo consisting of an entrée, side, and/or drink of their choice.
- You do not have to enforce the requirement that a combo contains all three items to be added to the order. However, the combo should only get the discount if all three items are populated. The existing
Combo
class should handle this as defined in the previous milestone.
- You do not have to enforce the requirement that a combo contains all three items to be added to the order. However, the combo should only get the discount if all three items are populated. The existing
- Any entrée, side, or drink in the combo should also be customizable.
- Some of the code in the
SidebarPanel
class will need to be updated to properly handle combos.- Combos should be displayed with the name of the combo as the topmost element in the tree. If the name is not set, a default name may be used.
- If the combo is eligible for the discount, that message should be displayed as a child node of the combo.
- Each item in the combo should be displayed below the combo name as a child node.
- The special instructions of each item in the combo should be displayed as child nodes of the appropriate item.
- In effect, combos will have 3 levels in the tree instead of the usual 2 for other order items.
- This means that some of the logic for handling item selection and updates will need to be carefully updated.
- You may choose to simply write special cases for handling combos instead of generalizing or using recursion (the tree will be limited to 3 levels of depth, not including the single hidden root node).
- Any new functionality should not interfere with previous functionality. This means:
- All individual entrées, sides, and drinks can be added to the order and customized.
- Any items in the order can be selected and edited.
- If an item is part of a combo, you may choose to load the screen for editing the entire combo instead of the item selected - this is up to you!
Hints for Part 1
At the bottom of this page is a GUI sketch of one possible way to build a screen for customizing a combo. It is designed to reuse the existing panels for each menu item. We will refer to this class as ComboPanel
in this document. In your implementation, you are encouraged to reuse existing code whenever possible - try to stick to the Don’t Repeat Yourself principle. Some hints for this particular implementation:
- Instead of each panel using the
MainWindow
class/type as its parent, we can abstract that to aParentPanel
interface that is implemented by both theMainWindow
class andComboPanel
. This allows the existing order item panels to use the newComboPanel
as its parent. - Use combo boxes to allow users to select from existing items to add to the combo. Add a listener/event handler for when the combobox is changed, and use that to change the panel for that item.
- Include a default option representing “no selection” in the combo boxes to allow users to clear out a particular option.
- Recall that the panels for each menu item will call a method in the parent panel when the item is saved. This can be used to retrieve the updated item from the panel when the “Save” button is clicked in the combo customization panel. Here’s the basic order of events:
- Click “Save” in
ComboPanel
- Fire “save” event in item panel
- Receive item from panel via the panel calling the save method in its parent (which is now
ComboPanel
instead ofMainWindow
) - Update the combo order item
- Call the save method in the
MainWindow
to add the item to the order.
- Click “Save” in
- You may choose to add additional getters to the classes in the
data
package as desired. - In Python, you may have a circular reference in your
PanelFactory
since it could be used from withinComboPanel
, but also will be used to create instances ofComboPanel
. A way to resolve this would be to create aComboPanelFactory
to handle combos, and adapt the code wherePanelFactory
is used to direct combo instances to the newComboPanelFactory
instead.
Unit Tests
Your new GUI panel(s) should include some basic unit tests modeled after the tests used for the item panels. Specifically, you should test the following:
- Selecting a particular entrée, side, or drink in the appropriate GUI element causes a panel of the correct type to be loaded.
- Receiving a combo as input containing a particular entrée, side, or drink causes the panel of the correct type to be loaded.
- Selecting a particular entrée, side, or drink to be included in the combo via the GUI causes an item of that type to be added to the resulting
Combo
object when it is saved. - Selecting the “no selection” option will remove that item from an existing
Combo
object when it is saved. - Cancelling will result in no changes being made to the
Combo
object.
You should use test doubles (stubs, fakes, or mocks) in these unit tests to mimic the other parts of the application, including the order items and associated panels. The goal is to only test the new GUI panel(s) in isolation. This may not be possible in Python due to issues with mocking classes from tkinter
.
Part 2 - Checkout
Implement the functionality for a user to checkout and complete an order. This process will make use of an external library to handle credit cards, cash transactions, and printing a receipt. First, you’ll need to install the register
library into your application:
- Java
- Download and install the latest JAR file release from GitHub.
- View the Javadoc for specifics of how to use it.
- Review the Source Code if desired.
- All library classes are in the
edu.ksu.cs.cc410.register
package. - Post any questions or bugs regarding the library to the GitHub Issues page.
- Pull requests for bug fixes are welcome! However, in general we won’t greatly change or enhance the functionality of the library overall.
- Python
- Download and install the latest wheel file release from GitHub.
- View the Documentation for specifics of how to use it.
- Review the Source Code if desired.
- All library classes are in the
cc410.register
package. - Post any questions or bugs regarding the library to the GitHub Issues page.
- Pull requests for bug fixes are welcome! However, in general we won’t greatly change or enhance the functionality of the library overall.
When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
- Pay by Credit/Debit Card
- Pay by Cash
- Cancel
Clicking “Cancel” will return to the main GUI screen without changing the existing order.
Otherwise, see the descriptions below for the process of paying by credit/debit card or cash.
You may wish to use modal dialogs in various places in this milestone to present responses or error message to the user. See How to Make Dialogs for Java or Dialog Windows for Python.
Read this entire section before attempting to build this part of the application. You may wish to develop the wrapper classes and unit tests discussed in the unit testing section first, then use those wrappers in your eventual GUI panels. The design of the wrappers may inform the overall interaction design in the GUI.
Pay by Credit Card
When a user chooses to pay by credit card, the application should call the appropriate method of the CardReader
class in the external library. That method will return one of the CardTransactionResult
enumeration values, which describes the result. If the response is APPROVED
, the transaction is completed and the application may proceed to print the receipt (see the description below). Otherwise, the appropriate error message from the CardTransactionResult
should be displayed to the user, and they may choose to try again.
The CardReader
class will return APPROVED
roughly 40% of the time, and each other result will be returned around 10% of the time each.
Pay by Cash
When the user chooses to pay by cash, the application should show a window where the user can enter the cash denominations and amounts provided from the customer. One possible GUI sketch for this window is included at the bottom of this page.
The GUI should include a “Cancel” button that can be used at any time to cancel the cash transaction and return back to the main GUI screen without changing the existing order.
The CashDrawer
class in the external library is used to keep track of the available amount of each denomination in the drawer and to balance transactions. Each transaction begins by opening the drawer and providing the expected amount to be deposited. Then, while the drawer is open, cash denominations are added to the drawer from the customer and any change given back is deducted from the drawer. When the drawer is closed, the amount it contains must equal the previous amount plus the expected transaction amount. In addition, the total value in the drawer and the count of each denomination in the drawer may be accessed when the drawer is closed.
Your project must only instantiate a CashDrawer
instance once, when the project is first launched. It should use that same CashDrawer
instance for all transactions, updating it as needed, until the application is closed.
Cash denominations are listed in the CashDenomination
enum, which includes both the name and value of each denomination.
If the customer has not provided enough money to pay for the transaction, your application should now allow it to be finalized. Your application should also handle making appropriate change from the cash drawer when finalizing a transaction. This includes determining the count of each denomination to be given back to the customer. Some tips for completing this portion of the project:
- The contents of the drawer cannot be queried while the drawer is open, nor can the contents of the drawer be updated while it is closed. The external library will throw exceptions if this rule is violated.
- To make change, find the amount to be given back and work from the highest denomination to the lowest. Make use of division and modulo arithmetic. (This is exactly backwards to how you were most likely taught to do this in your head!) If you use any online resources to create this algorithm, make sure you cite them in the comments of your code.
- The cash drawer contains limited amounts of each denomination. So, when making change, you may find that you don’t have enough of a particular denomination. If that is the case, deduct one from the next largest available denomination and use that to refill this denomination. We will assume that you are able to freely convert one denomination to another using an external source.
Thankfully, the monetary system in the United States will always guarantee that change will be made with the fewest possible coins by following the naive algorithm described above. So, that greatly simplifies this process.
In addition, since the cash drawer will only accept deposits, we never have to worry about running out of cash. Simply make sure that the cash received from the customer is added to the drawer before removing the change. If needed, you can exchange the denominations provided from the customer to other denominations as part of your algorithm to make change.
Finally, consider multiplying all values by 100 to work with whole integers instead of floating-point values. There is a great risk of floating-point error when working with cash values in this way.
When the transaction is completed successfully, the application may proceed to print the receipt (see the description below).
Printing a Receipt
Once a transaction has been completed successfully, the system should print a receipt containing the details of the transaction. The ReceiptPrinter
class in the external library is used to print a receipt.
The receipt should include the following information:
- The order number
- The date and time of the transaction
- A list of all items in the order, including price and special instructions.
- The subtotal
- The tax amount
- The total amount
- The payment method (credit/debit or cash)
- If paid by cash, the amount received and the change given.
The receipt can only be printed one line at a time using the appropriate method in the ReceiptPrinter
class, and each line is limited to no more than 40 characters. You are encouraged to make use of simple formatting, ASCII art, and short indentions to make the receipt more readable. There are methods provided in the ReceiptPrinter
class to start and end a receipt.
The ReceiptPrinter
class will print the receipt to a file named receipt.txt
in the project folder. By default, the ReceiptPrinter
will append new receipts to the end of that file. You may wish to empty this file regularly as part of testing, and should not commit it to GitHub.
Unit Tests
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
- When a cash transaction is finalized, the customer must have provided an amount of money equal to or greater than the transaction amount.
- When a cash transaction is completed, your application makes the correct change - both the amount and the denominations returned.
- When making change, the application will correctly handle the situation when not enough of a denomination is present.
- When a receipt is printed, it includes all of the information in an order.
You do not have to verify that the external library functions correctly. It already contains a complete set of unit tests. You are encouraged to review the source code of the unit tests contained in the external library for examples of how to test your own code!
Instead, you are encouraged to write wrapper classes around the classes in the external library using the adapter pattern and test those wrapper classes that contain your logic.
For example:
- Write a method in your
CashDrawer
wrapper that accepts a transaction amount and a description of the cash denominations provided by the user, and then computes the correct change and returns a description of the denominations and amounts to be given as change. If the user did not provide enough cash, it could throw an exception or some other error. - Write a method in your
CashDrawer
wrapper that accepts a description of the cash provided by the user, and a description of the change to be given. The method should compute the updated contents of the drawer using its existing contents, making substitutions when needed to handle situations where not enough of a denomination are present, and then return a description of those changes.- Your wrapper would also include a separate method to actually send those changes to the cash drawer, but that method does not need to be unit tested for correctness and shouldn’t be directly called by the method above. That would technically be an integration test, which we aren’t worrying about for now.
- Write a method in your
ReceiptPrinter
wrapper that accepts anOrder
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect theOrder
given to it.- Your wrapper would also include a separate method to actually print a list of strings to a receipt, but that method does not need to be unit tested for correctness and shouldn’t be directly called by the method above.
Review the source code of the CashDrawer
class in the external library to see how it uses a hash map or dictionary to keep track of its contents. This is a good model for describing “cash” amounts made up of several denominations and amounts in these methods.
If done correctly, you should not have to create a test double for any of the classes in the external library. While not an unbreakable rule, it is generally considered a bad practice to mock a type you don’t own, as that can lead to issues if the external library’s API changes in the future. The mock version of the library will continue to function as before, meaning tests will pass that would otherwise fail when executed on the real library.
Time Requirements
Completing this project is estimated to require 5 - 10 hours.
A rough estimate for this milestone would be around 1500-2000 lines of new or updated code. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Part 1 - 50%
- Combo Buttons on Order Panel - 5%
- Combo Interface for selecting/editing items - 25%
- Sidebar Handles Combos - 10%
- Unit Tests - 10%
- Part 2 - 50%
- Credit Card - 5%
- Cash Interface - 5%
- Makes Change - 15%
- Prints Receipt - 15%
- Unit Tests - 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Sample Combo Customization GUI
Sample Cash Transaction GUI
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
Website Basics
This page lists the milestone requirements for Milestone 8 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The eighth milestone involves moving into the web by creating a data-driven website to display the menu and some other information about the restaurant.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings. - All HTML must conform to the HTML5 standard. Use the W3C Validator to check your rendered pages if desired.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
Web Framework
Add a Web Framework to the existing project.
- Java - Install the Spring framework using the Spring Initializr. It should include the Spring Boot DevTools, Spring Web, and Thymeleaf Template Engine as dependencies.
- Python - Install the Flask framework and the Flask-Classful extension. You may also wish to install
python-dotenv
to use a.flaskenv
file.
Java Users - You will need to remove the 'org.junit.jupiter:junit-jupiter-api:5.6.2'
entry from the testImplementation
section of the dependencies. It conflicts with the version provided by Spring.
Python Users - You may ignore any type errors from flask_classful
by adding #type: ignore
after the import line.
Web Code
- Create a new
starfleetsubs.web
package. - Create a
starfleetsubs.web.MenuController
class to act as the controller. It should include the following routes:/
- a home page for the application./about
- an about page with the text given at the bottom of the page./menu
- a page that includes the entire menu (all predefined combos, entrees, sides, and drinks).- It should use the existing
Menu
class to collect these items. - You may add additional methods (with requisite unit tests) to the
Menu
class as desired.
- It should use the existing
- Update the required files to launch the web application properly as shown in the example video.
Templates
Create a base layout file including the following:
- Valid HTML5 structure
- A <title> element including the page name, followed by
- Starfleet Subs
- A <body> containing:
- <nav> that contains links to all pages in the application
- <main> containing all the content in the page
- <footer> containing the following copyright notice: “© 2021 Starfleet Subs”
- It is recommended (but not required) to build upon an existing template. You may wish to review the Bootstrap Examples.
Create the following template files to match the routes listed above:
index.html
contains an <h1> tag with the title “Starfleet Subs” and the following text in a paragraph (you may add additional text as desired):
Welcome to Starfleet Subs! Our motto: to boldly eat a sandwich where no sandwich has been eaten before!
about.html
contains an <h1> tag with the title “About Starfleet Subs” and the following text in a paragraph (you may add additional text as desired):
Starfleet Subs was developed as part of the CC 410 course at Kansas State University by <your name here>.
menu.html
contains the following content:- an <h1> containing “Menu”
- an <h2> containing the four categories of menu items (entree, side, drink, combo)
- Each menu item should be placed in a <div> with the class
menu-item
. It should include:- The name of the item
- The price of the item
- The calories of the item
- If the item comes in multiple sizes, the price and calories for each size should be listed!
- You may use additional HTML elements & CSS style to improve the readability of this page as you see fit! As with the GUI project, this is your chance to explore a bit.
- The model solution uses the Card component and Row Columns in Bootstrap.
- Under the “Combo” heading, add a note that any entree, side, and drink may be combined for a combo discount, and print the current combo discount value as well. (Hint: you’ll have to send this through the controller to the template somehow…)
You can format currency values directly in your templates! See Formatting Currencies in Spring using Thymeleaf for Java or using the familiar Python String.format() function as demonstrated in this StackOverflow comment.
Time Requirements
Completing this project is estimated to require 2 - 5 hours.
A rough estimate for this milestone would be around 500 lines of new or updated code, the majority of which is HTML. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Web Framework Installation: 10%
- Web Code: 30%
- Index & About Routes: 10%
- Menu Route: 20%
- Templates: 60%
- Layout Template: 20%
- Index & About Templates: 10%
- Menu Template: 30%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Web Sketches
Below is a screenshot from the model solution for some web design inspiration.
Form Data
This page lists the milestone requirements for Milestone 9 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The ninth milestone involves augmenting the menu display from the previous project by adding search and filtering functionality via an HTML form.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings. - All HTML must conform to the HTML5 standard. Use the W3C Validator to check your rendered pages if desired.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
Simple Search via Keywords
Your website should implement a simple search functionality via keywords, which allows the user to enter one or more words, separated by spaces, in a text input field, and then any menu items containing any of those keywords anywhere in the name of the item should be displayed on a results page.
Your search page should be accessible via the search
route/URL. If you used a template layout that includes a search box, such as the Bootstrap Sticky Footer with Navbar, you may implement this search functionality using the search box in the default layout. Make sure that you specify the action
of the form to point to the correct URL, since it will be available on all pages. The form should use the HTTP POST
method.
You may choose to use the same template for both the search page and the results, or different templates. Also, don’t forget to add a link to the search
URL in your site’s navigation in the layout template.
Advanced Search and Filter
Your website should also implement an advanced search and filter feature. This page will allow the user to find menu items based on the following criteria:
- Keywords (same as the simple search above)
- Type (entree, side, drink, combo)
- Price Range (minimum & maximum)
- Calories Range (minimum & maximum)
Your advanced search page should include HTML form elements for each of the items given above, arranged to make it clear to the user how to use the form. Try to make it as functional as possible based on the user’s intent. For example, if the user doesn’t enter any keywords, assume that they wish to find all menu items. Likewise, if the user inputs a maximum price but not a minimum, you should show all items that are less than the maximum price given. When submitted, the form should use the HTTP POST
method. If any inputs are invalid or cannot be parsed, you should substitute them with reasonable default values.
Your advanced search page should be accessible via the advancedsearch
route/URL. You should add a link to this URL to your site’s navigation.
You must use the same template for both the search form and displaying results. If the search form has been completed and submitted, the submitted values should be present in the form where the results are displayed. Likewise, if the form has not been completed or no results are present, the site should clearly present that information to the user.
Search Functions in Menu
The functions required to search and filter the menu should be implemented in the existing Menu
class as static methods. You should not perform any searching in the web application controller itself - it should simply call these methods as needed.
Some recommended functions you may wish to implement:
filterKeywords(Iterable<OrderItem> items, String keywords) - returns Iterable<OrderItem>
filterTypes(Iterable<OrderItem> items, boolean entree, boolean side, boolean drink, boolean combo) - returns Iterable<OrderItem>
- Alternatively, you could call the appropriate existing methods to collect these types initially before filtering
filterPrice(Iterable<OrderItem> items, float min, float max) - returns Iterable<OrderItem>
filterCalories(Iterable<OrderItem> items, int min, int max) - returns Iterable<OrderItem>
Each new method added to Menu
should include proper unit tests. You are encouraged to use test doubles (mocks, etc.) to test these methods rather than using actual menu items.
Time Requirements
Completing this project is estimated to require 2 - 5 hours.
A rough estimate for this milestone would be around 750 lines of new or updated code, the majority of which is HTML and unit tests. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Simple Search: 30%
- Keyword Search: 15%
- Results: 15%
- Advanced Search: 50%
- Types: 10%
- Price: 10%
- Calories: 10%
- Results: 20%
- Unit Tests: 20%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
RESTful Architecture
This page lists the milestone requirements for Milestone 10 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The tenth milestone involves building a RESTful web application that could be used to manage custom menu items.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings. - All HTML must conform to the HTML5 standard. Use the W3C Validator to check your rendered pages if desired.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone adds several pieces of functionality to your existing website, focused on managing custom menu items. First, you’ll need to add new classes to represent and store the custom items. Then, you’ll create a new web controller that follows a RESTful architecture to manage these custom items. While doing so, you’ll also create several templates to display the custom items on the web. Finally, you’ll update the UML diagram for your application to include the new web application classes.
New Classes
CustomItem Class
Create a class starfleetsubs.data.menu.CustomItem
that can represent a custom menu item. It should implement the OrderItem
interface, and should include both getters and setters for all required attributes. The class itself should only store the name, price, and calories of the item. It may simply return an empty list for special instructions. You may add additional utility methods as desired. You do not have to create any unit tests for this class.
CustomItemList Class
Create a class starfleetsubs.data.menu.CustomItemList
that represents a list of custom menu items. This class should implement both the Iterator design pattern (using the Iterable<CustomItem>
type), as well as the Singleton design pattern. This class is designed to keep a single list of custom items in memory for the entire application. We are using the singleton pattern so that it can be instantiated in the web controllers as needed, and it will always refer to the same list.
This class should maintain a list of CustomItem
objects, and provide methods for adding, retrieving, updating, and deleting those items. You may add additional utility methods as desired. You do not have to create any unit tests for this class.
In Java, you may wish to refer to the methods commonly used in the List interface. In Python, you may wish to refer to the methods in the MutableSequence abstract base class, which includes “dunder” methods __getitem__
, __setitem__
and __delitem__
, among others.
In the next milestone, we will add serialization capabilities to this class, which will allow us to maintain a list of custom items across many application executions.
Web Controller
Create a new web controller named CustomItemController
to handle these custom items. It should follow a RESTful architectural style. Specifically, it should include the following URL routes:
HTTP Method | URL Path | Description | CRUD Method |
---|---|---|---|
GET | /customitems |
Display all custom items. | Read All |
GET | /customitems/new |
Display a form to create a new item. | N/A |
POST | /customitems |
Create a new custom item | Create |
GET | /customitems/{id} |
Display a single custom item | Read One |
GET | /customitems/{id}/edit |
Display a form to edit the custom item | N/A |
POST | /customitems/{id} |
Update the custom item | Update |
GET | /customitems/{id}/delete |
Display a warning page before deleting an item | N/A |
POST | /customitems/{id}/delete |
Delete the custom item | Destroy |
More details about each page is included below. In these URLs, assume the {id}
is the index of the custom menu item in the CustomItemList
data structure.
Unlike an actual RESTful application, this application will NOT maintain the same identifier for an item indefinitely. For example, if there are three items in the list, and the second item is removed, the identifier for the third item will now be changed. This is because it is now at a different index in the CustomItemList
data structure, and because of this the URL to access that item will also change. However, since we are not using a relational database to store our data, this is a reasonable compromise that allows us to explore a RESTful architecture without the extra complexity of a database.
Since our application should also be following the HATEOAS model, the links on the index page should be updated as soon as it is reloaded in the browser. So, we’ll still be able to interact with our application, but it will only work well with just a single tab open. Otherwise, any deletions might cause unintended consequences.
Likewise, since browsers only natively support the HTTP GET and POST methods, we won’t be using PUT or DELETE here. Using those methods requires client-side JavaScript code, which is outside of the scope of this class.
Base Layout
Add a link to the /customitems
route to the navigation section of your site’s base layout template.
All Items
You are encouraged to reuse the content from your existing template for displaying all menu items here. Each menu item should include a link to the /customitems/{id}
route for that item.
Single Item
This is a new page, but it can also reuse content from the existing template for menu items - just remove the loop! This page should include links to the /customitems/{id}/edit
and /customitems/{id}/delete
routes, as well as a link to the main /customitems
route.
New Item / Edit Item
You’ll need to create a form that can be used for creating new items or editing existing items. Much of the template code is reused, and there are ways to use the same template for both routes. You may include additional HTML attributes on the HTML form to add limits to the numerical values. However, your web application may assume that data submitted matches the expected format. We will handle validation of form data in the next milestone.
Python users are encouraged to use Flask-WTF to create a special class for representing the form, as demonstrated in the example video. This will make the next milestone much simpler.
Unfortunately, there is not something similar for Java users, but the Spring framework already includes parts that make the next milestone very simple with the existing code, only with slight modifications.
Delete Item
This page is a copy of the single item page, but with additional warnings about deleting the item. This page should have a form that uses the HTTP POST method to submit to the same URL. When submitted, it should delete the item from the list.
For the user, the process to delete an item should follow this pattern:
/customitems
- find the item to delete and click the link to see details./customitems/{id}
- click the delete link to delete the item./customitems/{id}/delete
- see a warning page about deleting, and click the delete link again./customitems/{id}/delete
- browser sends a POST request to this URL to delete the item (this is invisible to the user)/customitems
- browser is redirected back to the main page
Update UML Diagram
At the end of this project, you should update the UML diagram for the project to include the new web application classes. You may choose to make multiple diagrams showing more detail within each package, and a summary diagram showing the relationships between the packages.
Time Requirements
Completing this project is estimated to require 2 - 5 hours.
A rough estimate for this milestone would be around 500 lines of new or updated code. The new controller and new classes are under 100 lines each. However, the small amount of code required involves some complexity to make everything function properly. There are many moving pieces to this milestone, but they are all pretty simple to put together. Try to reuse existing template resources whenever possible, and get a small portion working before starting on the next. It is simplest to start with creating a new custom item, displaying the entire list, and displaying a single item. From there, most of those parts can be reused to build the rest of the application. -Russ
Grading Rubric
This assignment will be graded based on the rubric below:
CustomItem
class - 10%CustomItemList
class - 20%- REST Controller & Templates - 60%
- Create New - 15%
- Read All - 10%
- Read One - 10%
- Update - 15%
- Destroy - 10%
- UML Diagram Updates - 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.
Validation & Serialization
This page lists the milestone requirements for Milestone 11 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
Purpose
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Starfleet Subs, based in the Star Trek universe.
The eleventh milestone involves adding form validation and serialization to the existing project, specifically targeted at custom menu items.
General Requirements
This milestone must follow these professional coding standards:
- All code must be object-oriented.
- All executable code must be within a class
- Python package files such as
__init__.py
and__main__.py
are exempt.
- Python package files such as
- Classes must be organized into packages based on common usage.
- All executable code must be within a class
- This project must include automation for compilation, unit testing, style checking, documentation generation, and execution.
- Java: Use Gradle with the
application
plugin. The project should compile without errors. - Python: Use tox configured to use Python 3.6 and a requirements file to install libraries.
- Java: Use Gradle with the
- All code must properly compile or be interpreted.
- Java: It must compile using Gradle.
- Python: It must be interpreted using Python 3.6. Where specified, type hints should be included in the code, and all code should pass a strict Mypy type check with low imprecision percentage.
- Classes in the
starfleetsubs.gui
package do not require type hints in Python, though you may continue to use them if they are helpful. Any errors from Mypy originating in these classes will be ignored.
- Classes in the
- Where specified, code should contain appropriate unit tests that achieve the specified level of code coverage.
- Java: Use JUnit 5. You may choose to use Hamcrest for assertions.
- Python: Use pytest. You may choose to use Hamcrest for assertions.
- Where specified, code should contain appropriate documentation comments following the language’s style guide.
- Java: Use javadoc to generate documentation.
- Python: Use pdoc3 to generate documentation.
- All code submitted must be free of style errors. We will be using the Google Style Guide for each language.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- You may modify the configuration to allow 4 space indentations instead of 2 space indentations.
- Python: Use Flake8 with the
flake8-docstrings
andpep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings. - All HTML must conform to the HTML5 standard. Use the W3C Validator to check your rendered pages if desired.
- Java: Use Checkstyle 8.38+ and the Google Style Configuration.
- Submissions to Canvas should be tagged GitHub releases that are numbered according to Semantic Versioning.
Assignment Requirements
This milestone consists of two portions: adding form validation to the forms for creating and editing custom items, and serializing those custom items to a file.
Form Validation
Update the forms for creating and editing custom menu items to perform server-side validation. This should use the built-in features of either Java Spring or Python Flask, as demonstrated in the example video. The following validation rules should be enforced:
- The
name
of the custom menu item should not be null, and have at least 3 characters. - The
price
of the custom menu item must be greater than or equal to 0, and support no more than 2 decimal places. You may either use a validator for this or implement rounding in the setter for this item. - The
calories
of the custom menu item must be greater than or equal to 0.
When validation fails, the user should be taken back to the form, where the entered values are still present and the validation errors are clearly displayed.
Java developers will need to change the price
attribute to use the BigDecimal
class (Javadoc) in order to enforce a limit on the number of digits using a validator. I recommend maintaining the existing getter and setters for price
(adapting them to use the value in the new BigDecimal
class) and then adding new getters and setters for this attribute. Likewise, in the HTML form, you’ll use the new BigDecimal
attribute instead of the existing price
. See the example video for details.
Serialization
Update the application to use serialization to store and load the list of custom items. You may choose any file format (XML, JSON, or binary, or another of your choosing). See the serialization examples on GitHub (Java or Python) as well as the textbook for code you can use.
- The custom menu items should be loaded into memory when the singleton instance of the
CustomItemList
class is created. In Java, this would most likely be thegetInstance()
method, while in Python it would be in the__new__()
method. So, when the user first visits the/customitems
page, the previously saved custom items should appear. - The
CustomItemList
class should implement a new method calledsave
that will serialize the current contents of the custom item list to a file. - The application should add a new HTTP POST route to the
CustomItemController
with the path/customitems/save
that will save the existing custom items list to file by calling the newsave
method. - Add an HTML form to the
/customitems
index page containing a button to save the custom items by sending a POST request to the new route. This form will be very similar to the one used on the page for deleting items.
The code should include proper exception handling when reading and writing files, as well as ensuring the file is properly closed. In Java, a try with resources statement is recommended. In Python, a with inside a try structure is recommended. You may simply catch the generic exception and print it to the terminal instead of handling multiple exception types.
As proof of working serialization, create the following custom menu item and serialize it to a file, then ensure that file is committed to your Git repository when committing this project.
- Name: The Roddenberry
- Price: 8.19
- Calories: 1921
Time Requirements
Completing this project is estimated to require 2 - 5 hours.
A rough estimate for this milestone would be around 100 lines of new or updated code.-Russ
Grading Rubric
This assignment will be graded based on the rubric below:
- Validation: 30%
- Name: 10%
- Price: 10%
- Calories: 10%
- Serialization: 70%
- Save: 30%
- Load: 30%
- Preloaded Entry “The Roddenberry”: 10%
The following deductions apply:
- Any portion of the project which will not compile (Java), pass a strict type check (Python), or execute properly will be given a grade of 0.
This is not an exhaustive list of possible deductions. The instructors will strive to provide reasonable and fair grading, but we can’t predict all possible defects. It is up to the student to ensure that the project is complete and correct before submission.
Submission
Submit this assignment by creating a release on GitHub and uploading the release URL to the assignment on Canvas. You should not submit this Codio project or mark it as complete in Codio, in case you need to come back to it and make changes later.