p1-recipes

EECS 183 Project 1: Focaccia Bread

Project Due Friday, September 13, 2024, 8:00 pm Eastern (accepted for full credit until 11:59 pm)

In this project, you will write a program to help you purchase the correct amount of ingredients to make focaccia bread for a party.

By completing this project, you will learn to:

You will apply the following skills you learned in lecture:

Vocabulary

specification
magic number
diffchecker
development cycle
test input
sample run

Getting Started

Starter Files

You can download the starter files using this link.

The IDE setup tutorials for Visual Studio and XCode include a video about how to set up a project using the starter files. You can access the tutorials here:

Submission and Grading

Submit your code to the autograder here. You receive 4 submits each day and your best overall submission counts as your score. There are 60 possible points for correctness and 10 points for style.

The deadline is Friday, September 13, 2024 at 8PM Eastern. If your last submission is before Wednesday, September 11 at 11:59PM Eastern, you will receive a 5% bonus. If your last submission is before Thursday, September 12 at 11:59PM Eastern, you will receive a 2.5% bonus.

You have 3 late days that you can use any time during the semester for projects. There are 3 late days total, not 3 per project. To use a late day, submit to the autograder after the deadline. It will prompt you about using one of your late day tokens. There are more details about late days in the syllabus.

How to get help

Most students in EECS 183 need help from staff and faculty multiple times each project. We’re here for you!

If your question is about the specification or about something about the project in general, Piazza is the fastest place to get help.

You can meet with us for help in office hours. You can find details on group and 1-1 office hours here.

Collaboration Policy

We want students to learn from and with each other, and we encourage you to collaborate. We also want to encourage you to reach out and get help when you need it. You are encouraged to:

To clarify the last item, you are permitted to look at another student’s code to help them understand what is going on with their code. You are not allowed to tell them what to write for their code, and you are not allowed to copy their work to use in your own solution. If you are at all unsure whether your collaboration is allowed, please contact the course staff via the admin form before you do anything. We will help you determine if what you’re thinking of doing is in the spirit of collaboration for EECS 183.

The following are considered Honor Code violations:

The full collaboration policy can be found in the syllabus.

What are Specifications?

The project descriptions in EECS 183 are specifications, which tell you what your program needs to do when you are finished. Specifications don’t tell you how to write the program or the steps it takes for you to write the program with the least amount of work. That means that you have a lot of freedom. At the beginning, this freedom means that it is hard to know where to get started.

Take a look at the specification at the bottom of this page before moving on.

Making Smaller Parts

You probably noticed that there are many interconnected parts to this program. For example, the total cost depends on the number of packages of each ingredient, which depends on the number of loaves. Future 183 projects will have more parts that depend on each other in more complicated ways. Because of this, the first step in making a large program is breaking it apart into smaller parts. We’ll build up the program by programming one smaller part at a time.

One way to represent the way things are connected is with a picture. Here is one possible picture for this project:

Here is another:

Why work on one part at a time?

In programming, even experts make mistakes the first time they write part of a program. (The professors can’t write this project without making mistakes!) What makes expert programmers productive is the process they use as write their program which makes these mistakes easier to discover and fix.

As an example, let’s say that we completed Project 1 all at once, then got this incorrect output on a sample run.

Expected Output Actual Output
You need to make: 3334 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
834 bags of flour
2594 packages of yeast
1042 canisters of salt
198 bottles of olive oil

Total expected cost of ingredients: $5056.86

Have a great party!
You need to make: 1024 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
321 bags of flour
1194 packages of yeast
9342 canisters of salt
12 bottles of olive oil

Total expected cost of ingredients: $9322.32

Have a great party!

Notice how hard it is to find all the problems and also how it’s not clear where to start to fix them all. A bug in one part of the program might be affecting a later part of the program. To put this in the picture from earlier, we don’t know which of the steps is the problem:

Development cycle

A better way to write the program would have been focusing on getting one part 100% correct, and only moving onto the next part when it is finished. Here’s how we did this in our Project 1.

Because everything else depends on getting the number of loaves right, we decided to focus on that part first.

The development cycle describes 4 steps you can follow to build one small part to be 100% correct.

  1. Make examples of input and the correct output
  2. Find the pattern linking the input and output
  3. Write C++ code
  4. Test your code

You’ll be following these steps yourself to complete the rest of the project, so follow along with these steps in your IDE.

Step 1: Make examples of input and output

