This is an individual lab.
Most students are used to calculators which have parentheses so users can control the order of operations. For example, you might enter 3 + (4 * 5) to compute 23. An alternative that was popular decades ago was to use RPN which allowed you to enter the numbers and then apply operations. The HP-35 was one such calculator. See this HP-35 emulator. To use it, click on the 3, ENTER↑, 4, ENTER↑, 5, ×, +, and notice the calculator displays 23.
You are being given an implementation of a similar calculator. For most
students, you will get the code through GitHub Classroom, but this code
is also available in the file calculator.zip
. While
this calculator uses RPN, it has other key differences from the HP-35.
You will not attempt to emulate the HP-35. Instead, you will extend the
provided calculator so it supports undo and redo through the Command
pattern.
To get started, check out (or download) the code and open the project in
IntelliJ. Attempt to build CalculatorTest
. If you have errors saying
"package org.junit does not exist
", then open
CalculatorTest.java
(in IntelliJ) and select
"Add 'JUnit5' to classpath". This will cause IntelliJ to prompt you
to download the library from the Maven Repository; click OK. Once
built, right click on CalculatorTest
in the project browser and
execute all of the tests. These test just the basic calculator
operations; they do not test undo and redo. You will test those in other
ways.
Once the built-in tests are working, confirm that your calculator works through the console. Run the program and enter the bold-face text as shown below:
4,5*
Display: 4
Multiply
Display: 20
q
Quit
Final result: 20
To compute "(18 - 3) * 2", enter
18,3-2*q
Note the comma (,) roughly corresponds to the "ENTER↑" command on the HP-35; it signals that a complete number has been entered. A significant difference between this calculator and the HP-35 is that as values are computed, they are placed in an accumulator rather than on a stack. An operation such as add takes the current accumulator and the displayed value, adds them, displays the value, and stores that value in the accumulator. Thus if you enter **3,4,5* **, the calculator will replace the 3 by a 4 after the second comma, and the final result will be 20.
So you have an idea of where you are headed, the following shows what happens if the user decides to add instead of subtract and then goes on to do other operations:
18,3–2*
Display: 18
Subtract
Display: 15
Multiply
Display: 30
u
Undo
Display: 2
u
Undo
Display: 15
u
Undo
Display: 3
+
Add
Display: 21
2
*
Multiply
Display: 42
q
Quit
Final result: 42
Note that undoing the multiply (after displaying 30) results in displaying a 2 in the middle of this run; that is so the user knows what number (in this case, a 2) is being applied to the accumulator. This is the behavior you would probably see on a real calculator if that calculator supported undo and redo. If you would like to see a bit more explanation of this example, you might check out a video illustrating it.
Main.java
for the list of commands and their effects. The
commands echo to the screen; on a real calculator, these would be
replaced by (say) lights that show particular operations have been
executed. Several of your changes will be in Main.java
.Calculator.java
. This implements a
domain-level class capturing the calculator behavior, and its behavior has
been approved by your clients. Actions like adding numbers go through
class Calculator
- every operation you implement will use Calculator
methods to get their work done.Nothing to undo
or
Nothing to redo
. After executing an action, display the new
state of the calculator.History.java
is the History
class from the
phonebook example
with class Command
renamed to CalculatorCommand
. You should not
need to make any changes to History.java
or CalculatorCommand
.appendDigit
, the calculator
should be in the state that allows new numbers to be entered
(newNumber
should be true). That is, undoing most operations
means that the next digit starts a new number. Undoing appendDigit
should leave the next digit state as it was before the appendDigit
command was executed. That is, appendDigit
will need to save and
restore Calculator.newNumber
.Nothing to undo
or Nothing to redo
(as appropriate).Main.java
, and
implementing unexecute will boil down to figuring out what data to save
in execute and restoring the appropriate items in the unexecute. Remember
to call class Calculator
methods to do the work.Main.java
to use the add command rather than simply adding
values. Make sure you can handle an input sequence like 3,4+ud
.NOTE: Do not change any files in the .github
folder and do not change
Calculator.java
. If you do make changes to these by mistake, please talk to
your instructor and they will assist in correcting the issue.
Follow any directions in Canvas. If your instructor is having you submit
through GitHub Classroom, simply commit and push your changes and GitHub will
run your code. To see the results, log on to GitHub, visit the Actions
tab, and click on the most recent workflow run. The green checkmark indicates
all tests passed, the red x indicates at least one test failed. If you click
on the mark, you can then click on run-autograding-tests to see the
detail. Open Autograding Reporter and browse to the test runner summary
(see this example). The test runner summary shows you which test runs passed. In this particular case, only one passes and the student clearly has more work to do! To debug a particular test, run the program in IntelliJ using the test data in the corresponding file; these are in the console_test
folder in your project. The inputs and expected outputs for each test run are in this folder.
If none of the tests are running: expand Test 1 (by clicking the arrow) and check for compilation errors. If you do have compilation errors, make sure the project builds locally and that all changes have been committed and pushed.
Once your solution is working, make sure you have satisfied your instructor's coding standard. In particular, be sure to document any classes you write (including those we started for you). You do not need to document abstract methods when the base class already has accurate documentation. You may also need to format the code so the indentation is consistent. Finally, answer questions as required by your instructor.
From time to time we may need to update the starter code used for this assignment. If this happens, we will suggest updating your repository to merge the changes into your project. The steps for doing this: