Previous Semesters
Previous Semesters
Previous Semesters
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.
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.
All projects must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
, jacoco
, and checkstyle
plugins.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.A complete final project should include the following features:
As of January 2021, this list is subject to change as the course progresses, depending on how far into the content we get. - Russ
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.
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.
README
file that describes your project, including how to compile and run it.README
file as well.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.
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.
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.
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.
All projects must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
, jacoco
, and checkstyle
plugins.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This project should include the following features:
HelloWorld
class that contains a main
method.
main
method should print “Hello World” if no command line arguments are received.main
method should print “Hello {arg}” if a command line argument is received.HelloWorld
class, properly testing both with and without command-line arguments..py
files should also include a file docstring, including __init__.py
and __main__.py
files for packages.HelloWorld
class must include explicit data types
HelloWorld
class must not use Any
as a type.Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%The following deductions apply:
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.
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.
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.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.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.
ClassName
, methods and attributes start with lowercase like methodName
. See the Google Style Guide.method_name
, with the exception of classes, which are named in CamelCase starting with an uppercase letter like ClassName
. 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!
flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone should include the following features:
starfleetsubs.data.entrees
packagestarfleetsubs.data.sides
packagestarfleetsubs.data.drinks
packagestarfleetsubs.data.enums
packageSee 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
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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):
price
attribute would have a getPrice
getter and setPrice
setter method.__price
attribute would have a getter and setter named price
implemented as a Python Property.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
value (see below). It should have a getter and setter method.Condiment
values (see below).
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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.
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.
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.
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 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.
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.
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
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.
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
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.
double
or Python float
value.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.
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.
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.
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.
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.
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
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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.
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 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.
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.
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.
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.
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.
an upper deck and a lower deck is important for any sub
starfleetsubs.data.enums.Bread
- White Bread, Wheat Bread, Sourdough Bread
options to fit any appetite
starfleetsubs.data.enums.Size
- Small, Medium, Large
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!
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.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.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.
ClassName
, methods and attributes start with lowercase like methodName
. See the Google Style Guide.method_name
, with the exception of classes, which are named in CamelCase starting with an uppercase letter like ClassName
. 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!
flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone should include the following features:
test
directory for the class it is testing.src
directory.java
or python
folder).Some quick tips from when I did this milestone:
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.ham
or lemon
) 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.@pytest.mark.parametrize("bread", Bread)
.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
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Each entrée test class should contain unit tests for the following:
SpecialInstructionsInitiallyEmpty()
- the SpecialInstructions
list should be empty when the object is createdHasCorrectBreadInitially()
- the Bread
attribute is initially set correctlyHasCorrectPrice()
- the price
is correctHasCorrectCalories()
- the calories
is correctNameIsCorrectForBread(Bread)
- call the toString()
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.
boolean
value indicating if the condiment should be included by default.AddRemoveCondiments(Condiment)
- for each condiment, check that it can be added and removed, and the Condiments
set will change accordingly.Has<Ingredient>ByDefault()
- for each ingredient, check to see that it is included by default (returns true).
TheKirk
would have a test method HasHamByDefault()
.Change<Ingredient>SetsSpecialInstructions()
- for each ingredient, check that changing it from and to the default value will add and remove the correct item from the SpecialInstructions
list.
TheKirk
would have ChangeHamSetsSpecialInstructions()
that would confirm setting ham
to false
would add "Hold Ham"
to the list of SpecialInstructions
.ChangeMultipleIngredientSpecialInstructions()
- confirm that changing multiple ingredients from their default values will add multiple items to the SpecialInstructions
list.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentBreadNotEqual()
- generate two different instances of the item using different bread, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentIngredientsNotEqual()
- generate two different instances of the item using different sets of ingredients, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentCondimentsNotEqual()
- generate two different instances of the item using different sets of condiments, and confirm that they are not equal using equals()
(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 using equals()
(Java) or --
(Python). This should not throw an exception.Each side test class should contain unit tests for the following:
DefaultSizeCorrect()
- each side should have the default size of Small
when initially created.HasCorrectNameForSize(Size)
- call the toString()
or __str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- the price
is correct for each sizeHasCorrectCaloriesForSize(Size)
- the calories
is correct for each sizeSameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal using equals()
(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 using equals()
(Java) or --
(Python). This should not throw an exception.Each drink test class should contain unit tests for the following:
SpecialInstructionsInitiallyEmpty()
- the SpecialInstructions
list should be empty when the object is createdDefaultSizeCorrect()
- each drink should have the default size of Small
when initially created.HasCorrectNameForSize(Size)
- call the toString()
or __str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- the price
is correct for each sizeHasCorrectCaloriesForSize(Size)
- the calories
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 method HasLemonByDefault()
.DoesNotHave<Ingredient>ByDefault()
- for each optional ingredient not included by default, check to see that it is not included (returns false).
ThePicard
would have a test method DoesNotHaveIceByDefault()
.Change<Ingredient>SetsSpecialInstructions()
- for each ingredient, check that changing it from and to the default value will add and remove the correct item from the SpecialInstructions
list.
ThePicard
would have ChangeIceSetsSpecialInstructions()
that would confirm setting ice
to true
would add "Add Ice"
to the list of SpecialInstructions
.ChangeMultipleIngredientSpecialInstructions()
- confirm that changing multiple ingredients from their default values will add multiple items to the SpecialInstructions
list.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentIngredientsNotEqual()
- generate two different instances of the item using different sets of ingredients, and confirm that they are not equal using equals()
(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 using equals()
(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!
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.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone should include the following features:
starfleetsubs.data.menu.OrderItem
interface that is implemented by all entrée, side, and drink classes
starfleetsubs.data.entrees.Entree
base classstarfleetsubs.data.sides.Side
base classstarfleetsubs.data.drinks.Drink
base classstarfleetsubs.data.menu.Menu
that contains the full menu
Menu
class should containOrderItem
interfaceMenu
and OrderItem
should report near 100% code coverage.Menu
to confirm that each possible menu item is present in the menu.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
This assignment will be graded based on the rubric below:
OrderItem
Interface - 25%Entree
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%Menu
Class - 20%Menu
Unit Tests - 10%The following deductions apply:
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.
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.
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:
Each menu item (entrées, sides, and drinks) should be refactored to implement this interface. This will require some changes:
Entree
base class.Side
base class.Accordingly, the unit tests for some of these classes will need updated, as discussed below.
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:
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:
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:
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.
The starfleetsubs.data.menu.Menu
class should be a class that has static getter methods for these four elements:
entrees
- a list of OrderItem
elements containing an instance of all available entrées (7 in total).sides
- a list of OrderItem
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 of OrderItem
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.
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Add:
InheritsFromEntree()
- check if a given object inherits from the base Entree
class.ImplementsOrderItem()
- check if a given object implements the interface OrderItem
.ChangeCondimentSetsSpecialInstructions(Condiment)
- for each condiment, check that changing it from and to the default value will add and remove the correct item from the SpecialInstructions
list.Update:
SpecialInstructionsInitiallyEmpty()
should be renamed SpecialInstructionsInitiallyCondiments()
and should now verify that the initial set of condiments is in the special instructions list.Add:
InheritsFromSide()
- check if a given object inherits from the base Side
class.ImplementsOrderItem()
- check if a given object implements the interface OrderItem
.SpecialInstructionsEmpty()
- check that the Special Instructions list is always empty.Add:
InheritsFromDrink()
- check if a given object inherits from the base Drink
class.ImplementsOrderItem()
- check if a given object implements the interface OrderItem
.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).
Create a new test class for the Menu
static class:
IncludesAllEntrees()
- test that the entrees
list contains an instance of each entrée classIncludesAllSides()
- test that the sides
list contains an instance of each side class for each sizeIncludesAllDrinks()
- test that the drinks
list contains an instance of each drink class for each sizeIncludesAllItems()
- test that the fullmenu
list contains an instance of every menu item.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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone should include the following features:
starfleetsubs.Main
class that properly loads and displays the program’s GUI.starfleetsubs.gui.MainWindow
class that represents the main GUI window.
starfleetsubs.gui.OrderPanel
class to represent the main order screen panel.
starfleetsubs.gui.SidebarPanel
class to represent the sidebar panel.
starfleetsubs.gui.entrees
package for each entrée item.
EntreePanel
class to reduce the amount of duplicate code.SidePanel
in the starfleetsubs.gui.sides
package.
Side
class. However, when buttons on the OrderPanel are clicked, you’ll need to make sure an instance of the correct item is generated.starfleetsubs.gui.drinks
package for each drink item.
DrinkPanel
class to reduce the amount of duplicate code.starfleetsubs.gui
package do not require unit tests.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.starfleetsubs.gui
package do require all appropriate documentation comments, and must be free of style errors.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.
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
This assignment will be graded based on the rubric below:
Main
class - 2%MainWindow
class - 4%SidebarPanel
class - 4%OrderPanel
class - 20%SidePanel
class - 5%The following deductions apply:
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.
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.
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
Here are a couple of helpful pieces of code that you may wish to use in your project.
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.
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!
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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone should include the following new GUI features:
SidebarPanel
panel.SidebarPanel
to a tree element (Java JTree
or tkinter Treeview
). 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.
SidebarPanel
, the following should happen:
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:
SidebarPanel
if it is a new item, or the item should be updated if it is being edited.MainWindow
should be replaced with the OrderScreen
(this was part of the previous milestone).MainWindow
should be replaced with the OrderScreen
(this was part of the previous milestone).SidebarPanel
is clicked, the following should happen:
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 the OrderItem
.MainWindow
and populated with the current status of the item (most of this should work from the previous milestone).SidebarPanel
is clicked, the following should happen:
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 the OrderItem
.SidebarPanel
class.Unit tests should be added to the corresponding test package for the following classes:
starfleetsubs.gui.entrees
starfleetsubs.gui.drinks
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:
starfleetsubs.gui
base package do not require unit tests, but all entrée, drink, and side panels require unit tests as outlined above.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.starfleetsubs.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors.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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
I found these methods helpful in my solution:
MainWindow.addItem(item)
- basically a pass-through method that calls the SidebarPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to the MainWindow
instance.SidebarPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.==
operator in Java, or the is
operator in Python. This means that you won’t be able to use the normal contains()
or in
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. If node
is null
or not provided, it creates a new one, otherwise it uses the existing node
and updates it. It should return the node
or that node’s id
when complete.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 the actionPerformed()
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 the bread
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 given bread
, 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 both true
and false
.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 both true
and false
.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 both true
and false
.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 both true
and false
.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.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 the actionPerformed()
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 the size
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 given size
, 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.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 the actionPerformed()
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 the size
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 given size
, 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 both true
and false
.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 both true
and false
.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.
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
DISPLAY
environment variable.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.reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.starfleetsubs.data.menu.Order
- this class should represent a collection of OrderItem
objects that make up an order.
size()
in Java or __len__()
in Python).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.get(i)
method in Java or __getitem__(i)
in Python).items
of OrderItems
, with methods to add and remove items, as well as the iterator pattern methods discussed above.
orderNumber
for this order. It will be generated using the OrderNumberSingleton
class discussed below. It should only include a getter.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 all Order
objects. The tax rate must be a valid percentage value ranging from 0.0 to 1.0, inclusive.subtotal
- the total sum of the prices for each item in the order.tax
- the subtotal
multiplied by the taxRate
total
- the subtotal
plus the tax
.calories
- the total number of calories in the order.starfleetsubs.data.menu.Combo
- this class should implement the OrderItem
interface, and represent a combo meal consisting of an entrée, side, and drink.
name
- the name of the combo, which does not require a getter (you may add one) or setter. This attribute can be set to null
or None
.Entree
named entree
- the entrée in the combo, which does not require a getter (you may add one) or setter. This attribute can be set to null
or None
. It should include a removeEntree()
method to set the value to null
or None
.Side
named side
- the side in the combo, which does not require a getter (you may add one) or setter. This attribute can be set to null
or None
. It should include a removeSide()
method to set the value to null
or None
.Drink
named drink
- the drink in the combo, which does not require a getter (you may add one) or setter. This attribute can be set to null
or None
. It should include a removeDrink()
method to set the value to null
or None
.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 all Combo
objects.OrderItem
interface:
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.calories
that returns the sum of the calories of each item.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 static discount
attribute.)name
. The constructor should allow the name to be omitted or set to null
or None
. The name
will only be set by the ComboBuilder
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 the entree
, side
and drink
attributes to null
or None
initially.addItem()
method that accepts an OrderItem
object and places it in the appropriate attribute (entree
, side
or drink
). It should replace the existing item in that attribute, if any. If the OrderItem
is not one of the three types listed above, it should throw an appropriate exception.getItems()
method that returns list of the items included in the combo, if any. If none are included, then return an empty list.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 is null
or None
, it is considered equal if the matching attribute is also null
or None
.
equals()
method on a null
object will result in an exception. So, you’ll have to check if each attribute in this object is null
first. If so, and the other object’s attribute is not null
, then they are not equal. If this object’s attribute is not null
, you can safely call equals()
on it, regardless of the other object’s attribute.starfleetsubs.data.menu.ComboBuilder
- a class that implements the Builder Pattern to build the available combos described below.
buildCombo()
that accepts an integer as input, and builds and returns the Combo
object indicated by the integer.starfleetsubs.data.menu.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
nextOrderNumber
attribute, which is initially set to 1getNextOrderNumber()
that will return the next order number.
getInstance()
method to get the actual singleton instance stored as a static attribute in the class.nextOrderNumber
attribute through that singleton instance.nextOrderNumber
attribute (a synchronized
statement in Java or a lock in a with
statement in Python).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.
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 the parent
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 the name
is not recognized, an exception should be thrown.getPanel(OrderItem item, MainWindow parent)
should accept an instance of an OrderItem
and return a panel that represents that item, with the parent
GUI element as its parent. If the item
is not recognized, an exception should be thrown.Combos
as OrderItems
. We’ll address that in the next milestone.Menu
- update to include the following items:
getCombos()
method that returns all pre-configured combos described below. This method should use the ComboBuilder
class discussed below.getFullMenu()
method to include the combos returned from getCombos()
in its output.OrderPanel
- update to include the following items:
actionPerformed
method should be updated to use the PanelFactory
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:
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree.Order
attribute that stores the items in the order.
SidebarPanel
constructor.Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.
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.
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
This assignment will be graded based on the rubric below:
Order
- 10%Combo
- 10%ComboBuilder
- 10%OrderNumberSingleton
- 5%PanelFactory
- 5%Order
- 15%Combo
- 15%ComboBuilder
- 5%OrderNumberSingleton
- 5%Menu
and unit tests: 5%OrderPanel
: 5%SidebarPanel
: 10%The following deductions apply:
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.
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.
The Kirk, Bones McCoy, Altair Water
The Riker, Data Chips, The Picard
The Janeway, Enterprise, The Guinan
The Gagh, Borg, The Worf
The Scotty, Enterprise, The Troi
The Q, Borg, The Picard
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.
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 the contains
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true when equals()
is called. Place one in the order, and use them to confirm that contains
returns both true and false when given two items that are equal but not the same instance.RemoveUsesInstanceComparison()
- confirm that the removeItem
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true when equals()
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 the Order
class is using OrderNumberSingleton
. Create a fake OrderNumberSingleton
that returns a value for an order number, then instantiate an Order
and verify that it received the given order number.TaxRateSetGlobally()
- create two Order
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 the tax
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.ConstructorSetsName()
- the constructor should set the name. This is visible as the first element in the special instructions list.ConstructorAcceptsNullName()
- the constructor should accept null
or None
for the name.ConstructorSetsItemsToNull()
- the constructor should set the entree, side, and drink elements to null
or None
.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 are null
or None
.CaloriesZeroNoItems()
- the calories should be 0 if all items are null
or None
.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 two Combo
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 an Entree
to the combo using addItem()
and verify that it is placed in the entree
attribute. You may need to make the attribute visible to the test.AddSideUpdatesSide()
- add a Side
to the combo using addItem()
and verify that it is placed in the side
attribute. You may need to make the attribute visible to the test.AddDrinkUpdatesDrink()
- add a Drink
to the combo using addItem()
and verify that it is placed in the drink
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 by getItems()
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 with null
or None
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 return false
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.
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 exceptionSequentialOrderNumbers
- call getNextOrderNumber()
several times and make sure each one is sequential.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:
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:
reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.It is best to think of this assignment as one consisting of two distinct parts.
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:
Combo
class should handle this as defined in the previous milestone.SidebarPanel
class will need to be updated to properly handle combos.
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:
MainWindow
class/type as its parent, we can abstract that to a ParentPanel
interface that is implemented by both the MainWindow
class and ComboPanel
. This allows the existing order item panels to use the new ComboPanel
as its parent.ComboPanel
ComboPanel
instead of MainWindow
)MainWindow
to add the item to the order.data
package as desired.PanelFactory
since it could be used from within ComboPanel
, but also will be used to create instances of ComboPanel
. A way to resolve this would be to create a ComboPanelFactory
to handle combos, and adapt the code where PanelFactory
is used to direct combo instances to the new ComboPanelFactory
instead.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:
Combo
object when it is saved.Combo
object when it is saved.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
.
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:
edu.ksu.cs.cc410.register
package.cc410.register
package.When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
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.
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.
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:
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).
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 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.
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
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:
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.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.
ReceiptPrinter
wrapper that accepts an Order
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect the Order
given to it.
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.Add a Web Framework to the existing project.
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.
starfleetsubs.web
package.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).
Menu
class to collect these items.Menu
class as desired.Create a base layout file including the following:
- Starfleet Subs
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:
menu-item
. It should include:
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Below is a screenshot from the model solution for some web design inspiration.
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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
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.
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:
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.
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>
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.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.
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.
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.
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.
Add a link to the /customitems
route to the navigation section of your site’s base layout template.
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.
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.
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.
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 pageAt 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.
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
This assignment will be graded based on the rubric below:
CustomItem
class - 10%CustomItemList
class - 20%The following deductions apply:
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.
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.
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.
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.
This milestone must follow these professional coding standards:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors.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.flake8-docstrings
and pep8-naming
plugins. Code should conform to PEP 8 style with Google style docstrings.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.
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:
name
of the custom menu item should not be null, and have at least 3 characters.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.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.
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.
CustomItemList
class is created. In Java, this would most likely be the getInstance()
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.CustomItemList
class should implement a new method called save
that will serialize the current contents of the custom item list to a file.CustomItemController
with the path /customitems/save
that will save the existing custom items list to file by calling the new save
method./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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
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.
A complete final project should include the following features:
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. This project should be roughly 1/4 to 1/3 the size and scope of the semester-long restaurant project.
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.
README
file that describes your project, including how to compile and run it.README
file as well.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 60%.
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.
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.
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.
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.
This project should include the following features:
HelloWorld
class that contains a main
method.
main
method should print “Hello World” if no command line arguments are received.main
method should print “Hello {arg}” if a command line argument is received.HelloWorld
class, properly testing both with and without command-line arguments..py
files should also include a file docstring, including __init__.py
and __main__.py
files for packages.HelloWorld
class must include explicit data types
HelloWorld
class must not use Any
as a type.Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%The following deductions apply:
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.
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
heropizza.data.pizzas
packageheropizza.data.sides
packageheropizza.data.drinks
packageheropizza.data.enums
packageSee the Hero Pizza 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
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 pizzas and start there. Once you have the pizzas all working, the sides and drinks are pretty easy and use much of the same structure. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
our motto: eat like a hero - choose pizza!
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):
price
attribute would have a getPrice
getter and setPrice
setter method.__price
attribute would have a getter and setter named price
implemented as a Python Property.Each pizza should be stored in an appropriately named class in the heropizza.data.pizzas
package. Each pizza should include an attribute for the following data:
Crust
value (see below). It should have a getter and setter method.Veggie
values (see below).
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.
double
or Python float
value representing the base price of the item plus any upcharge associated with the chosen Crust value.int
value representing the number of calories associated with the item.String
values or a Python list of str
values.
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 pizza class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the pizza. The string should be formatted as “{pizza name} on {crust} Crust”, such as “The Mikey on Thin Crust”.
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 pizza description will include a list of toppings included on the pizza. Those toppings 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 {topping}” message, such as “Hold Ham”, to be added to the Modifications list. Likewise, changing it back to true
will remove the appropriate message. If all toppings are at their default values, the Modifications list should be empty.
Each pizza will be served on Thin Crust by default, and will include a default set of Veggies. Those attributes should be populated appropriately in the constructor for the pizza. Changes to the Crust and Veggies attributes will not affect the Modifications attribute at this time (we’ll add that later).
The number of Calories for a pizza will remain constant, regardless of other attributes (we’ll just pretend that changing the pizza doesn’t change the number of calories).
The Price for a pizza will change based on the value selected for the Crust. Each pizza will have a base price listed for the Thin crust option. Other crusts include an associated upcharge, which must be added to the base price.
just like the turtle himself, this sandwich “hams” it up and is super “cheesy”
heropizza.data.pizzas.TheMikey
- The price is $8.25 and it is 986 calories. Toppings: Ham and Cheese. Veggies: Pineapple.
a simple pizza for a complex hero
heropizza.data.pizzas.TheJeanGrey
- The price is $10.25 and it is 850 calories. Toppings: Pork and Cheese. Veggies: Mushrooms, Red Onions, Black Olives, Green Peppers, Banana Peppers and Roma Tomatoes
all the meat for a carnivorous feast
heropizza.data.pizzas.TheWolverine
- The price is $9.35 and it is 950 calories. Toppings: Sausage, Bacon, Ham and Pork. Veggies: Red Onions and Green Peppers.
everyone “adora"s this classic
heropizza.data.pizzas.TheSheRa
- The price is $8.75 and it is 1325 calories. Toppings: Pepperoni and Cheese. Veggies: none.
a star studded treat that isn’t a hologram
heropizza.data.pizzas.TheJem
- The price is $9.65 and it is 1075 calories. Toppings: Chicken, BBQ Sauce and Bacon. Veggies: Red Onions
a pizza for a heroic appetite
heropizza.data.pizzas.TheHeMan
- The price is $18.95 and it is 1986 calories. Toppings: Ham, Sausage, Pepperoni, Bacon, Pork, and Cheese. Veggies: Mushrooms, Red Onions, Black Olives, Green Peppers, Banana Peppers and Jalapeno Peppers
by your powers combined
heropizza.data.pizzas.TheCaptainPlanet
- The price is $6.50 and it is 745 calories. Toppings: Cheese. Veggies: Mushrooms, Red Onions, Black Olives, Green Peppers, Banana Peppers, Jalapeno Peppers, Pineapple and Roma Tomatoes
Each side should be stored in an appropriately named class in the heropizza.data.sides
package. Each side should include an attribute for the following data:
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.
double
or Python float
value.int
value.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 Snarf Sticks”.
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
.
soft breadsticks with a chewy bite
heropizza.data.sides.SnarfSticks
- Small: $1.95 and 275 calories. Medium: $3.25 and 450 calories. Hero: $5.50 and **750 ** calories.
meatballs inspired by a famous hairdo
heropizza.data.sides.SailorMoon
- Small: $2.35 and 300 calories. Medium: $4.85 and 550 calories. Hero: $7.95 and 960 calories.
do you have what it takes to wield Thor’s hammer?
heropizza.data.sides.Mjolnir
- Small: $2.95 and 425 calories. Medium: $4.65 and 595 calories. Hero: $6.95 and 840 calories.
Batman’s trusty snack
heropizza.data.sides.Batwings
- Small: $3.25 and 525 calories. Medium: $5.25 and 765 calories. Hero: $6.55 and 905 calories.
Each drink should be stored in an appropriately named class in the heropizza.data.drinks
package. Each drink should include an attribute for the following data:
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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 Katara”.
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 flavors that may be added. Those flavors 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 {flavor}” message, such as “Add Cherry”, to be added to the Modifications list. Likewise, changing it back to false
will remove the appropriate message.
In addition, drinks may specify default flavors that 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 {flavor}” message, such as “Hold Coconut”, to be added to the Modifications list. Likewise, changing it back to true
will remove the appropriate message.
If all flavors are at their default values, the Modifications list should be empty.
Each side description will include a Price and number of Calories for each Size. The sides will have a default size of Small
. Changes to the Size attribute will not affect the Modification attribute.
a titan of a drink
heropizza.data.drinks.Starfire
- Flavors: Cherry (default), Vanilla, Orange and Grape. Small: $1.40 and 170 calories. Medium: $3.75 and 255 calories. Hero: $4.75 and 375 calories.
a tasty drink made from strong roots
heropizza.data.drinks.Groot
- Flavors: Caramel, Cinnamon, and Anise. Small: $3.55 and 320 calories. Medium: $4.45 and 435 calories. Hero: $5.05 and 540 calories.
a smooth drink to sooth a warrior’s spirit
heropizza.data.drinks.SamuraiJack
- Flavors: Jackfruit (default), Banana, Mango and Strawberry. Small: $4.25 and 650 calories. Medium: $6.75 and 825 calories. Hero: $9.55 and 1115 calories.
a “powerpuff” of a drink with sugar and spice
heropizza.data.drinks.Bubbles
- Flavors: Lychee, Passion Fruit, and Matcha. Small: $3.40 and 350 calories. Medium: $4.45 and 425 calories. Hero: $5.65 and 695 calories.
a simple water drink for an extraordinary water bender
heropizza.data.drinks.Katara
- Flavors: Lemon and Coconut. All sizes are $1.00 and 0 calories.
Each enumeration should be stored in an appropriately named class in the heropizza.data.enums
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.
a solid base for a trustworthy pizza slice
heropizza.data.enums.Crust
- Thin, Hand Tossed (add $0.50), Deep Dish (add $1.00), Cheese Stuffed (add $2.00)
It is possible to create an enumeration that also stores additional data associated with each value, and then access that data through the enum value. You may be able to use this to simplify handling the upcharge for each crust type. Below are links to some sample code from later in this course that shows how to create such an enum and use that data.
options to fit any heroic appetite
heropizza.data.enums.Size
- Small, Medium, Hero
an important part of a balanced meal
heropizza.data.enums.Veggie
- Mushrooms, Red Onions, Black Olives, Green Peppers, Banana Peppers, Jalapeno Peppers, Pineapple, Roma Tomatoes
Special thanks to friends and family for inspiration and menu suggestions!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
test
directory for the class it is testing.src
directory.java
or python
folder).Some quick tips from when I did this milestone:
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 pizza 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.ham
or cherry
) 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.@pytest.mark.parametrize("crust", Crust)
.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
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 pizzas and start there writing unit tests. Once you have the pizzas all working, the sides and drinks are pretty easy and use much of the same structure. There are several hundred 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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Each entrée test class should contain unit tests for the following:
ModificationsInitiallyEmpty()
- the Modifications
list should be empty when the object is createdHasCorrectCrustInitially()
- the Crust
attribute is initially set correctlyHasCorrectPriceForCrust(Crust)
- the price
is correct for each crust optionHasCorrectCalories()
- the calories
is correctStringIsCorrectForCrust(Crust)
- call the toString()
or __str__()
method with each type of crust and verify the output.IncludesCorrectVeggiesByDefault(Veggie)
- for each veggie, check if it is included or not by default.
boolean
value indicating if the veggie should be included by default.AddRemoveVeggies(Veggie)
- for each veggie, check that it can be added and removed, and the Veggies
set will change accordingly.Has<Topping>ByDefault()
- for each topping, check to see that it is included by default (returns true).
TheMikey
would have a test method HasHamByDefault()
.Change<Topping>SetsModifications()
- for each topping, check that changing it from and to the default value will add and remove the correct item from the Modifications
list.
TheMikey
would have ChangeHamSetsSpecialInstructions()
that would confirm setting ham
to false
would add "Hold Ham"
to the list of Modifications
.ChangeMultipleToppingsModifications()
- confirm that changing multiple toppings from their default values will add multiple items to the Modifications
list.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentCrustNotEqual()
- generate two different instances of the item using different crust, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentToppingsNotEqual()
- generate two different instances of the item using different sets of toppings, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentVeggiesNotEqual()
- generate two different instances of the item using different sets of veggies, and confirm that they are not equal using equals()
(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 using equals()
(Java) or ==
(Python). This should not throw an exception.Each side test class should contain unit tests for the following:
DefaultSizeCorrect()
- each side should have the default size of Small
when initially created.StringIsCorrectForSize(Size)
- call the toString()
or __str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- the price
is correct for each sizeHasCorrectCaloriesForSize(Size)
- the calories
is correct for each sizeSameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal using equals()
(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 using equals()
(Java) or --
(Python). This should not throw an exception.Each drink test class should contain unit tests for the following:
ModificationsInitiallyEmpty()
- the Modifications
list should be empty when the object is createdDefaultSizeCorrect()
- each drink should have the default size of Small
when initially created.StringIsCorrectForSize(Size)
- call the toString()
or __str__()
method with each size and verify the output.HasCorrectPriceForSize(Size)
- the price
is correct for each sizeHasCorrectCaloriesForSize(Size)
- the calories
is correct for each sizeHas<Flavor>ByDefault()
- for each flavor included by default, check to see that it is included (returns true). For example, Starfire
would have a test method HasCherryByDefault()
.DoesNotHave<Flavor>ByDefault()
- for each optional flavor not included by default, check to see that it is not included (returns false).
Starfire
would have a test method DoesNotHaveVanillaByDefault()
.Change<Flavor>SetsModifications()
- for each flavor, check that changing it from and to the default value will add and remove the correct item from the Modifications
list.
Starfire
would have ChangeCherrySetsModifications()
that would confirm setting cherry
to false
would add "Hold Cherry"
to the list of Modifications
.ChangeMultipleFlavorsModifications()
- confirm that changing multiple flavors from their default values will add multiple items to the Modifications
list.
SameObjectsAreEqual()
- generate two different instances of the item, and confirm that they are equal using equals()
(Java) or ==
(Python).DifferentSizeNotEqual()
- generate two different instances of the item using different sizes, and confirm that they are not equal using equals()
(Java) or ==
(Python).DifferentFlavorsNotEqual()
- generate two different instances of the item using different sets of flavors, and confirm that they are not equal using equals()
(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 using equals()
(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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
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 should include the following features:
heropizza.data.menu.Food
interface that is implemented by all pizza, side, and drink classes
heropizza.data.pizzas.Pizza
base classheropizza.data.sides.Side
base classheropizza.data.drinks.Drink
base classheropizza.data.menu.Menu
that contains the full menu
Menu
class should containFood
interfaceMenu
and Food
should report near 100% code coverage.Menu
to confirm that each possible menu item is present in the menu.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 about 100 more unit tests in total. -Russ
This assignment will be graded based on the rubric below:
Food
Interface - 25%pizza
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%Menu
Class - 20%Menu
Unit Tests - 10%The following deductions apply:
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.
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.
The heropizza.data.menu.Food
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:
Each menu item (pizza, sides, and drinks) should be refactored to implement this interface. This will require some changes:
Pizza
base class.Side
base class.Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
heropizza.data.pizzas.Pizza
is the base class for all pizza items. It should include the following elements that are common to all pizza classes:
heropizza.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:
heropizza.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:
You may choose to implement the Food
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 Food
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 Food
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.
The heropizza.data.menu.Menu
class should be a class that has static getter methods for these four elements:
pizzas
- a list of Food
elements containing an instance of all available pizzas (7 in total).sides
- a list of Food
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 of Food
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.
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Add:
InheritsFromPizza()
- check if a given object inherits from the base Pizza
class.ImplementsFood()
- check if a given object implements the interface Food
.ChangeVeggieSetsModifications(Veggie)
- for each veggie, check that changing it from and to the default value will add and remove the correct item from the Modifications
list.Update:
ModificationsInitiallyEmpty()
should be renamed ModificationsInitiallyVeggies()
and should now verify that the initial set of veggies is in the modifications list.Add:
InheritsFromSide()
- check if a given object inherits from the base Side
class.ImplementsFood()
- check if a given object implements the interface Food
.ModificationsEmpty()
- check that the Modifications list is always empty.Add:
InheritsFromDrink()
- check if a given object inherits from the base Drink
class.ImplementsFood()
- check if a given object implements the interface Food
.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).
Create a new test class for the Menu
static class:
IncludesAllPizzas()
- test that the pizzas
list contains an instance of each pizza classIncludesAllSides()
- test that the sides
list contains an instance of each side class for each sizeIncludesAllDrinks()
- test that the drinks
list contains an instance of each drink class for each sizeIncludesAllItems()
- test that the fullmenu
list contains an instance of every menu item.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
This milestone should include the following features:
heropizza.Main
class that properly loads and displays the program’s GUI.heropizza.gui.MainWindow
class that represents the main GUI window.
heropizza.gui.OrderPanel
class to represent the main order screen panel.
heropizza.gui.SidebarPanel
class to represent the sidebar panel.
heropizza.gui.pizzas
package for each pizza.
PizzaPanel
class to reduce the amount of duplicate code.SidePanel
in the heropizza.gui.sides
package.
Side
class. However, when buttons on the OrderPanel are clicked, you’ll need to make sure an instance of the correct item is generated.heropizza.gui.drinks
package for each drink item.
DrinkPanel
class to reduce the amount of duplicate code.heropizza.gui
package do not require unit tests.heropizza.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.heropizza.gui
package do require all appropriate documentation comments, and must be free of style errors.You are welcome to add additional methods to the existing content in the heropizza.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.
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
This assignment will be graded based on the rubric below:
Main
class - 2%MainWindow
class - 4%SidebarPanel
class - 4%OrderPanel
class - 20%SidePanel
class - 5%The following deductions apply:
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.
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.
Below are some GUI sketches to help you visualize one possible GUI for a previous version of 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
Here are a couple of helpful pieces of code that you may wish to use in your project.
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 pizza 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.
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 pizza 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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
The fifth milestone involves dealing with the various events generated by the GUI and constructing a list of items that represent an order.
Changes to the previous milestone:
SidebarPanel
panel.SidebarPanel
to a tree element (Java JTree
or tkinter Treeview
). 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:
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 Food
instances that they represent.
In addition, the following events should be implemented in the GUI:
When the Save button in any of the pizza, side, or drink panels is clicked, the following should happen:
SidebarPanel
if it is a new item, or the item should be updated if it is being edited.MainWindow
should be replaced with the OrderPanel
(this was part of the previous milestone).When the Cancel button in any of the pizza, side, or drink panels is clicked, the following should happen:
MainWindow
should be replaced with the OrderPanel
(this was part of the previous milestone for the Save button, and the code is similar).When the Edit button in the SidebarPanel
is clicked, the following should happen:
Food
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Food
.MainWindow
and populated with the current status of the item (most of this should be present from the previous milestone, but much of it may be untested at this point).When the Delete button in the SidebarPanel
is clicked, the following should happen:
Food
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Food
.SidebarPanel
class.Unit tests should be added to the corresponding test package for the following classes:
heropizza.gui.pizzas
heropizza.gui.drinks
heropizza.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._s
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:
heropizza.gui
base package do not require unit tests, but all pizza, drink, and side panels require unit tests as outlined above.heropizza.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.heropizza.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors.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 one of the more complex pizza panels, and I used that as a template to create the rest of the unit tests. My current model solution contains ~850 unit tests, and I was able to achieve 100% code coverage on all GUI Food
panels. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
I found these methods helpful in my solution:
MainWindow.addItem(item)
- basically a pass-through method that calls the SidebarPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to the MainWindow
instance.SidebarPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.==
operator in Java, or the is
operator in Python. This means that you won’t be able to use the normal contains()
or in
method for determining if the item is already in a list - you must iterate through the list manually.SidebarPanel.updateTree(item, node)
- handles actually updating the tree. If node
is null
or not provided, it creates a new one, otherwise it uses the existing node
and updates it. It should return the node
or that node’s id
when complete.Each pizza 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 the actionPerformed()
method with a bad action command, and assert that an exception is not thrown.testCrustComboBox(Crust)
- instantiate a panel with an existing item, change the value of the crust combo box in the GUI to the crust
value, and fire a “save” action, then verify that the item has the correct crust value.testCrustComboBoxSetCorrectly(Crust)
- instantiate a panel with an existing item using the given crust
, and assert that the crust 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 both true
and false
.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 both true
and false
.testToppingCheckBox(Topping)
- instantiate a panel with an existing item, change the value of the topping 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 both true
and false
.testToppingCheckBoxSetCorrectly(Topping)
- instantiate a panel with an existing item with a given value for topping, and assert that the topping checkbox is set to the correct value. Do this for both true
and false
.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.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 the actionPerformed()
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 the size
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 given size
, 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.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 the actionPerformed()
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 the size
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 given size
, 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 both true
and false
.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 both true
and false
.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.
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
DISPLAY
environment variable.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/heropizza/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas --html=reports/pytest-pizzas/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/drinks test/heropizza/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.reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
heropizza.data.menu.Order
- this class should represent a collection of Food
objects that make up an order.
Food
object is contained in the collection. Recall that this should use the identity test, not the equality test.Foods
, with methods to add and remove items.
OrderNumberSingleton
class discussed below. It should only include a getter.Order
objects.heropizza.data.menu.Combo
- this class should implement the Food
interface, and represent a combo meal consisting of an pizza, two sides, and drink.
Pizza
instance - the pizza in the comboSide
instances - the sides in the comboDrink
instance - the drink in the combonull
or None
in the constructor to represent a combo yet to be configured.null
or None
. You may have a single method, or one for each attribute.Food
interface:
null
or None
. The name will only be set by the ComboBuilder
class discussed below, but users will also be able to configure a custom combo via the GUI that does not include a name.null
or None
initially.null
or None
, it is considered equal if the matching attribute is also null
or None
.
equals()
method on a null
object will result in an exception. So, you’ll have to check if each attribute in this object is null
first. If so, and the other object’s attribute is not null
, then they are not equal. If this object’s attribute is not null
, you can safely call equals()
on it, regardless of the other object’s attribute.heropizza.data.menu.ComboBuilder
- a class that implements the Builder Pattern to build the available combos described below.
Combo
object indicated by the integer.heropizza.data.menu.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
synchronized
statement in Java or a lock in a with
statement in Python).heropizza.gui.PanelFactory
- a class that implements the Factory Method Pattern to return an instance of a GUI panel for a given pizza, side, or drink.
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 the parent
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 the name
is not recognized, an exception should be thrown.Food
item, MainWindow
parent) should accept an instance of an Food
and return a panel that represents that item, with the parent
GUI element as its parent. If the item
is not recognized, an exception should be thrown.Combos
as Foods
. We’ll address that in the next milestone.Menu
- update to include the following items:
ComboBuilder
class discussed below.OrderPanel
- update to include the following items:
PanelFactory
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:
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree.Order
instance as well.
SidebarPanel
constructor.Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.
All new and updated classes in this milestone should contain full documentation comments.
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:
heropizza.data.*
heropizza.gui.drinks.*
heropizza.gui.pizzas.*
heropizza.gui.sides.*
The only classes that do not meet this requirement are MainWindow
, OrderPanel
, PanelFactory
, and SidebarPanel
in the heropizza.gui
package.
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
This assignment will be graded based on the rubric below:
Order
- 10%Combo
- 10%ComboBuilder
- 10%OrderNumberSingleton
- 5%PanelFactory
- 5%Order
- 15%Combo
- 15%ComboBuilder
- 5%OrderNumberSingleton
- 5%Menu
and unit tests: 5%OrderPanel
: 5%SidebarPanel
: 10%The following deductions apply:
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.
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.
The Mikey, Snarf Sticks, Mjolnir, Starfire
The Wolverine, Batwings, Sailor Moon, Groot
The He-Man, Snarf Sticks, Sailor Moon, Samurai Jack
The Jem, Sailor Moon, Batwings, Bubbles
The Captain Planet, Snarf Sticks, Mjolnir, Katara
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.
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 a few fake items one at a time and check size after each one.AddItemsUpdatesTotals()
- add a few fake items one at a time and check subtotal, tax, and total after each one.AddItemsUpdatesCalories()
- add a few fake items one at a time and check calories after each one.ContainsUsesInstanceComparison()
- confirm that the contains
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true when equals()
is called. Place one in the order, and use them to confirm that contains
returns both true and false when given two items that are equal but not the same instance.RemoveUsesInstanceComparison()
- confirm that the remove
method uses instance comparison. Create two actual order items (this cannot be done with fakes) that will return true when equals()
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 the Order
class is using OrderNumberSingleton
. Create a fake OrderNumberSingleton
that returns a value for an order number, then instantiate an Order
and verify that it received the given order number.TaxRateSetGlobally()
- create two Order
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 the tax
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.ConstructorSetsName()
- the constructor should set the name.ConstructorAcceptsNullName()
- the constructor should accept null
or None
for the name.ConstructorSetsItemsToNull()
- the constructor should set the pizza, sides, and drink elements to null
or None
.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 are null
or None
.CaloriesZeroNoItems()
- the calories should be 0 if all items are null
or None
.PriceAllItems()
- add fake items to combo and verify that the price is summed correctly (remember to take off the discount).CaloriesAllItems()
- add fake items to combo and verify that the calories is summed correctly.NoDiscountWhenItemMissing()
- add up to three items to the combo and verify that the price is correct and does not include discount.DiscountSetGlobally()
- create two Combo
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.ItemsListCorrect()
- add fake items to the combo and verify that the list returned by items getter contains those items.ItemsListEmpty()
- getting a list when the combo is empty results in an empty list.ModificationsHasDiscount()
- modifications list should include a discount message if all combo 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 with null
or None
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 return false
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.
For these tests, I recommend just checking the types of the pizza, sides, and drink items 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 correctlyBadComboThrowsException()
- a bad combo number should throw an exceptionSequentialOrderNumbers
- call getNextOrderNumber()
several times and make sure each one is sequential.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:
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/heropizza/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheMikeyPanel.py --html=reports/pytest-pizzas1/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheJeanGreyPanel.py --html=reports/pytest-pizzas2/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheWolverinePanel.py --html=reports/pytest-pizzas3/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheSheRaPanel.py --html=reports/pytest-pizzas4/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheJemPanel.py --html=reports/pytest-pizzas5/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheHeManPanel.py --html=reports/pytest-pizzas6/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/pizzas/test_TheCaptainPlanetPanel.py --html=reports/pytest-pizzas7/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/heropizza/gui/drinks test/heropizza/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:
reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
It is best to think of this assignment as one consisting of two distinct parts.
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:
Combo
class should handle this as defined in the previous milestone.SidebarPanel
class will need to be updated to properly handle combos.
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:
MainWindow
class/type as its parent, we can abstract that to a ParentPanel
interface that is implemented by both the MainWindow
class and ComboPanel
. This allows the existing order item panels to use the new ComboPanel
as its parent.ComboPanel
ComboPanel
instead of MainWindow
)MainWindow
to add the item to the order.data
package as desired.PanelFactory
since it could be used from within ComboPanel
, but also will be used to create instances of ComboPanel
. A way to resolve this would be to create a ComboPanelFactory
to handle combos, and adapt the code where PanelFactory
is used to direct combo instances to the new ComboPanelFactory
instead.All new and updated classes in this milestone should contain full documentation comments.
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:
Combo
object when it is saved.Combo
object when it is saved.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
.
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:
edu.ksu.cs.cc410.register
package.cc410.register
package.When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
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.
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.
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:
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).
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 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.
All new and updated classes in this milestone should contain full documentation comments.
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
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:
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.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.
ReceiptPrinter
wrapper that accepts an Order
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect the Order
given to it.
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Note that the window above only has a single side option, but the combo for this project requires two sides. So, you may have to adapt this layout to work in this case.
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
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.
Add a Web Framework to the existing project.
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.
heropizza.web
package.heropizza.web.MenuController
class to act as the controller. It should include the following routes:
/
- a home page for the application./info
- an info page with the text given at the bottom of the page. You may add additional text and items as desired/order
- a page that includes the entire menu (all predefined combos, pizzas, sides, and drinks).
Menu
class to collect these items.Menu
class as desired to make this work.Create a base layout file including the following:
- Hero Pizza
Create the following template files to match the routes listed above:
index.html
contains an <h1> tag with the title “Homepage” and the following text in a paragraph (you may add additional text as desired):Welcome to Hero Pizza! Our motto: eat like a hero - choose pizza!
info.html
contains an <h1> tag with the title “About Hero Pizza” and the following text in a paragraph (you may add additional text as desired):Hero Pizza was developed as part of the CC 410 course at Kansas State University by <your name here>.
order.html
contains the following content:
food-item
. It should include:
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Below is a screenshot from a previous model solution for some web design inspiration.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
The ninth milestone involves augmenting the menu display from the previous project by adding search and filtering functionality via an HTML form.
This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
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.
You should also handle the case where keyword searches will return a combo if it contains an item that matches the search term. For example, a search for “batwings” should not only return that side, but also combos 2 and 4 since those combos include that item.
Your search page should be accessible via the simplesearch
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.
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:
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.
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<Food> items, String keywords) - returns Iterable<Food>
filterTypes(Iterable<Food> items, boolean entree, boolean side, boolean drink, boolean combo) - returns Iterable<Food>
filterPrice(Iterable<Food> items, float min, float max) - returns Iterable<Food>
filterCalories(Iterable<Food> items, int min, int max) - returns Iterable<Food>
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
The tenth milestone involves building a RESTful web application that could be used to manage custom menu items.
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.
Create a class heropizza.data.menu.CustomMenuItem
that can represent a custom menu item. It should implement the Food
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.
Create a class heropizza.data.menu.CustomMenuItemList
that represents a list of custom menu items. This class should implement both the Iterator design pattern (using the Iterable<CustomMenuItem>
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 CustomMenuItem
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.
Create a new web controller named CustomController
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 | /custom |
Display all custom items. | Read All |
GET | /custom/new |
Display a form to create a new item. | N/A |
POST | /custom |
Create a new custom item | Create |
GET | /custom/{id} |
Display a single custom item | Read One |
GET | /custom/{id}/edit |
Display a form to edit the custom item | N/A |
POST | /custom/{id} |
Update the custom item | Update |
GET | /custom/{id}/delete |
Display a warning page before deleting an item | N/A |
POST | /custom/{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 CustomMenuItemList
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 CustomMenuItemList
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.
Add a link to the /custom
route to the navigation section of your site’s base layout template.
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 /custom/{id}
route for that 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 /custom/{id}/edit
and /custom/{id}/delete
routes, as well as a link to the main /custom
route.
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.
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:
/custom
- find the item to delete and click the link to see details./custom/{id}
- click the delete link to delete the item./custom/{id}/delete
- see a warning page about deleting, and click the delete link again./custom/{id}/delete
- browser sends a POST request to this URL to delete the item (this is invisible to the user)/custom
- browser is redirected back to the main pageAt 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.
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
This assignment will be graded based on the rubric below:
CustomMenuItem
class - 10%CustomMenuItemList
class - 20%The following deductions apply:
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.
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Hero Pizza, celebrating the heroes from cartoons, comic books, movies, and more.
The eleventh milestone involves adding form validation and serialization to the existing project, specifically targeted at custom menu items.
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.
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:
name
of the custom menu item should not be null, and have at least 5 characters.price
of the custom menu item must be greater than or equal to 1.00, 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.calories
of the custom menu item must be greater than or equal to 100.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.
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.
CustomMenuItemList
class is created. In Java, this would most likely be the getInstance()
method, while in Python it would be in the __new__()
method. So, when the user first visits the /custom
page, the previously saved custom items should appear.CustomMenutemList
class should implement a new method called save
that will serialize the current contents of the custom item list to a file.CustomController
with the path /custom/save
that will save the existing custom items list to file by calling the new save
method./custom
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
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.
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.
A complete final project should include the following features:
gradle
or tox
) and test frameworks. The goal is to use the tools learned throughout the semester to build a different project and focus on the design of the code, not learning new tools or languages.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. This project should be roughly 1/4 to 1/3 the size and scope of the semester-long restaurant project.
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.
README
file that describes your project, including how to compile and run it.README
file as well.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 60%.
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.
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.
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.
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.
This project should include the following features:
HelloWorld
class that contains a main
method.
main
method should print “Hello World” if no command line arguments are received.main
method should print “Hello {arg}” if a command line argument is received.HelloWorld
class, properly testing both with and without command-line arguments..py
files should also include a file docstring, including __init__.py
and __main__.py
files for packages.HelloWorld
class must include explicit data types
HelloWorld
class must not use Any
as a type.Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%The following deductions apply:
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.
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
thatsawrap.data.wraps
packagethatsawrap.data.sides
packagethatsawrap.data.drinks
packagethatsawrap.data.enums
packageSee the That’s a Wrap 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
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 wraps and start there. Once you have the wraps all working, the sides and drinks are pretty easy and use much of the same structure. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
our motto: be a star - wrap things your way!
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):
price
attribute would have a getPrice
getter and setPrice
setter method.__price
attribute would have a getter and setter named price
implemented as a Python Property.Each wrap should be stored in an appropriately named class in the thatsawrap.data.wraps
package. Each wrap should include an attribute for the following data:
Shell
value (see below). It should have a getter and setter method.Addin
values (see below).
In addition, each wrap 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.
double
or Python float
value representing the base price of the item plus any upcharge associated with the chosen Shell value.int
value representing the number of calories associated with the item.String
values or a Python list of str
values.
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 wrap class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the wrap. The string should be formatted as “{wrap name} in a {shell} Shell”, such as “The Godfather in a Stromboli Shell”.
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 wrap description will include a list of ingredients included on the wrap. 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 Pepperoni”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message. If all ingredients are at their default values, the Instructions list should be empty.
Each wrap will be served in a particular Default Shell, and will include a default set of Addins. Those attributes should be populated appropriately in the constructor for the wrap. Changes to the Shell and Addins attributes will not affect the Instructions attribute at this time (we’ll add that later).
The number of Calories for a wrap will remain constant, regardless of other attributes (we’ll just pretend that changing the wrap doesn’t change the number of calories).
The Price for a wrap will change based on the value selected for the Shell. Each wrap will have a base price listed for the Default Shell option. Other shells include an associated upcharge or discount, which must be adjusted.
This means that the prices shown on the menu already include the upcharge for the given default shell. You may want to calculate and store a base price for the item by removing the upcharge from the menu price.
this wrap will make your taste buds an offer they can’t refuse
thatsawrap.data.wraps.Godfather
- The price is $9.65 and it is 1268 calories. Served in a Stromboli Shell. Ingredients: Pepperoni, Sausage, Marinara and Cheese. Addins: Peppers and Onions.
an emerald city of flavors - truly a wrap of a different color
thatsawrap.data.wraps.Wizard
- The price is $10.35 and it is 1085 calories. Served in a Spinach Shell. Ingredients: Chicken, Spinach, Cheese. Addins: Tomatoes and Dressing.
a hot and spicy classic
thatsawrap.data.wraps.SomeLike
- The price is $11.45 and it is 1370 calories. Served in a Whole Grain Shell. Ingredients: Chicken, Cheese. Addins: Onions, Peppers and Buffalo Sauce.
a specialty from the city so nice they named it twice
thatsawrap.data.wraps.WestSide
- The price is $8.75 and it is 1240 calories. Served in a Whole Grain Shell. Ingredients: Corned Beef, Cabbage and Cheese. Addins: Onions, Pickles and Mustard.
a massive wrap that can feed even the hungriest warrior
thatsawrap.data.wraps.Spartacus
- The price is $16.55 and it is 1874 calories. Served in a Spinach Shell. Ingredients: Pepperoni, Sausage, Chicken, Corned Beef and Cheese. Addins: Peppers, Tomatoes, Onions, Pickles, Buffalo Sauce and Dressing.
Each side should be stored in an appropriately named class in the thatsawrap.data.sides
package. Each side should include an attribute for the following data:
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.
double
or Python float
value.int
value.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 “Indie Yankee Doodle Dandy”.
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 Indie
.
stuck a feather in his cap and called it macaroni
thatsawrap.data.sides.Yankee
- Indie: $2.25 and 400 calories. Studio: $3.95 and 650 calories. Blockbuster: $6.25 and 875 calories.
fried potatoes good enough to keep for yourself
thatsawrap.data.sides.French
- Indie: $2.75 and 550 calories. Studio: $4.85 and 700 calories. Blockbuster: $5.25 and 950 calories.
guaranteed not to be poisoned or your money back
thatsawrap.data.sides.SnowWhite
- Indie: $1.50 and 225 calories. Studio: $2.25 and 350 calories. Blockbuster: $3.00 and 475 calories.
Each drink should be stored in an appropriately named class in the thatsawrap.data.drinks
package. Each drink should include an attribute for the following data:
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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 “Indie Forrest Gump”.
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 flavors that may be added. Those flavors 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 {flavor}” message, such as “Add Cherry”, to be added to the Instructions list. Likewise, changing it back to false
will remove the appropriate message.
In addition, drinks may specify default flavors that 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 {flavor}” message, such as “Hold Coconut”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message.
If all flavors are at their default values, the Instructions list should be empty.
Each side description will include a Price and number of Calories for each Size. The sides will have a default size of Indie
. Changes to the Size attribute will not affect the Instructions attribute.
you never know what you are going to get
thatsawrap.data.drinks.Forrest
- Flavors: Chocolate (default), Vanilla, Caramel and Coffee. Indie: $5.25 and 980 calories. Studio: $7.50 and 1365 calories. Blockbuster: $9.00 and 1875 calories.
comes with a little umbrella, but you have to provide the song
thatsawrap.data.drinks.Singin
- Flavors: Cherry (default), Strawberry, Cola and Grape. Indie: $2.75 and 360 calories. Studio: $3.25 and 400 calories. Blockbuster: $4.00 and 550 calories.
eye of the tiger not included
thatsawrap.data.drinks.Rocky
- Flavors: Strawberry (default), Banana, Peach and Mango. Indie: $5.85 and 665 calories. Studio: $7.95 and 825 calories. Blockbuster: $9.45 and 1060 calories.
Each enumeration should be stored in an appropriately named class in the thatsawrap.data.enums
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.
an excellent setting for a delicious meal
thatsawrap.data.enums.Shell
- Whole Grain (add $0.75), Spinach (add $1.00) or Stromboli (add $1.50)
It is possible to create an enumeration that also stores additional data associated with each value, and then access that data through the enum value. You may be able to use this to simplify handling the upcharge for each shell. Below are links to some sample code from later in this course that shows how to create such an enum and use that data.
options to fit any budget
thatsawrap.data.enums.Size
- Indie (Small), Studio (Medium), Blockbuster (Large)
the extras aren’t just in the background
thatsawrap.data.enums.Addins
- Peppers, Onions, Tomatoes, Pickles, Dressing, Buffalo Sauce, Mustard
Special thanks to friends and family for inspiration and menu suggestions!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
test
directory for the class it is testing.src
directory.java
or python
folder).Some quick tips from when I did this milestone:
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 wraps 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.pepperoni
or cherry
) 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.@pytest.mark.parametrize("crust", Crust)
.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
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 wraps and start there writing unit tests. Once you have the wraps all working, the sides and drinks are pretty easy and use much of the same structure. There are several hundred 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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Remember that unit tests should test a single unit of code. So, make sure your unit tests are as short and concise as possible to allow you to pinpoint individual errors.
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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
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 should include the following features:
thatsawrap.data.menu.Item
interface that is implemented by all wrap, side, and drink classes
thatsawrap.data.wraps.Wrap
base classthatsawrap.data.sides.Side
base classthatsawrap.data.drinks.Drink
base classthatsawrap.data.menu.Menu
that contains the full menu
Menu
class should containItem
interfaceMenu
and Item
should report near 100% code coverage.Menu
to confirm that each possible menu item is present in the menu.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 about 100 more unit tests in total. -Russ
This assignment will be graded based on the rubric below:
Item
Interface - 25%Wrap
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%Menu
Class - 20%Menu
Unit Tests - 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
The thatsawrap.data.menu.Item
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:
Each menu item (wraps, sides, and drinks) should be refactored to implement this interface. This will require some changes:
Wrap
base class.Side
base class.Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
thatsawrap.data.wraps.Wrap
is the base class for all wrap items. It should include the following elements that are common to all wrap classes:
thatsawrap.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:
thatsawrap.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:
You may choose to implement the Item
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 Item
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, though going through the base class makes things simpler down the road!
If you choose to inherit from the Item
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.INDIE
), then make sure you call that constructor using super().__init__()
in the subclass’ constructor.
The thatsawrap.data.menu.Menu
class should be a class that has static getter methods for these four elements:
wraps
- a list of Item
elements containing an instance of all available wraps (5 in total).sides
- a list of Item
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 (9 in total).drinks
- a list of Item
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 (9 in total).fullmenu
- a combined list of all menu items (23 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.
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Item
interfaceItem
interfaceItem
interfaceTo 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).
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
This milestone should include the following features:
thatsawrap.gui
package to store all GUI code.thatsawrap.gui.wraps
package to store all GUI panels for wraps.thatsawrap.gui.sides
package to store all GUI panels for sides.thatsawrap.gui.drinks
package to store all GUI panels for drinks.thatsawrap.Main
class that properly loads and displays the program’s GUI.thatsawrap.gui.PrimaryWindow
class that represents the main GUI window.
thatsawrap.gui.MenuPanel
class to represent the main ordering screen panel.
thatsawrap.gui.OrderPanel
class to represent the sidebar panel containing a user’s order.
thatsawrap.gui.wraps
package for each wrap.
WrapPanel
class to reduce the amount of duplicate code.SidePanel
in the thatsawrap.gui.sides
package.
Side
class instead of individual sides themselves. When the buttons on the menu are clicked, you’ll need to make sure an instance of the correct menu item is created.thatsawrap.gui.drinks
package for each drink item.
DrinkPanel
class to reduce the amount of duplicate code.Each of the menu item panels should also implement the following functionality:
thatsawrap.gui
package do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.thatsawrap.gui
package do not require unit tests.thatsawrap.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.thatsawrap.gui
package and how all GUI classes are related. You should also show any links to the classes in the thatsawrap.data
package, but you may choose to show simplified links between packages instead of individual classes. You do not have to include full details from classes in the thatsawrap.data
packages.
thatsawrap.gui.wraps
package are all related to similar classes in the thatsawrap.data.wraps
package without listing the individual classes in that package.You are welcome to add additional methods to the existing content in the thatsawrap.data
package. If so, make sure you include appropriate documentation, 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.
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
This assignment will be graded based on the rubric below:
Main
class - 2%PrimaryWindow
class - 4%OrderPanel
class - 4%MenuPanel
class - 20%SidePanel
class - 5%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
Below are some GUI sketches to help you visualize one possible GUI for a previous version of 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
Here are a couple of helpful pieces of code that you may wish to use in your project.
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 wrap 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.
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 pizza 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 MenuPanel
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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
The fifth milestone involves dealing with the various events generated by the GUI and constructing a list of items that represent an order.
Changes to the previous milestone:
OrderPanel
panel.OrderPanel
to a tree element (Java JTree
or tkinter Treeview
). 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 OrderPanel
, the following should happen:
It may be helpful to maintain a hash map or dictionary in the OrderPanel
class that associates nodes in the GUI tree element with the actual Item
instances that they represent.
When the Save button in any of the wrap, side, or drink panels is clicked, the following should happen:
OrderPanel
if it is a new item, or the item should be updated if it is being edited.PrimaryWindow
should be replaced with the MenuPanel
(this was part of the previous milestone).When the Cancel button in any of the wrap, side, or drink panels is clicked, the following should happen:
PrimaryWindow
should be replaced with the OrderPanel
(this was part of the previous milestone for the Save button, and the code is similar).When the Edit button in the OrderPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.PrimaryWindow
and populated with the current data from the item (most of this should be present from the previous milestone, but much of it may be untested at this point).When the Delete button in the SidebarPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.OrderPanel
class.Unit tests should be added to the corresponding test package for the following classes:
thatsawrap.gui.wraps
thatsawrap.gui.drinks
thatsawrap.gui.sides
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 PrimaryWindow
, OrderPanel
, or MenuPanel
classes in this milestone. - Russ
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:
thatsawrap.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.thatsawrap.gui
base package do not require unit tests, but all wrap, drink, and side panels require unit tests as outlined above.thatsawrap.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.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 one of the more complex panels, and I used that as a template to create the rest of the unit tests. My current model solution contains ~850 unit tests, and I was able to achieve 100% code coverage on all GUI item panels. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
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.
I found these methods helpful in my solution:
PrimaryWindow.addItem(item)
- basically a pass-through method that calls the OrderPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to the PrimaryWindow
instance.OrderPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.==
operator in Java, or the is
operator in Python. This means that you won’t be able to use the normal contains()
or in
method for determining if the item is already in a list - you must iterate through the list manually.OrderPanel.updateTree(item, node)
- handles actually updating the tree. If node
is null
or not provided, it creates a new one, otherwise it uses the existing node
and updates it. It should return the node
or that node’s id
when complete.Each wrap panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each side panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each drink panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).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.
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
DISPLAY
environment variable.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/thatsawrap/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps --html=reports/pytest-wraps/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/drinks test/thatsawrap/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.reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
This assignment will add several new classes to the project
thatsawrap.data.order.Order
- this class should represent a collection of Item
objects that make up an order.
Item
object is contained in the collection. Recall that this should use the identity test, not the equality test.Item
s, with methods to add and remove items.
OrderNumberSingleton
class discussed below. It should only include a getter.Order
objects.thatsawrap.data.order.Combo
- this class should implement the Item
interface, and represent a combo meal consisting of a wrap, a side, and a drink.
Wrap
instance - the wrap in the comboSide
instance - the side in the comboDrink
instance - the drink in the combonull
or None
in the constructor to represent a combo yet to be configured.null
or None
. You may have a single method, or one for each attribute.Item
interface:
discount
Discount Applied” if all items in the combo are present. If not, this entry should not be included.null
or None
. The name will only be set by the ComboBuilder
class discussed below, but users will also be able to configure a custom combo via the GUI that does not include a name.null
or None
initially.null
or None
, it is considered equal if the matching attribute is also null
or None
.
equals()
method on a null
object will result in an exception. So, you’ll have to check if each attribute in this object is null
first. If so, and the other object’s attribute is not null
, then they are not equal. If this object’s attribute is not null
, you can safely call equals()
on it, regardless of the other object’s attribute.thatsawrap.data.order.ComboBuilder
- a class that implements the Builder Pattern and Factory Method Pattern to build the available combos described below.
Combo
object indicated by that string (the name of the combo).You don’t have to create individual classes for the builder pattern in the ComboBuilder
class - it is sufficient to just have a private method for building each combo in the class itself. The full Builder pattern is a bit too much boilerplate code for this simple use.
thatsawrap.data.order.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
synchronized
statement in Java or a lock in a with
statement in Python).thatsawrap.gui.PanelFactory
- a class that implements the Factory Method Pattern to return an instance of a GUI panel for a given wrap, side, or drink.
PrimaryWindow
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 the parent
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 the name
is not recognized, an exception should be thrown.Item
item, PrimaryWindow
parent) should accept an instance of an Item
and return a panel that represents that item, with the parent
GUI element as its parent. If the item
is not recognized, an exception should be thrown.Combos
as Items
. We’ll address that in the next milestone.There will also be several updates to existing classes.
Menu
- update to include the following items:
ComboBuilder
class discussed below.MenuPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the action command received from button that was clicked.OrderPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree.Order
instance as well.
OrderPanel
constructor.Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.
All new and updated classes in this milestone should contain full documentation comments. Every method should be completely documented!
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 PrimaryWindow
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 PrimaryWindow
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 PrimaryWindow
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:
thatsawrap.data.*
thatsawrap.gui.drinks.*
thatsawrap.gui.wraps.*
thatsawrap.gui.sides.*
The only classes that do not meet this requirement are PrimaryWindow
, OrderPanel
, PanelFactory
, and MenuPanel
in the thatsawrap.gui
package.
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
This assignment will be graded based on the rubric below:
Order
- 10%Combo
- 10%ComboBuilder
- 10%OrderNumberSingleton
- 5%PanelFactory
- 5%Order
- 15%Combo
- 15%ComboBuilder
- 5%OrderNumberSingleton
- 5%Menu
and unit tests: 5%MenuPanel
: 5%OrderPanel
: 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
The Godfather, The French Connection, Singin’ in the Rain
The Wizard of Oz, Snow White, Rocky
Spartacus, Yankee Doodle Dandy, Forrest Gump
Some Like It Hot, The French Connection, Forrest Gump
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.
equals()
is called. Place one in the order, and use them to confirm that contains
returns both true and false when given two items that are equal but not the same instance.OrderNumberSingleton
that returns a value for an order number, then instantiate an Order
and verify that it received the given order number.Order
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 the tax
virtual attribute.null
or None
and handle that case properlynull
or None
Combo
instances, change the discount, and confirm that both use the new discount. This is best done by adding all items to each combo and checking the total price.For these tests, I recommend just checking the types of the wrap, side, and drink items 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.
getNextOrderNumber()
several times and make sure each one is sequential.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:
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/thatsawrap/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps/test_GodfatherPanel.py --html=reports/pytest-items1/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps/test_WizardPanel.py --html=reports/pytest-items2/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps/test_SomeLikePanel.py --html=reports/pytest-items3/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps/test_WestSidePanel.py --html=reports/pytest-items4/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/wraps/test_SpartacusPanel.py --html=reports/pytest-items5/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/thatsawrap/gui/drinks test/thatsawrap/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:
reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
It is best to think of this assignment as one consisting of two distinct parts.
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:
Combo
class should handle this as defined in the previous milestone.OrderPanel
class will need to be updated to properly handle combos.
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:
PrimaryWindow
class/type as its parent, we can abstract that to a ParentPanel
interface that is implemented by both the PrimaryWindow
class and ComboPanel
. This allows the existing order item panels to use the new ComboPanel
as its parent.ComboPanel
ComboPanel
instead of PrimaryWindow
)PrimaryWindow
to add the item to the order.data
package as desired.PanelFactory
since it could be used from within ComboPanel
, but also will be used to create instances of ComboPanel
. A way to resolve this would be to create a ComboPanelFactory
to handle combos, and adapt the code where PanelFactory
is used to direct combo instances to the new ComboPanelFactory
instead.All new and updated classes in this milestone should contain full documentation comments. All methods must be fully documented!
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:
Combo
object when it is saved.Combo
object when it is saved.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
.
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:
edu.ksu.cs.cc410.register
package.cc410.register
package.When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
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.
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.
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 only 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 not 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:
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).
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 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 indentations 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.
All new and updated classes in this milestone should contain full documentation comments. All methods must be fully documented!
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
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 highly 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:
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.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.
ReceiptPrinter
wrapper that accepts an Order
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect the Order
given to it.
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
Note that the window above only has a single side option, but the combo for this project requires two sides. So, you may have to adapt this layout to work in this case.
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
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.
Add a Web Framework to the existing project.
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.
thatsawrap.web
package.thatsawrap.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. You may add additional text and items as desired/menu
- a page that includes the entire menu (all predefined combos, wraps, sides, and drinks).
Menu
class to collect these items.Menu
class as desired to make this work.Create a base layout file including the following:
- That's a Wrap
Create the following template files to match the routes listed above:
index.html
contains an <h1> tag with the title “Homepage” and the following text in a paragraph (you may add additional text as desired):Welcome to That’s a Wrap! Our motto: be a star - wrap things your way!
about.html
contains an <h1> tag with the title “About That’s a Wrap” and the following text in a paragraph (you may add additional text as desired):That’s a Wrap was developed as part of the CC 410 course at Kansas State University by <your name here>.
menu.html
contains the following content:
menu-item
. It should include:
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
Below is a screenshot from a previous model solution for some web design inspiration.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
The ninth milestone involves augmenting the menu display from the previous project by adding search and filtering functionality via an HTML form.
This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
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.
You should also handle the case where keyword searches will return a combo if it contains an item that matches the search term. For example, a search for “wizard” should not only return that wrap, but also any combos that include that item.
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.
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:
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.
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<Item> items, String keywords) - returns Iterable<Item>
filterTypes(Iterable<Item> items, boolean wrap, boolean side, boolean drink, boolean combo) - returns Iterable<Item>
filterPrice(Iterable<Item> items, float min, float max) - returns Iterable<Item>
filterCalories(Iterable<Item> items, int min, int max) - returns Iterable<Item>
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.
In the method signature above, the Iterable
class is simply an interface. In Java, you can use a List
subtype such as LinkedList
that supports that interface. In Python, the base List
type will also work. - Russ
Menu
class require unit tests to achieve 100% coverage. You should use test doubles in these unit tests, and make sure you are testing all possible outcomes.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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
The tenth milestone involves building a RESTful web application that could be used to manage custom menu items.
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.
Create a class thatsawrap.data.custom.CustomItem
that can represent a custom menu item. It should implement the Item
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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
Create a class thatsawrap.data.custom.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.
The class should include full documentation comments. 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.
Create a new web controller named CustomController
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 | /custom |
Display all custom items. | Read All |
GET | /custom/new |
Display a form to create a new item. | N/A |
POST | /custom |
Create a new custom item | Create |
GET | /custom/{id} |
Display a single custom item | Read One |
GET | /custom/{id}/edit |
Display a form to edit the custom item | N/A |
POST | /custom/{id} |
Update the custom item | Update |
GET | /custom/{id}/delete |
Display a warning page before deleting an item | N/A |
POST | /custom/{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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
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.
Add a link to the /custom
route to the navigation section of your site’s base layout template. This should be clearly accessible via the navigation menu or a similar structure.
You are encouraged to reuse the content from your existing template for displaying all custom menu items here. Each custom menu item should include a link to the /custom/{id}
route for that 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 /custom/{id}/edit
and /custom/{id}/delete
routes, as well as a link to the main /custom
route.
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.
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:
/custom
- find the item to delete and click the link to see details./custom/{id}
- click the delete link to delete the item./custom/{id}/delete
- see a warning page about deleting, and click the delete link again./custom/{id}/delete
- browser sends a POST request to this URL to delete the item (this is invisible to the user)/custom
- browser is redirected back to the main pageAt the end of this project, you should create a new UML diagram for the project that includes the new web application classes. It should also show the links to other classes/packages in the application, but those items do not require any details (they can just be simple boxes containing the class or package name.)
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
This assignment will be graded based on the rubric below:
CustomItem
class - 10%CustomItemList
class - 20%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named That’s a Wrap, offering wraps of all shapes and sizes to celebrate our favorite movies.
The eleventh milestone involves adding form validation and serialization to the existing project, specifically targeted at custom menu items.
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.
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:
name
of the custom menu item should not be null, and have at least 4 characters.price
of the custom menu item must be greater than or equal to 1.50, 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.calories
of the custom menu item must be an integer greater than or equal to 250.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.
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.
CustomItemList
class is created. In Java, this would most likely be the getInstance()
method, while in Python it would be in the __new__()
method. So, when the user first visits the /custom
page, the previously saved custom items should appear.CustomItemList
class should implement a new method called save
that will serialize the current contents of the custom item list to a file.CustomController
with the path /custom/save
that will save the existing custom items list to file by calling the new save
method./custom
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
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.
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.
A complete final project should include the following features:
gradle
or tox
) and test frameworks. The goal is to use the tools learned throughout the semester to build a different project and focus on the design of the code, not learning new tools or languages.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. This project should be roughly 1/4 to 1/3 the size and scope of the semester-long restaurant project.
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.
README
file that describes your project, including how to compile and run it.README
file as well.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 60%.
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.
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.
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.
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.
This project should include the following features:
HelloWorld
class that contains a main
method.
main
method should print “Hello World” if no command line arguments are received.main
method should print “Hello {arg}” if a command line argument is received.HelloWorld
class, properly testing both with and without command-line arguments..py
files should also include a file docstring, including __init__.py
and __main__.py
files for packages.HelloWorld
class must include explicit data types
HelloWorld
class must not use Any
as a type.Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%The following deductions apply:
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.
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
gamegrub.data.entrees
packagegamegrub.data.sides
packagegamegrub.data.drinks
packagegamegrub.data.enums
packageSee the Game Grub 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
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 entrees and start there. Once you have the entrees all working, the sides and drinks are pretty easy and use much of the same structure. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
our motto: play fair, eat well
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):
price
attribute would have a getPrice
getter and setPrice
setter method.__price
attribute would have a getter and setter named price
implemented as a Python Property.Each entree should be stored in an appropriately named class in the gamegrub.data.entrees
package. Each entree should include an attribute for the following data:
Base
value (see below). It should have a getter and setter method.Topping
values (see below).
In addition, each entree 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.
double
or Python float
value representing the base price of the item plus any upcharge associated with the chosen Base value.int
value representing the number of calories associated with the item.String
values or a Python list of str
values.
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 entree class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the entree. The string should be formatted as “{entree name} on {base}”, such as “Clue Chili on Spaghetti”.
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 entree description will include a list of ingredients included on the entree. 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 Sauce”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message. If all ingredients are at their default values, the Instructions list should be empty.
Each entree will be served on a particular Default Base, and will include a default set of Toppings. Those attributes should be populated appropriately in the constructor for the entree. Changes to the Base and Toppings attributes will not affect the Instructions attribute at this time (we’ll add that later).
The number of Calories for a entree will remain constant, regardless of other attributes (we’ll just pretend that changing the base or toppings doesn’t change the number of calories).
The Price for a entree will change based on the value selected for the Base. Each entree will have a base price listed for the Default Base option. Other bases include an associated upcharge or discount, which must be adjusted.
This means that the prices shown on the menu already include the upcharge for the given default base. You may want to calculate and store a base price for the item by removing the upcharge from the menu price.
you’ll have to discover “whodunit” and created this twist on a classic
gamegrub.data.entrees.Clue
- The price is $10.45 and it is 1165 calories. Served on a Spaghetti Base. Ingredients: Spicy Beef, Chili, Red Sauce and Beans. Toppings: Onion, Cheese and Hot Sauce
stack them higher and higher until it all falls down
gamegrub.data.entrees.Jenga
- The price is $11.85 and it is 1470 calories. Served on a Chips Base. Ingredients: Spicy Beef, and Beans. Toppings: Onion, Cheese, Sour Cream, Hot Sauce and Guacamole
a refreshing dish perfect for a day on the water
gamegrub.data.entrees.Yahtzee
- The price is $15.25 and it is 785 calories. Served on a Rice Base. Ingredients: Tuna, Veggies, and Seaweed. Toppings: Guacamole, Soy Sauce, Hot Sauce and Crispy Strips
a hearty dish to checkmate any hunger
gamegrub.data.entrees.Chess
- The price is $13.65 and it is 1555 calories. Served on a Spaghetti Base. Ingredients: Crispy Chicken, and Red Sauce. Toppings: Cheese and Fresh Herbs
a true winner takes home everything
gamegrub.data.entrees.Monopoly
- The price is $18.65 and it is 1685 calories. Served on a Rice Base. Ingredients: Spicy Beef, Crispy Chicken, Beans, and Veggies. Toppings: Onion, Cheese, Hot Sauce, Sour Cream, Guacamole, and Crispy Strips
Each side should be stored in an appropriately named class in the gamegrub.data.sides
package. Each side should include an attribute for the following data:
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.
double
or Python float
value.int
value.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 “Junior Potato Dice”.
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 Junior
.
a pile of d6 shaped taters, deep fried and tasty
gamegrub.data.sides.Dice
- Junior: $2.75 and 350 calories. Classic: $3.85 and 475 calories. Winner: $5.35 and 795 calories.
wheat breaded lamb skewers, baked in a wood-fired clay oven and sprinkled with salt ore - every resource in the game!
gamegrub.data.sides.Catan
- Junior: $4.45 and 530 calories. Classic: $6.85 and 815 calories. Winner: $8.65 and 1045 calories.
deep fried mac & cheese balls, but one has a spicy surprise - are you brave enough to risk it?
gamegrub.data.sides.Risk
- Junior: $3.95 and 480 calories. Classic: $5.15 and 755 calories. Winner: $6.95 and 940 calories.
Each drink should be stored in an appropriately named class in the gamegrub.data.drinks
package. Each drink should include an attribute for the following data:
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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 “Junior Candy Land Shake”.
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 flavors that may be added. Those flavors 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 {flavor}” message, such as “Add Cherry”, to be added to the Instructions list. Likewise, changing it back to false
will remove the appropriate message.
In addition, drinks may specify default flavors that 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 {flavor}” message, such as “Hold Coconut”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message.
If all flavors are at their default values, the 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 Junior
. Changes to the Size attribute will not affect the Instructions attribute.
a classic shake with all the candy!
gamegrub.data.drinks.Candy
- Flavors: Chocolate (default), Vanilla, and Strawberry. Junior: $5.75 and 770 calories. Classic: $7.45 and 1215 calories. Winner: $9.55 and 1465 calories.
soda fountain for all, no apologies needed
gamegrub.data.drinks.Sorry
- Flavors: Cola (default), Cherry, Grape, and Orange. Junior: $2.55 and 370 calories. Classic: $3.85 and 535 calories. Winner: $5.35 and 765 calories.
fuel for the brain to win the game
gamegrub.data.drinks.Cranium
- Flavors: Milk (default), Caramel, Chocolate, and Mint. Junior: $4.35 and 380 calories. Classic: $5.25 and 495 calories. Winner: $6.00 and 585 calories.
Each enumeration should be stored in an appropriately named class in the gamegrub.data.enums
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.
an excellent start for a delicious meal
gamegrub.data.enums.Base
- Rice (add $1.00), Spaghetti (add $1.50) or Chips (add $2.00)
It is possible to create an enumeration that also stores additional data associated with each value, and then access that data through the enum value. You may be able to use this to simplify handling the upcharge for each base. Below are links to some sample code from later in this course that shows how to create such an enum and use that data.
strategies to win any game and fulfill your hunger
gamegrub.data.enums.Size
- Junior (Small), Classic (Medium), Winner (Large)
complete your meal and win the day
gamegrub.data.enums.Toppings
- Onions, Cheese, Hot Sauce, Sour Cream, Guacamole, Soy Sauce, Crispy Strips, Fresh Herbs
Special thanks to friends and family for inspiration and menu suggestions!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
test
directory for the class it is testing.src
directory.java
or python
folder).Some quick tips from when I did this milestone:
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 entrees 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.beans
or cherry
) 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.@pytest.mark.parametrize("base", Base)
.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
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 entrees and start there writing unit tests. Once you have the entrees all working, the sides and drinks are pretty easy and use much of the same structure. There are several hundred 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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Remember that unit tests should test a single unit of code. So, make sure your unit tests are as short and concise as possible to allow you to pinpoint individual errors.
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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
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.
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 should include the following features:
gamegrub.data.Item
interface that is implemented by all entree, side, and drink classes
gamegrub.data.entrees.Entree
base classgamegrub.data.sides.Side
base classgamegrub.data.drinks.Drink
base classgamegrub.data.menu.Menu
that contains the full menu
Menu
class should containItem
interfaceMenu
and Item
should report near 100% code coverage.Menu
to confirm that each possible menu item is present in the menu.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 about 100 more unit tests in total. -Russ
This assignment will be graded based on the rubric below:
Item
Interface - 25%Entree
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%Menu
Class - 20%Menu
Unit Tests - 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
The gamegrub.data.Item
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:
Each menu item (entrees, sides, and drinks) should be refactored to implement this interface. This will require some changes:
Entree
base class. This also means that newly instantiated items should no longer have an empty Instructions list. However, it may be simpler to populate the list when it is requested instead of storing it.Side
base class.Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
gamegrub.data.entrees.Entree
is the base class for all entree items. It should include the following elements that are common to all entree classes:
gamegrub.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:
gamegrub.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:
You may choose to implement the Item
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 Item
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, though going through the base class makes things simpler down the road!
If you choose to inherit from the Item
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.JUNIOR
), then make sure you call that constructor using super().__init__()
in the subclass’ constructor.
The gamegrub.data.menu.Menu
class should be a class that has static, class-level getter methods for these four elements:
entrees
- a list of Item
elements containing an instance of all available entrees (5 in total).sides
- a list of Item
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 (9 in total).drinks
- a list of Item
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 (9 in total).fullmenu
- a combined list of all menu items (23 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.
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Item
interfaceItem
interfaceItem
interfaceTo 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).
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The fourth milestone involves creating a class to track orders made at the restaurant, a class for combo meals, and more. It also includes many different design patterns to improve the structure of the code.
This assignment will add several new classes to the project
gamegrub.data.order.Order
- this class should represent a collection of Item
objects that make up an order.
Item
object is contained in the collection. Recall that this should use the identity test, not the equality test.Item
s, with methods to add and remove items.
OrderNumberSingleton
class discussed below. It should only include a getter.Order
objects.gamegrub.data.combo.Combo
- this class should implement the Item
interface, and represent a combo meal consisting of an entree, a side, and a drink.
Entree
instance - the entree in the comboSide
instance - the side in the comboDrink
instance - the drink in the combonull
or None
in the constructor to represent a combo yet to be configured.null
or None
. You may have a single method, or one for each attribute.Item
interface:
discount
Discount Applied” if all items in the combo are present. If not, this entry should not be included.null
or None
. The name will only be set by the ComboBuilder
class discussed below, but users will also be able to configure a custom combo via the GUI that does not include a name.null
or None
initially.null
or None
, it is considered equal if the matching attribute is also null
or None
.
equals()
method on a null
object will result in an exception. So, you’ll have to check if each attribute in this object is null
first. If so, and the other object’s attribute is not null
, then they are not equal. If this object’s attribute is not null
, you can safely call equals()
on it, regardless of the other object’s attribute.gamegrub.data.combo.ComboBuilder
- a class that implements the Builder Pattern and Factory Method Pattern to build the available combos described below.
Combo
object indicated by that string (the name of the combo).You don’t have to create individual classes for the builder pattern in the ComboBuilder
class - it is sufficient to just have a private method for building each combo in the class itself. The full Builder pattern is a bit too much boilerplate code for this simple use.
gamegrub.data.order.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
There will also be several updates to existing classes.
Menu
- update to include the following items:
ComboBuilder
class discussed below.All new and updated classes in this milestone should contain full documentation comments. Every method should be completely documented!
No new unit tests are required for this milestone. They will be added in the next milestone.
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. -Russ
This assignment will be graded based on the rubric below:
Order
- 30%Combo
- 30%ComboBuilder
- 15%OrderNumberSingleton
- 15%Menu
class: 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
Jenga Nachos, Catan Skewers, Sorry Soda
Yahtzee Poke, Potato Dice, Candy Land Shake
Chess Chicken Parmesan, Risk Bites, Cranium Coffee
Monopoly Bowl, Potato Dice, Sorry Soda
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The fifth milestone involves writing unit tests for the order, combo, and associated classes created in the previous milestone. These unit tests will make extensive use of test doubles.
The following new classes should contain unit tests that achieve at or near 100% code coverage and adequately test all aspects of the class.
Order
Combo
ComboBuilder
OrderNumberSingleton
Test doubles must be used where noted in the discussion below. In general, any time a test refers to another class other than the one being tested, it should use a test double instead of an instance of that class.
In addition, some previous tests may need to be updated to match new requirements.
Menu
- add tests for combos and updated full menuOnce this milestone is complete, all classes in the following packages should have unit tests that achieve at or near 100% code coverage:
gamegrub.data.*
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
This assignment will be graded based on the rubric below:
Order
- 30%Combo
- 30%ComboBuilder
- 15%OrderNumberSingleton
- 15%Menu
unit tests: 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
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.
equals()
is called. Place one in the order, and use them to confirm that contains
returns both true and false when given two items that are equal but not the same instance.OrderNumberSingleton
that returns a value for an order number, then instantiate an Order
and verify that it received the given order number.Order
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 the tax
virtual attribute.null
or None
and handle that case properlynull
or None
Combo
instances, change the discount, and confirm that both use the new discount. This is best done by adding all items to each combo and checking the total price.For these tests, I recommend just checking the types of the entree, side, and drink items in the Combo returned, as well as the name, rather than using any test double objects. As before, you may wish to make these attributes visible to the test.
getNextOrderNumber()
several times and make sure each one is sequential.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The sixth 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.
This milestone should include the following features:
gamegrub.gui
package to store all GUI code.gamegrub.gui.entrees
package to store all GUI panels for entrees.gamegrub.gui.sides
package to store all GUI panels for sides.gamegrub.gui.drinks
package to store all GUI panels for drinks.gamegrub.Main
class that properly loads and displays the program’s GUI.gamegrub.gui.PrimaryWindow
class that represents the main GUI window.
gamegrub.gui.MenuPanel
class to represent the main ordering screen panel.
gamegrub.gui.OrderPanel
class to represent the sidebar panel containing a user’s order.
gamegrub.gui.entrees
package for each entree.
EntreePanel
class to reduce the amount of duplicate code.SidePanel
in the gamegrub.gui.sides
package.
Side
class instead of individual sides themselves. When the buttons on the menu are clicked, you’ll need to make sure an instance of the correct menu item is created.gamegrub.gui.drinks
package for each drink item.
DrinkPanel
class to reduce the amount of duplicate code.Each of the menu item panels should also implement the following functionality:
gamegrub.gui
package do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.gamegrub.gui
package do not require unit tests at this time.gamegrub.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.gamegrub.gui
package and how all GUI classes are related. You should also show any links to the classes in the gamegrub.data
package, but you may choose to show simplified links between packages instead of individual classes. You do not have to include full details from classes in the gamegrub.data
packages.
gamegrub.gui.entrees
package are all related to similar classes in the gamegrub.data.entrees
package without listing the individual classes in that package.You are welcome to add additional methods to the existing content in the gamegrub.data
package. If so, make sure you include appropriate documentation, 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.
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
This assignment will be graded based on the rubric below:
Main
class - 2%PrimaryWindow
class - 4%OrderPanel
class - 4%MenuPanel
class - 20%SidePanel
class - 5%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
Below are some GUI sketches to help you visualize one possible GUI for a previous version of 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
Here are a couple of helpful pieces of code that you may wish to use in your project.
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 entree 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.
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 pizza 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 MenuPanel
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!
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The seventh milestone involves dealing with the various events generated by the GUI and constructing a list of items that represent an order.
Changes to the previous milestone:
OrderPanel
panel.OrderPanel
to a tree element (Java JTree
or tkinter Treeview
). 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 OrderPanel
, the following should happen:
It may be helpful to maintain a hash map or dictionary in the OrderPanel
class that associates nodes in the GUI tree element with the actual Item
instances that they represent. This is in addition to the Order
object they will be stored in (added in a later milestone).
When the Save button in any of the entree, side, or drink panels is clicked, the following should happen:
OrderPanel
if it is a new item, or the item should be updated if it is being edited.PrimaryWindow
should be replaced with the MenuPanel
(this was part of the previous milestone).When the Cancel button in any of the entree, side, or drink panels is clicked, the following should happen:
PrimaryWindow
should be replaced with the OrderPanel
(this was part of the previous milestone for the Save button, and the code is similar).When the Edit button in the OrderPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.PrimaryWindow
and populated with the current data from the item (most of this should be present from the previous milestone, but much of it may be untested at this point).When the Delete button in the SidebarPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.OrderPanel
class.Unit tests should be added to the corresponding test package for the following classes:
gamegrub.gui.entrees
gamegrub.gui.drinks
gamegrub.gui.sides
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 PrimaryWindow
, OrderPanel
, or MenuPanel
classes in this milestone. - Russ
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:
gamegrub.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.gamegrub.gui
base package do not require unit tests, but all entree, drink, and side panels require unit tests as outlined above.gamegrub.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.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 one of the more complex panels, and I used that as a template to create the rest of the unit tests. My current model solution contains ~850 unit tests, and I was able to achieve 100% code coverage on all GUI item panels. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
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.
I found these methods helpful in my solution:
PrimaryWindow.addItem(item)
- basically a pass-through method that calls the OrderPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to the PrimaryWindow
instance.OrderPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.==
operator in Java, or the is
operator in Python. This means that you won’t be able to use the normal contains()
or in
method for determining if the item is already in a list - you must iterate through the list manually.OrderPanel.updateTree(item, node)
- handles actually updating the tree. If node
is null
or not provided, it creates a new one, otherwise it uses the existing node
and updates it. It should return the node
or that node’s id
when complete.Each entree panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each side panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each drink panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).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.
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
DISPLAY
environment variable.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/gamegrub/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/gamegrub/gui/entrees --html=reports/pytest-entrees/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/gamegrub/gui/drinks test/gamegrub/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.reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The eighth 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.
This milestone introduces one new feature to the project. Instead of specifying a particular set of classes and structure, it is up to you as the developer to determine how to best implement this feature. Some hints are given in the related example project.
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:
Combo
class should handle this as defined in a previous milestone.OrderPanel
class will need to be updated to properly handle combos.
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:
PrimaryWindow
class/type as its parent, we can abstract that to a ParentPanel
interface that is implemented by both the PrimaryWindow
class and ComboPanel
. This allows the existing order item panels to use the new ComboPanel
as its parent.ComboPanel
ComboPanel
instead of PrimaryWindow
)PrimaryWindow
to add the item to the order.data
package as desired.PanelFactory
since it could be used from within ComboPanel
, but also will be used to create instances of ComboPanel
. A way to resolve this would be to create a ComboPanelFactory
to handle combos, and adapt the code where PanelFactory
is used to direct combo instances to the new ComboPanelFactory
instead.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:
Combo
object when it is saved.Combo
object when it is saved.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
.
This assignment will add one new class to the project
gamegrub.gui.PanelFactory
- a class that implements the Factory Method Pattern to return an instance of a GUI panel for a given entree, side, or drink.
PrimaryWindow
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 the parent
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 the name
is not recognized, an exception should be thrown.Item
item, PrimaryWindow
parent) should accept an instance of an Item
and return a panel that represents that item, with the parent
GUI element as its parent. If the item
is not recognized, an exception should be thrown.There will also be several updates to existing classes.
MenuPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the action command received from button that was clicked.OrderPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree.Order
instance as well.
OrderPanel
constructor.Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.
All new and updated classes in this milestone should contain full documentation comments. Every method should be completely documented!
Some previous tests may need to be updated to match new requirements.
Once this milestone is complete, all classes in the following packages should continue to have unit tests that achieve at or near 100% code coverage:
gamegrub.data.*
gamegrub.gui.drinks.*
gamegrub.gui.entrees.*
gamegrub.gui.sides.*
The only classes that do not meet this requirement are PrimaryWindow
, OrderPanel
, PanelFactory
, and MenuPanel
in the gamegrub.gui
package.
Any new classes created to handle editing combos should include unit tests. Refer to the associated example project for some ideas of how to unit test that class.
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
This assignment will be graded based on the rubric below:
PanelFactory
OrderPanel
- 20%MenuPanel
- 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The ninth milestone involves finalizing the GUI for creating orders and 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.
Implement the following features into your existing project.
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:
edu.ksu.cs.cc410.register
package.cc410.register
package.When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
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.
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.
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 only 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 not 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:
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).
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 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 indentations 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.
All new and updated classes in this milestone should contain full documentation comments. All methods must be fully documented!
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
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 highly 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:
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.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.
ReceiptPrinter
wrapper that accepts an Order
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect the Order
given to it.
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The tenth milestone involves moving into the web by creating a data-driven website to display the menu and some other information about the restaurant.
Add a Web Framework to the existing project.
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.
gamegrub.web
package.gamegrub.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. You may add additional text and items as desired/menu
- a page that includes the entire menu (all predefined combos, entrees, sides, and drinks).
Menu
class to collect these items.Menu
class as desired to make this work.Create a base layout file including the following:
- Game Grub
Create the following template files to match the routes listed above:
index.html
contains an <h1> tag with the title “Homepage” and the following text in a paragraph (you may add additional text as desired):Welcome to Game Grub! Our motto: play fair, eat well!
about.html
contains an <h1> tag with the title “About Game Grub” and the following text in a paragraph (you may add additional text as desired):Game Grub was developed as part of the CC 410 course at Kansas State University by <your name here>.
menu.html
contains the following content:
menu-item
. It should include:
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
Below is a screenshot from a previous model solution for some web design inspiration.
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.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The eleventh milestone involves augmenting the menu display from the previous project by adding search and filtering functionality via an HTML form.
This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
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.
You should also handle the case where keyword searches will return a combo if it contains an item that matches the search term. For example, a search for “chess” should not only return that entree, but also any combos that include that item.
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.
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:
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.
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<Item> items, String keywords) - returns Iterable<Item>
filterTypes(Iterable<Item> items, boolean entree, boolean side, boolean drink, boolean combo) - returns Iterable<Item>
filterPrice(Iterable<Item> items, float min, float max) - returns Iterable<Item>
filterCalories(Iterable<Item> items, int min, int max) - returns Iterable<Item>
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.
In the method signature above, the Iterable
class is simply an interface. In Java, you can use a List
subtype such as LinkedList
that supports that interface. In Python, the base List
type will also work. - Russ
Menu
class require unit tests to achieve 100% coverage. You should use test doubles in these unit tests, and make sure you are testing all possible outcomes.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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
This page lists the milestone requirements for Milestone 12 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The twelfth milestone involves building a RESTful web application that could be used to manage custom menu items.
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.
Create a class gamegrub.data.custom.CustomItem
that can represent a custom menu item. It should implement the Item
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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
Create a class gamegrub.data.custom.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.
The class should include full documentation comments. 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.
Create a new web controller named CustomController
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 | /custom |
Display all custom items. | Read All |
GET | /custom/new |
Display a form to create a new item. | N/A |
POST | /custom |
Create a new custom item | Create |
GET | /custom/{id} |
Display a single custom item | Read One |
GET | /custom/{id}/edit |
Display a form to edit the custom item | N/A |
POST | /custom/{id} |
Update the custom item | Update |
GET | /custom/{id}/delete |
Display a warning page before deleting an item | N/A |
POST | /custom/{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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
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.
Add a link to the /custom
route to the navigation section of your site’s base layout template. This should be clearly accessible via the navigation menu or a similar structure.
You are encouraged to reuse the content from your existing template for displaying all custom menu items here. Each custom menu item should include a link to the /custom/{id}
route for that 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 /custom/{id}/edit
and /custom/{id}/delete
routes, as well as a link to the main /custom
route.
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.
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:
/custom
- find the item to delete and click the link to see details./custom/{id}
- click the delete link to delete the item./custom/{id}/delete
- see a warning page about deleting, and click the delete link again./custom/{id}/delete
- browser sends a POST request to this URL to delete the item (this is invisible to the user)/custom
- browser is redirected back to the main pageAt the end of this project, you should create a new UML diagram for the project that includes the new web application classes. It should also show the links to other classes/packages in the application, but those items do not require any details (they can just be simple boxes containing the class or package name.)
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
This assignment will be graded based on the rubric below:
CustomItem
class - 10%CustomItemList
class - 20%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
This page lists the milestone requirements for Milestone 13 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
The CC 410 Restaurant Project project for this semester is centered around building a point of sale (POS) system for a fictional restaurant named Game Grub, offering food of all kinds to celebrate our love of games of all kinds.
The thirteenth milestone involves adding form validation and serialization to the existing project, specifically targeted at custom menu items.
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.
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:
name
of the custom menu item should not be null, and have at least 4 characters.price
of the custom menu item must be greater than or equal to 1.50, 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.calories
of the custom menu item must be an integer greater than or equal to 250.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.
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.
CustomItemList
class is created. In Java, this would most likely be the getInstance()
method, while in Python it would be in the __new__()
method. So, when the user first visits the /custom
page, the previously saved custom items should appear.CustomItemList
class should implement a new method called save
that will serialize the current contents of the custom item list to a file.CustomController
with the path /custom/save
that will save the existing custom items list to file by calling the new save
method./custom
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
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.
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.
A complete final project should include the following features:
gradle
or tox
) and test frameworks. The goal is to use the tools learned throughout the semester to build a different project and focus on the design of the code, not learning new tools or languages.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. This project should be roughly 1/4 to 1/3 the size and scope of the semester-long restaurant project.
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.
README
file that describes your project, including how to compile and run it.README
file as well.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 60%.
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.
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.
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.
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.
This project should include the following features:
HelloWorld
class that contains a main
method.
main
method should print “Hello World” if no command line arguments are received.main
method should print “Hello {arg}” if a command line argument is received.HelloWorld
class, properly testing both with and without command-line arguments..py
files should also include a file docstring, including __init__.py
and __main__.py
files for packages.HelloWorld
class must include explicit data types
HelloWorld
class must not use Any
as a type.Completing this project is estimated to require 2-5 hours depending on familiarity with the tools involved.
This assignment will be graded based on the rubric below:
HelloWorld
class - 30%The following deductions apply:
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.
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.
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.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
sfsubs.data.entrees
packagesfsubs.data.sides
packagesfsubs.data.drinks
packagesfsubs.data.enums
packageSee 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
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 entrees and start there. Once you have the entrees all working, the sides and drinks are pretty easy and use much of the same structure. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
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):
price
attribute would have a getPrice
getter and setPrice
setter method.__price
attribute would have a getter and setter named price
implemented as a Python Property.Each entree should be stored in an appropriately named class in the sfsubs.data.entrees
package. Each entree should include an attribute for the following data:
Base
value (see below). It should have a getter and setter method.Topping
values (see below).
In addition, each entree 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.
double
or Python float
value representing the base price of the item plus any upcharge associated with the chosen Base value.int
value representing the number of calories associated with the item.String
values or a Python list of str
values.
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 entree class should also override the default string representation method (toString()
in Java or __str__()
in Python) and return a string that properly describes the entree. The string should be formatted as “{entree name} on {base}”, 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 entree description will include a list of ingredients included on the entree. 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 Sauce”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message. If all ingredients are at their default values, the Instructions list should be empty.
Each entree will be served on a particular Default Base, and will include a default set of Toppings. Those attributes should be populated appropriately in the constructor for the entree. Changes to the Base and Toppings attributes will not affect the Instructions attribute at this time (we’ll add that later).
The number of Calories for a entree will remain constant, regardless of other attributes (we’ll just pretend that changing the base or toppings doesn’t change the number of calories).
The Price for a entree will change based on the value selected for the Base. Each entree will have a base price listed for the Default Base option. Other bases include an associated upcharge or discount, which must be adjusted.
This means that the prices shown on the menu already include the upcharge for the given default base. You may want to calculate and store a base price for the item by removing the upcharge from the menu price.
just like the man himself, this sandwich “hams” it up and is super “cheesy”
sfsubs.data.entrees.Kirk
- The price is $7.35 and it is 650 calories. Served on White Bread with Ham and Cheese. Comes with Lettuce, Tomato, and Mayo.
a sandwich tasty enough for any “voyager” to enjoy
sfsubs.data.entrees.Janeway
- The price is $10.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 ultimate judgement of humanity, a “continuum” of meats
sfsubs.data.entrees.Bbq
- The price is $12.25 and it is 1375 calories. Served on White Bread with Brisket, Pulled Pork, Sausage, and Bacon. Comes with Onion, Pickles, and BBQ Sauce.
our “number one” sandwich
sfsubs.data.entrees.Riker
- 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
a most logical choice
sfsubs.data.entrees.Spock
- The price is $6.50 and it is 700 calories. Served on Wheat Bread with Cheese. Comes with Lettuce, Tomato, Onion, Pickles, Peppers, Olives, and Mayo.
Each side should be stored in an appropriately named class in the sfsubs.data.sides
package. Each side should include an attribute for the following data:
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.
double
or Python float
value.int
value.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
.
crispy, crunchy potato chips seeking to understand human emotions
sfsubs.data.sides.Data
- Small: $2.75 and 250 calories. Medium: $2.25 and 350 calories. Large: $3.50 and 550 calories.
a round cookie and two gherkin “nacelles” in honor of the best ship in the fleet
sfsubs.data.sides.Enterprise
- Small: $2.98 and 170 calories. Medium: $3.77 and 340 calories. Large: $5.55 and 510 calories.
it is “futile” to “resist” these identical square pretzel bites wrapped in foil
sfsubs.data.sides.Borg
- Small: $3.55 and 375 calories. Medium: $4.15 and 565 calories. Large: $6.65 and 780 calories.
Each drink should be stored in an appropriately named class in the sfsubs.data.drinks
package. Each drink should include an attribute for the following data:
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.
double
or Python float
value.int
value. It should have a getter method.String
values or a Python list of str
values.
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 flavors that may be added. Those flavors 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 {flavor}” message, such as “Add Cherry”, to be added to the Instructions list. Likewise, changing it back to false
will remove the appropriate message.
In addition, drinks may specify default flavors that 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 {flavor}” message, such as “Hold Coconut”, to be added to the Instructions list. Likewise, changing it back to true
will remove the appropriate message.
If all flavors are at their default values, the 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
. Changes to the Size attribute will not affect the Instructions attribute.
tea, Earl Grey, hot
sfsubs.data.drinks.Picard
- Tea served with Lemon. Can optionally add Ice. Small: $0.95 and 5 calories. Medium: $2.35 and 10 calories. Large: $2.25 and 15 calories.
the ultimate comfort drink inspired by a chocolate sundae
sfsubs.data.drinks.Troi
- 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.
a warrior’s drink
sfsubs.data.drinks.Worf
- Prune Juice. Can optionally add Ice. Small: $1.25 and 150 calories. Medium: $2.25 and 225 calories. Large: $2.55 and 415 calories.
Each enumeration should be stored in an appropriately named class in the sfsubs.data.enums
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.
an upper deck and a lower deck is important for any sub
sfsubs.data.enums.Base
- White Bread (no upcharge), Wheat Bread (add $0.50), Sourdough Bread (add $1.00)
It is possible to create an enumeration that also stores additional data associated with each value, and then access that data through the enum value. You may be able to use this to simplify handling the upcharge for each base. Below are links to some sample code from later in this course that shows how to create such an enum and use that data.
options to fit any appetite
sfsubs.data.enums.Size
- Small, Medium, Large
don’t forget your KHAAAAAANNNNN!-diments
sfsubs.data.enums.Topping
- 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!
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.
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.
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:
__init__.py
and __main__.py
are exempt.application
plugin. The project should compile without errors. You may include a main class in a separate package for testing purposes only.This milestone should include the following features:
test
directory for the class it is testing.src
directory.java
or python
folder).Some quick tips from when I did this milestone:
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 entrees 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.ham
or cherry
) 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.@pytest.mark.parametrize("base", Base)
.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
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 entrees and start there writing unit tests. Once you have the entrees all working, the sides and drinks are pretty easy and use much of the same structure. There are several hundred 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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Each test class should contain unit tests for the following (this is not an exhaustive list, but should get close to 100% coverage):
Remember that unit tests should test a single unit of code. So, make sure your unit tests are as short and concise as possible to allow you to pinpoint individual errors.
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!
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.
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.
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 should include the following features:
sfsubs.data.Item
interface that is implemented by all entree, side, and drink classes
sfsubs.data.entrees.Entree
base classsfsubs.data.sides.Side
base classsfsubs.data.drinks.Drink
base classsfsubs.data.menu.Menu
that contains the full menu
Menu
class should containItem
interfaceMenu
and Item
should report near 100% code coverage.Menu
to confirm that each possible menu item is present in the menu.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 about 100 more unit tests in total. -Russ
This assignment will be graded based on the rubric below:
Item
Interface - 25%Entree
Base Class - 10%Side
Base Class - 10%Drink
Base Class - 10%Menu
Class - 20%Menu
Unit Tests - 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
The sfsubs.data.Item
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:
Each menu item (entrees, sides, and drinks) should be refactored to implement this interface. This will require some changes:
Entree
base class. This also means that newly instantiated items should no longer have an empty Instructions list. However, it may be simpler to populate the list when it is requested instead of storing it.Side
base class.Accordingly, the unit tests for some of these classes will need updated, as discussed below.
Each of the three types of menu items should directly inherit from a new abstract base class. These classes should not be instantiated!
sfsubs.data.entrees.Entree
is the base class for all entree items. It should include the following elements that are common to all entree classes:
sfsubs.data.sides.Side
is the base class for all side items. It should include the following elements that are common to all side classes:
sfsubs.data.drinks.Drink
is the base class for all drink items. It should include the following elements that are common to all drink classes:
You may choose to implement the Item
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 Item
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, though going through the base class makes things simpler down the road!
If you choose to inherit from the Item
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.
The sfsubs.data.menu.Menu
class should be a class that has static, class-level getter methods for these four elements:
entrees
- a list of Item
elements containing an instance of all available entrees (5 in total).sides
- a list of Item
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 (9 in total).drinks
- a list of Item
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 (9 in total).fullmenu
- a combined list of all menu items (23 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.
The following updates must be made to the existing unit tests in this project to accommodate these code changes:
Item
interfaceItem
interfaceItem
interfaceTo 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).
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.
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 a class to track orders made at the restaurant, a class for combo meals, and more. It also includes many different design patterns to improve the structure of the code.
This assignment will add several new classes to the project
sfsubs.data.order.Order
- this class should represent a collection of Item
objects that make up an order.
Item
object is contained in the collection. Recall that this should use the identity test, not the equality test.Item
s, with methods to add and remove items.
OrderNumberSingleton
class discussed below. It should only include a getter.Order
objects.sfsubs.data.combo.Combo
- this class should implement the Item
interface, and represent a combo meal consisting of an entree, a side, and a drink.
Entree
instance - the entree in the comboSide
instance - the side in the comboDrink
instance - the drink in the combonull
or None
in the constructor to represent a combo yet to be configured.null
or None
. You may have a single method, or one for each attribute.Item
interface:
discount
Discount Applied” if all items in the combo are present. If not, this entry should not be included.null
or None
. The name will only be set by the ComboBuilder
class discussed below, but users will also be able to configure a custom combo via the GUI that does not include a name.null
or None
initially.null
or None
, it is considered equal if the matching attribute is also null
or None
.
equals()
method on a null
object will result in an exception. So, you’ll have to check if each attribute in this object is null
first. If so, and the other object’s attribute is not null
, then they are not equal. If this object’s attribute is not null
, you can safely call equals()
on it, regardless of the other object’s attribute.sfsubs.data.combo.ComboBuilder
- a class that implements the Builder Pattern and Factory Method Pattern to build the available combos described below.
Combo
object indicated by that string (the name of the combo).You don’t have to create individual classes for the builder pattern in the ComboBuilder
class - it is sufficient to just have a private method for building each combo in the class itself. The full Builder pattern is a bit too much boilerplate code for this simple use.
sfsubs.data.order.OrderNumberSingleton
- a class that implements the Singleton Pattern to generate new order numbers.
There will also be several updates to existing classes.
Menu
- update to include the following items:
ComboBuilder
class discussed below.All new and updated classes in this milestone should contain full documentation comments. Every method should be completely documented!
No new unit tests are required for this milestone. They will be added in the next milestone.
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. -Russ
This assignment will be graded based on the rubric below:
Order
- 30%Combo
- 30%ComboBuilder
- 15%OrderNumberSingleton
- 15%Menu
class: 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
The Kirk, Enterprise, The Worf
The Riker, Data Chips, The Picard
The Janeway, Borg, The Troi
The Spock, Enterprise, The Picard
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.
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 writing unit tests for the order, combo, and associated classes created in the previous milestone. These unit tests will make extensive use of test doubles.
The following new classes should contain unit tests that achieve at or near 100% code coverage and adequately test all aspects of the class.
Order
Combo
ComboBuilder
OrderNumberSingleton
Test doubles must be used where noted in the discussion below. In general, any time a test refers to another class other than the one being tested, it should use a test double instead of an instance of that class.
In addition, some previous tests may need to be updated to match new requirements.
Menu
- add tests for combos and updated full menuOnce this milestone is complete, all classes in the following packages should have unit tests that achieve at or near 100% code coverage:
sfsubs.data.*
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
This assignment will be graded based on the rubric below:
Order
- 30%Combo
- 30%ComboBuilder
- 15%OrderNumberSingleton
- 15%Menu
unit tests: 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
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.
equals()
is called. Place one in the order, and use them to confirm that contains
returns both true and false when given two items that are equal but not the same instance.OrderNumberSingleton
that returns a value for an order number, then instantiate an Order
and verify that it received the given order number.Order
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 the tax
virtual attribute.null
or None
and handle that case properlynull
or None
Combo
instances, change the discount, and confirm that both use the new discount. This is best done by adding all items to each combo and checking the total price.For these tests, I recommend just checking the types of the entree, side, and drink items in the Combo returned, as well as the name, rather than using any test double objects. As before, you may wish to make these attributes visible to the test.
getNextOrderNumber()
several times and make sure each one is sequential.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.
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 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.
This milestone should include the following features:
sfsubs.gui
package to store all GUI code.sfsubs.gui.entrees
package to store all GUI panels for entrees.sfsubs.gui.sides
package to store all GUI panels for sides.sfsubs.gui.drinks
package to store all GUI panels for drinks.sfsubs.Main
class that properly loads and displays the program’s GUI.sfsubs.gui.PrimaryWindow
class that represents the main GUI window.
sfsubs.gui.MenuPanel
class to represent the main ordering screen panel.
sfsubs.gui.OrderPanel
class to represent the sidebar panel containing a user’s order.
sfsubs.gui.entrees
package for each entree.
EntreePanel
class to reduce the amount of duplicate code.SidePanel
in the sfsubs.gui.sides
package.
Side
class instead of individual sides themselves. When the buttons on the menu are clicked, you’ll need to make sure an instance of the correct menu item is created.sfsubs.gui.drinks
package for each drink item.
DrinkPanel
class to reduce the amount of duplicate code.Each of the menu item panels should also implement the following functionality:
sfsubs.gui
package do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.sfsubs.gui
package do not require unit tests at this time.sfsubs.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.sfsubs.gui
package and how all GUI classes are related. You should also show any links to the classes in the sfsubs.data
package, but you may choose to show simplified links between packages instead of individual classes. You do not have to include full details from classes in the sfsubs.data
packages.
sfsubs.gui.entrees
package are all related to similar classes in the sfsubs.data.entrees
package without listing the individual classes in that package.You are welcome to add additional methods to the existing content in the sfsubs.data
package. If so, make sure you include appropriate documentation, 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.
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
This assignment will be graded based on the rubric below:
Main
class - 2%PrimaryWindow
class - 4%OrderPanel
class - 4%MenuPanel
class - 20%SidePanel
class - 5%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
Below are some GUI sketches to help you visualize one possible GUI for a previous version of 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
Here are a couple of helpful pieces of code that you may wish to use in your project.
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 entree 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.
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 pizza 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 MenuPanel
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!
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.
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 dealing with the various events generated by the GUI and constructing a list of items that represent an order.
Changes to the previous milestone:
OrderPanel
panel.OrderPanel
to a tree element (Java JTree
or tkinter Treeview
). 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 OrderPanel
, the following should happen:
It may be helpful to maintain a hash map or dictionary in the OrderPanel
class that associates nodes in the GUI tree element with the actual Item
instances that they represent. This is in addition to the Order
object they will be stored in (added in a later milestone).
When the Save button in any of the entree, side, or drink panels is clicked, the following should happen:
OrderPanel
if it is a new item, or the item should be updated if it is being edited.PrimaryWindow
should be replaced with the MenuPanel
(this was part of the previous milestone).When the Cancel button in any of the entree, side, or drink panels is clicked, the following should happen:
PrimaryWindow
should be replaced with the OrderPanel
(this was part of the previous milestone for the Save button, and the code is similar).When the Edit button in the OrderPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.PrimaryWindow
and populated with the current data from the item (most of this should be present from the previous milestone, but much of it may be untested at this point).When the Delete button in the SidebarPanel
is clicked, the following should happen:
Item
that is currently selected should be determined. If the selection is an child of that item, the code should work upwards in the tree to find the related Item
.OrderPanel
class.Unit tests should be added to the corresponding test package for the following classes:
sfsubs.gui.entrees
sfsubs.gui.drinks
sfsubs.gui.sides
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 PrimaryWindow
, OrderPanel
, or MenuPanel
classes in this milestone. - Russ
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:
sfsubs.gui
package and sub-packages do require all appropriate documentation comments, and must be free of style errors. Every method must include full documentation comments.sfsubs.gui
base package do not require unit tests, but all entree, drink, and side panels require unit tests as outlined above.sfsubs.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.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 one of the more complex panels, and I used that as a template to create the rest of the unit tests. My current model solution contains ~850 unit tests, and I was able to achieve 100% code coverage on all GUI item panels. -Russ
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI portions, I’ll also be testing the functionality of the GUI for each class under review. - Russ
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.
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.
I found these methods helpful in my solution:
PrimaryWindow.addItem(item)
- basically a pass-through method that calls the OrderPanel.addItem(item)
method. This method would be accessible to all order item panels since they get a reference to the PrimaryWindow
instance.OrderPanel.addItem(item)
- adds a new item to the tree element, or updates the item if it is already contained in the tree.==
operator in Java, or the is
operator in Python. This means that you won’t be able to use the normal contains()
or in
method for determining if the item is already in a list - you must iterate through the list manually.OrderPanel.updateTree(item, node)
- handles actually updating the tree. If node
is null
or not provided, it creates a new one, otherwise it uses the existing node
and updates it. It should return the node
or that node’s id
when complete.Each entree panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each side panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).Each drink panel test class should contain unit tests for the following:
actionPerformed()
method with an invalid action command, and assert that an exception is not thrown (it should not do anything).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.
I ran into issues with Python not running unit tests in tox properly on this assignment. There are two causes:
DISPLAY
environment variable.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/sfsubs/data --html=reports/pytest-data/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/sfsubs/gui/entrees --html=reports/pytest-entrees/index.html
python3 -m coverage run --parallel-mode --source src -m pytest test/sfsubs/gui/drinks test/sfsubs/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.reports/pytest
folder will no longer be updated.coverage combine
command to combine the coverage data from multiple executions of pytest.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.
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 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.
This milestone introduces one new feature to the project. Instead of specifying a particular set of classes and structure, it is up to you as the developer to determine how to best implement this feature. Some hints are given in the related example project.
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:
Combo
class should handle this as defined in a previous milestone.OrderPanel
class will need to be updated to properly handle combos.
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:
PrimaryWindow
class/type as its parent, we can abstract that to a ParentPanel
interface that is implemented by both the PrimaryWindow
class and ComboPanel
. This allows the existing order item panels to use the new ComboPanel
as its parent.ComboPanel
ComboPanel
instead of PrimaryWindow
)PrimaryWindow
to add the item to the order.data
package as desired.PanelFactory
since it could be used from within ComboPanel
, but also will be used to create instances of ComboPanel
. A way to resolve this would be to create a ComboPanelFactory
to handle combos, and adapt the code where PanelFactory
is used to direct combo instances to the new ComboPanelFactory
instead.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:
Combo
object when it is saved.Combo
object when it is saved.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
.
This assignment will add one new class to the project
sfsubs.gui.PanelFactory
- a class that implements the Factory Method Pattern to return an instance of a GUI panel for a given entree, side, or drink.
PrimaryWindow
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 the parent
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 the name
is not recognized, an exception should be thrown.Item
item, PrimaryWindow
parent) should accept an instance of an Item
and return a panel that represents that item, with the parent
GUI element as its parent. If the item
is not recognized, an exception should be thrown.There will also be several updates to existing classes.
MenuPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the action command received from button that was clicked.OrderPanel
- update to include the following items:
PanelFactory
class to acquire the appropriate GUI panel based on the item selected in the tree.Order
instance as well.
OrderPanel
constructor.Order
instance and reset all appropriate GUI elements for a new order. This will delete any existing order.
All new and updated classes in this milestone should contain full documentation comments. Every method should be completely documented!
Some previous tests may need to be updated to match new requirements.
Once this milestone is complete, all classes in the following packages should continue to have unit tests that achieve at or near 100% code coverage:
sfsubs.data.*
sfsubs.gui.drinks.*
sfsubs.gui.entrees.*
sfsubs.gui.sides.*
The only classes that do not meet this requirement are PrimaryWindow
, OrderPanel
, PanelFactory
, and MenuPanel
in the sfsubs.gui
package.
Any new classes created to handle editing combos should include unit tests. Refer to the associated example project for some ideas of how to unit test that class.
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
This assignment will be graded based on the rubric below:
PanelFactory
OrderPanel
- 20%MenuPanel
- 10%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. - Russ
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.
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.
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 finalizing the GUI for creating orders and 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.
Implement the following features into your existing project.
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:
edu.ksu.cs.cc410.register
package.cc410.register
package.When the user clicks the “Checkout” button in the GUI, they should be presented with the following options:
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.
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.
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 only 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 not 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:
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).
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 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 indentations 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.
All new and updated classes in this milestone should contain full documentation comments. All methods must be fully documented!
Your application should include unit tests to test any functionality provided by your application. Specifically, you should test the following:
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 highly 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:
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.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.
ReceiptPrinter
wrapper that accepts an Order
object and returns a list of strings that represent the receipt to be printed. Verify that the contents of that list fully reflect the Order
given to it.
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
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.
You may wish to review the Spinner (Java) or Spinbox (Python) GUI elements.
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.
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 moving into the web by creating a data-driven website to display the menu and some other information about the restaurant.
Add a Web Framework to the existing project.
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.
sfsubs.web
package.sfsubs.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. You may add additional text and items as desired/menu
- a page that includes the entire menu (all predefined combos, entrees, sides, and drinks).
Menu
class to collect these items.Menu
class as desired to make this work.Create a base layout file including the following:
- About Starfleet Subs
Create the following template files to match the routes listed above:
index.html
contains an <h1> tag with the title “Homepage” 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:
menu-item
. It should include:
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
Below is a screenshot from a previous model solution for some web design inspiration.
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.
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 augmenting the menu display from the previous project by adding search and filtering functionality via an HTML form.
This milestone adds several pieces of functionality to your existing website, mostly based around searching and retrieving menu items.
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.
You should also handle the case where keyword searches will return a combo if it contains an item that matches the search term. For example, a search for “chess” should not only return that entree, but also any combos that include that item.
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.
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:
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.
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<Item> items, String keywords) - returns Iterable<Item>
filterTypes(Iterable<Item> items, boolean entree, boolean side, boolean drink, boolean combo) - returns Iterable<Item>
filterPrice(Iterable<Item> items, float min, float max) - returns Iterable<Item>
filterCalories(Iterable<Item> items, int min, int max) - returns Iterable<Item>
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.
In the method signature above, the Iterable
class is simply an interface. In Java, you can use a List
subtype such as LinkedList
that supports that interface. In Python, the base List
type will also work. - Russ
Menu
class require unit tests to achieve 100% coverage. You should use test doubles in these unit tests, and make sure you are testing all possible outcomes.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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
This page lists the milestone requirements for Milestone 12 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
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 twelfth milestone involves building a RESTful web application that could be used to manage custom menu items.
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.
Create a class sfsubs.data.custom.CustomItem
that can represent a custom menu item. It should implement the Item
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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
Create a class sfsubs.data.custom.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.
The class should include full documentation comments. 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.
Create a new web controller named CustomController
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 | /custom |
Display all custom items. | Read All |
GET | /custom/new |
Display a form to create a new item. | N/A |
POST | /custom |
Create a new custom item | Create |
GET | /custom/{id} |
Display a single custom item | Read One |
GET | /custom/{id}/edit |
Display a form to edit the custom item | N/A |
POST | /custom/{id} |
Update the custom item | Update |
GET | /custom/{id}/delete |
Display a warning page before deleting an item | N/A |
POST | /custom/{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.
The class should include full documentation comments. You do not have to create any unit tests for this class.
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.
Add a link to the /custom
route to the navigation section of your site’s base layout template. This should be clearly accessible via the navigation menu or a similar structure.
You are encouraged to reuse the content from your existing template for displaying all custom menu items here. Each custom menu item should include a link to the /custom/{id}
route for that 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 /custom/{id}/edit
and /custom/{id}/delete
routes, as well as a link to the main /custom
route.
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.
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:
/custom
- find the item to delete and click the link to see details./custom/{id}
- click the delete link to delete the item./custom/{id}/delete
- see a warning page about deleting, and click the delete link again./custom/{id}/delete
- browser sends a POST request to this URL to delete the item (this is invisible to the user)/custom
- browser is redirected back to the main pageAt the end of this project, you should create a new UML diagram for the project that includes the new web application classes. It should also show the links to other classes/packages in the application, but those items do not require any details (they can just be simple boxes containing the class or package name.)
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
This assignment will be graded based on the rubric below:
CustomItem
class - 10%CustomItemList
class - 20%The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.
This page lists the milestone requirements for Milestone 13 of the CC 410 Restaurant Project. Read the requirements carefully and discuss any questions with the instructors or TAs.
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 thirteenth milestone involves adding form validation and serialization to the existing project, specifically targeted at custom menu items.
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.
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:
name
of the custom menu item should not be null, and have at least 4 characters.price
of the custom menu item must be greater than or equal to 1.50, 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.calories
of the custom menu item must be an integer greater than or equal to 250.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.
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.
CustomItemList
class is created. In Java, this would most likely be the getInstance()
method, while in Python it would be in the __new__()
method. So, when the user first visits the /custom
page, the previously saved custom items should appear.CustomItemList
class should implement a new method called save
that will serialize the current contents of the custom item list to a file.CustomController
with the path /custom/save
that will save the existing custom items list to file by calling the new save
method./custom
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.
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
This assignment will be graded based on the rubric below:
The following deductions apply:
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.
As part of the grading of all assignments in this course, I will be doing a deep dive into a few classes in your code. This will include leaving detailed comments on code style and format in GitHub. I will usually choose various classes to review at random, and any issues found in that class will be verified in other classes of the same type. For any GUI and Web portions, I’ll also be testing the functionality of the UI for each class under review. - Russ
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.