From the specification, we knew that every 4 people requires a loaf of focaccia. To make sure we understood, we wrote out a table of input (number of people) and output (number of loaves).

Input (people) Output (loaves)
11
21
41
52
00

Step 2: Find the pattern

Once we have the examples, we used them to find the relationship between them. In our experience, there’s a difference between knowing how to do something in your head and how to write it down or explain it to someone else. In this step, we write the algorithm we think will work, then check it against the examples. Most of the time, even for experienced programmers, it takes multiple guesses.

Guess 1: Divide the number of people by 4 using integer division.

Check:

Input (people) Output (loaves)
11 / 4 = 0 (not correct)

Guess 2: Divide the number of people by 4 using integer division, then add 1

Check:

Input (people) Output (loaves)
1(1 / 4) + 1 = 1
2(2 / 4) + 1 = 1
4(4 / 4) + 1 = 2 (not correct)

Guess 3: Divide the number of people by 4 using double division, then round up

Check:

Input (people) Output (loaves)
11 / 4.0 = 0.25 rounded up gives 1
22 / 4.0 = 0.5 rounded up gives 1
44 / 4.0 = 1.0 rounded up gives 1
55 / 4.0 = 1.25 rounded up gives 2
00 / 4.0 = 0.0 rounded up gives 0

All our examples match, which makes us confident this algorithm will work.

Step 3: Write C++ code

Now that we have the pattern, we need to translate the steps into C++. From Lecture 3, we remembered that to divide with double division, at least one of the operands needs to be of the type double. From there, we can round up the result using the ceil() function.

We wrote our code in the main() function of focaccia.cpp:

int main() {
   int people = 0;
   cout << "How many people do you need to serve? ";
   cin >> people;
   cout << endl;

   // this is a double to force double division
   const double PEOPLE_PER_LOAF = 4.0;
   int loaves = ceil(people / PEOPLE_PER_LOAF);

   // This code will say "loaves" even when there is only one loaf.
   // You will fix this in a later step.
   cout << "You need to make: " << loaves << " loaves of focaccia" << endl; 

   return 0;
}

Step 4: Test your code

Using the examples we thought of in Step 1, we can test whether our code works the way we expect by running the code in our IDE.

Input (people) Output (loaves)
1
2
4
5
0

Everything looks good, so we have evidence that we have both a correct algorithm and a correct C++ implementation of it.

Your turn: bags of flour

We’ll follow the same steps together for the next small piece of our program: computing the number of bags of flour.

Step 1: Make examples of input and output

The output of this piece of the program will be the number of bags of flour, but we could choose input to be either the number of people or the number of loaves. Using the number of loaves is the better choice, because we already know how to translate the number of people to loaves. We’ve given you some useful test inputs – your job is to compute what the outputs will be.

This isn’t a worksheet you need to hand in, so you can do this in your notes.

Input (loaves) Output (bags of flour)
11
9[your answer here]
30[your answer here]
7519

Step 2: Find the pattern

Guess 1: Multiply the number of loaves by 5 then divide by 20

Check:

Input (loaves) Output (bags of flour)
10.25 (not correct)

Do more guesses and checks until you find an algorithm that produces the output from Step 1.

Step 3: Write C++ Code

Let’s start by translating your algorithm into a single line of code by filling in the blank:

int flourBags = _________________________________;

What you likely found was that you had some magic numbers in that formula, like 20. Numbers without an explanation of what they mean are called magic numbers and are not allowed according to our style guide, because someone else reading your code will not know what they represent. The style guide directs us to put these into constants. Fill in the blanks in this revised version of the code that uses constants.

const double FLOUR_CUPS_PER_LOAF = _________________________________;
const double FLOUR_CUPS_PER_BAG = _________________________________;
// use these constants on the following line:
int flourBags = _________________________________;
// temporary; you'll need to change this later to get pluralization correct
cout << flourBags << " bags of flour" << endl;

Put this code in main() after the code computing the number of loaves.

Step 4: Test your code

Run your program, and use the examples you developed in Step 1 to test your program. Remember that the input to your program is the number of people, not the number of loaves! Here’s a table we used to help us test:

Input to program (number of people) Loaves Output (bags of flour)
1
9
30
75

Roadmap and Timeline

From here, finish the project by adding one small feature at a time. These were the steps we followed to finish Project 1:

  1. Compute number of loaves
    1. Printed correct one of “loaf” or loaves” in the “You need to make” output line
  2. Compute number of bags of flour
    1. Print correct one of “bag” or “bags” of flour
    2. Repeat for all ingredients
  3. Compute cost of bags of flour
    1. Add cost of bags of flour to total and print total
    2. Repeat for all ingredients
  4. Add header and footer messages
  5. Test entire program using sample runs in Sample Runs section
    1. Use diffchecker to compare program output and sample run (details in Sample Runs section)
    2. Debug problems discovered
  6. Submitted to autograder
    1. Debug problems that autograder reveals
  7. Read the style guide and verify code follows it

Timeline

As an approximate timeline, you are on track if by:

Things to get used to when programming

Spelling and spacing must match exactly

Computers pay attention to every little detail, so your program needs to match the sample outputs and the tests on the autograder exactly. This includes spelling, capitalization, and all symbols. The one exception is whitespace: the autograder will ignore differences in whitespace, like spaces and newlines. You will need to use a tool like diffchecker.com to find the differences in spelling, capitalization, etc., because humans aren’t good at spotting them.

It is normal when things don’t work the first time

Most of the skill in programming is in debugging and finding problems, since everyone makes them!

The autograder can find problems you didn’t see

For this project, the best time to submit to the autograder is as soon as you pass one of the sample runs. In general, you can’t assume that because the program works on your computer it will work on the autograder. Many times there are some adjustments that you need to make.

Specification

Your task for this project is to create a program that creates a shopping list for focaccia bread. Your program will ask the user how many people they need to serve, and will output how much of each ingredient is needed and what the total cost of the ingredients will be.

Ingredient List

Each loaf of focaccia requires:

Ingredient Cost and Conversions

Package of ingredient How to output in shopping list Cost Conversion
5 pound bag of flour
bag of flour
$2.69 20 cups in 5 pounds
package of yeast
package of yeast
$0.40 2.25 teaspoons per package
30 gram canister of salt
canister of salt
$0.49 5 grams per teaspoon
500 milliliter bottle of olive oil
bottles of olive oil
$6.39 14.8 millilitres per tablespoon
water Do not include in shopping list No cost. Do not include in total cost.

Pluralization

When the number of batches and the number of each ingredient is printed in the shopping list, the correct pluralization must be used. For example, “2 bottle of olive oil” is not correct, and needs to be output as “2 bottles of olive oil”. As a hint, you can use the pluralize() function to help you output the correct forms in your program.

Remember that the plural of “loaf” is “loaves”.

Output Format

Your program’s output must match the following template.

First, the program must ask the user how many people they wish to serve, and read in an integer from the user using cin. Each loaf feeds 4 people.

How many people do you need to serve?

Then, it should print the number of batches to make and the shopping list. You must make an integer number of batches and purchase an integer number of packages of each ingredient. The parts of the template that will change each run of your program are in bold red.

You need to make: 7 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
2 bags of flour
6 packages of yeast
3 canisters of salt
1 bottle of olive oil

Total expected cost of ingredients: $15.64

Have a great party!

If the number of cents in the total expected cost is a multiple of 10, do not print the trailing zeros in the decimal. For example, instead of $4.10, you must print $4.1 and instead of $10.00, you must print $10. You should not need to do anything for this to happen – if you use the default settings for cout, your code will pass this automatically.

Sample Runs

Diffchecker

Your program’s output must exactly match the specification, including spelling, symbols, and capitalization. The only way to know whether the output is an exact match is to use a tool called a diffchecker, which shows you where differences are. The staff’s favorite website for this is diffchecker.com. Paste the output of a sample run below into “Original Text” and your program’s output into “Changed Text”, then click “Find Difference” to highlight any differences. Note: the autograder will show its own diffchecker - diffchecker.com is helpful for comparing the output on your computer to the expected output below, not when viewing the feedback on the autograder.

The input to the program is given in bold red in these sample runs.

Sample Run 1

How many people do you need to serve? 1


You need to make: 1 loaf of focaccia

Shopping List for Focaccia Bread
--------------------------------
1 bag of flour
1 package of yeast
1 canister of salt
1 bottle of olive oil

Total expected cost of ingredients: $9.97

Have a great party!

Sample Run 2

How many people do you need to serve? 5


You need to make: 2 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
1 bag of flour
2 packages of yeast
1 canister of salt
1 bottle of olive oil

Total expected cost of ingredients: $10.37

Have a great party!

Sample Run 3

How many people do you need to serve? 40


You need to make: 10 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
3 bags of flour
8 packages of yeast
4 canisters of salt
1 bottle of olive oil

Total expected cost of ingredients: $19.62

Have a great party!

Sample Run 4

How many people do you need to serve? 90


You need to make: 23 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
6 bags of flour
18 packages of yeast
8 canisters of salt
2 bottles of olive oil

Total expected cost of ingredients: $40.04

Have a great party!

Sample Run 5

How many people do you need to serve? 2000


You need to make: 500 loaves of focaccia

Shopping List for Focaccia Bread
--------------------------------
125 bags of flour
389 packages of yeast
157 canisters of salt
30 bottles of olive oil

Total expected cost of ingredients: $760.48

Have a great party!

How to Submit

When you’re ready to submit, visit the autograder.

Click “Choose files to upload” and navigate to your file. The file you submit to the autograder MUST be called focaccia.cpp.

If you’re using Xcode and don’t know how where exactly focaccia.cpp is located on your disk, right-click (or click while holding down the Control key) on the file in the Navigator area on the left side of the Xcode window and choose Show in Finder.

If you’re using Visual Studio and would like to know where focaccia.cpp is on your disk, right-click on focaccia.cpp in the tab above the Code pane and choose Open Containing Folder.

Once you’ve selected the correct file, click Submit to submit to the Autograder. The autograder will tell you if you did not select a file of the correct name.

Style Guide

Your code must follow the EECS 183 style guide, linked here.

Project 1 Style Rubric

Top Comment

Must have name, uniqname, program name, and project description at the top of the file.

Readability violations: -1 for each of the following categories

Category Possible Violations - i.e., these are bad
Top Comment
  • Missing any of the name, uniqname, program name, and project description at the top of the file.
Indentations
  • Not using a consistent number of spaces for each level of code indentation
  • Not indenting lines at all
    • Failing to indent the blocks of code inside curly braces
Spacing
  • Not putting a space around operators
    // good - do this
    total = units * cost;
    count = 0;
    
    // bad - do not do this
    total=units*cost;
    count=0;
    
  • Not putting a space before and after the stream insertion and extraction operators (e.g cout<<loaves; instead of cout << loaves;)
  • Spaces around parentheses - function headers and calls should not have a space between the function name and opening parenthesis.
    // good - do this
    pluralize("person", "people", people);
    
    // bad - do not do this
    pluralize ( "person" ,"people" , people );
    
Bracing (Scope)
  • Using a mix of Egyptian-style and hanging braces
    • Egyptian-style: { at the end of a statement
    • Hanging: { on its own line
  • Note: Braces must always be used for conditionals, loops, and functions.
Variables
  • Variable names not meaningful
  • Inconsistent variable naming style (camelCase vs. snake_case), excluding const variables, which are always SNAKE_CASE
  • Not using all uppercase SNAKE_CASE for const variable names
  • Using variable types that do not make sense in context
Line Limit
  • Going over 80 characters on a line
    • Includes lines of comments and lines of code
Statements
  • More than one statement on a single line
    • A statement ends in a semicolon
Comments
  • Commenting on the end of a line of code
    // A comment should be placed before a line of code - this is good
    int count = 0; // NOT on the same line as the code - this is bad
    
  • Insufficient comments or excessive comments
    • Note: code should be thoroughly commented such that lines’ functionality is apparent from comments alone or from quickly glancing at code
    • Example of appropriate comment:
      // calculate the area of the circle 
      double area = pi * radius * radius; 
      
    • Example of excessive comments:
      // declare variable for area 
      double area;
      
      // calculate area using the equation: area = Pi * r^2
      double area = pi * radius * radius;
      
  • Unneeded comments left in the code, such as:
    // your code goes here
    // FIXED
    
  • Commented out code, such as:
    // double area = 3.141527 * radius * radius;
    

Coding quality: -2 for each of the following categories

Category Possible Violations - i.e., these are bad
Global Variables Global variables not declared as const
Magic Numbers
  • Integer and/or double literals used such that it is unclear to a reasonable reader what the literals represent
    • 0, 1, and 2 never count as magic numbers
Egregious Code
  • Logic that is clearly too involved or incorrect
    • e.g. instead of basing numbers on conversions, writing:
      if (loaves == 1) {
          //do something
      } else if (loaves == 2) {
          //do something else
      } 
      // and so on
Function Misuse Not calling pluralize() when appropriate