Homework #8 CMSC 131
Due May 9, 6:00 pm Object-Oriented Programming I
Type of Homework: Open Spring 2005

Objective

This homework will give you practice in parsing, inheritance, interfaces, event-driven programming, packages, ArrayList, and designs involving programs that use the MVC (Model-View-Controller) model of interaction.

In case you have not already noticed, this is an Open homework.  You must read the Open/Closed policy before working on this project.  The policy can be found at policy

Overview

Your company wants to build a suite of interactive calculators, e.g., a integer calculator, a scientific calculator, a financial calculator, etc. For this homework, you will create a generic calculator class, called GenericCalcEng (Generic Calculator Engine), which provides a general framework for the implementation of several types of calculators.  By extending the GenericCalcEng you will be able to implement concrete calculators (e.g., scientific, financial, etc.). 

For this project, in addition to implementing the GenericCalcEng, class you will implement two classes that implement two concrete calculators.  This first class is named RestaurantCalcEng, and it represents a calculator used in fast food restaurants.  The second one is named ScientificCalcEng, and represents a typical scientific calculator.   

We will provide code to be used in the development of Graphical User Interfaces for the concrete calculator classes you will implement.  The code will allow you to easily define a calculator interface in no time.  More details about the program are provided in the Specifications section.

Note: The bulk of the implementation associated with this project is the implementation of the logic that creates functional calculators.  This logic is what the JUnit module (that you will create) will test.  Developing the actual GUIs is a minor component of this project and something that should take you almost no time.  For example, if you choose not to implement the GUIs for the calculators you will notice that you will pass all the tests in the submit server, as we don't check for that component via the submit server.  The graders will check the GUIs manually.  Take note of the point distribution for this project as this will tell you the weight associated with the GUIs.

This homework will be graded as follows:

Calculator Operation Model

Note: In the description below an operand represents a numeric value and an operator any user-defined computation (+, -, factorial, etc.) 

Most numerical calculators process the following type of operations:

Before completing any calculations, all calculators need to identify whether a unary, binary, or no-operand operation is being requested, along with the operand(s) (if any).  Once the identification has been made, the actual processing (determined by the operand) will take place.  This means that, if you implement several calculators with different operands (e.g., a scientific,  restaurant and binary calculators), parts of your processing will be common to all calculators.  Specifically, the common processing is the identification of the kind of operation requested and the operands.  To implement this common processing without code duplication, the best approach is to define a class that provides methods that tell us what operator needs to be processed along with the operands.  By using this class, we need only worry about implementing the computation associated with each particular operator. For this project you will implement such a class.  We name this class GenericCalcEng (Generic Calculator Engine), because, as its name implies, it provides the generic behavior associated with any calculator.  The class identifies operators and operands, and provides support for common operations found in any calculator (e.g., processing of backspaces, reset, etc.).  This class cannot generate any results.  It just identifies what needs to be done and relies on a subclass to actually implement the processing associated with an operator. 

Implementing a calculator using GenericCalcEng

    Let's suppose you want to implement a simple floating-point calculator that supports the operators +, -, *, /, =, backspace, and reset.  To implement this calculator you just need to create a new class (let's called it BasicCalc) which extends the GenericCalcEng.  By extending GenericCalcEng, BasicCalc doesn't need to implement the backspace or the reset operation as those are already provided by the base class.  Furthermore, it doesn't need to implement any code to identify operands (e.g., reading digits) or code that identifies operators.  All this processing is taken care of by GenericCalcEng.  What does BasicCalc implement? It provides the GenericCalcEng with a list of the operators (the name and type) the BasicCalc will process.  In addition, it provides the implementation of abstract methods present in the GenericCalcEng class.  One of these  methods takes care of processing unary operations, the other takes care of binary operations and a third one is in charge of processing constants.  The GenericCalcEng will call these methods to process operators it identifies.  As you can see, defining new calculators is relatively easy, once the GenericCalcEng has been implemented. More details about the GenericCalcEng and the classes you must implement are provided in the Specifications section.

Code Distribution

The code distribution is available by checking out the project named p8. The code distribution provides you with the following:

Calculator Library (We provide this.)

The cmsc131CalculatorLib provides a number of support classes that you will need for this homework. The classes you will find in this package are:

Java Files (We provide these.)

Specifications

GenericCalcEng Class

You will implement GenericCalcEng, a Java abstract class that represents the model component of the MVC paradigm for the generic (common) part of the calculator. The generic calculator can be tailored to recognize any unary and binary operators we want to implement. The generic calculator "parses" (that is, it syntactically classifies or recognizes) operators and operands and passes those values to methods in the derived classes that will take care of implementing the operator.

GenericCalcEng Operators

We can classify the GenericCalcEng operators into the following categories or types:

GenericCalcEng Operands

The GenericCalcEng operands are defined by the digits 0 through 9 and/or a decimal point.  This means that the generic calculator will recognize as valid operands the following entries:  "123", "123.45", "0", "0.56".  There is no need for a '-' sign, since negation (if needed) is handled at the operator level (e.g., unary +/-). 

GenericCalcEng Public Operands

The public methods of the GenericCalcEng class are:

Feel free to add any additional private methods as you see fit.  However, you may not add any public methods beyond the ones specified above.

Further Discussion of the processSelection( ) Method

As mentioned above, the processSelection method does not apply any binary or unary operators, since this is done in the concrete derived classes (e.g., ScientificCalcEng). For example, if the operator is the binary operator "+", then processSelection will call a method in the derived class to apply the addition operator. (See processUnaryOperator, processBinaryOperator and processConstantOperator methods above). On the other hand, operators that are deemed to be common to all calculators (e.g., ASSIGN_OP, CLEAR, CLEAR_LAST_OPERAND, BACKSPACE) are implemented by this method.

For purposes of testing, it is necessary that you implement your calculator functions in the same way that we do. If you consider the calculator's behavior when the user keys in the sequence "3 4 + 5 6 =" the number "34" is the first operand, the operator is "+", and the second operand is "56". When "=" is seen, the binary operator "+" is applied, and the resulting sum of "90" is displayed. How does the calculator know that "3" and "4" are parts of the first operand and "5" and "6" are parts of the second operand? The calculator is controlled by its state, which is made up of the following variables:

Keep in mind that you can add any other instance variables you see fit and you don't need to use exactly the variable names we provided.

The calculator's operation depends on the context. The possible contexts (states) are:

Semantics of GenericCalcEng Operators

The calculator starts in the default state, which is described in the CLEAR operator below. In the description below, the term current operand refers to either firstOperand or secondOperand, depending on the current context, RFO or RSO, respectively.

Creating calculator engines using the GenericCalcEng class

In order to have an operational calculator we must extend the GenericCalcEng class. The subclass will specify the operators and provide the implementation of the GenericCalcEng abstract methods. The class CalcEngExample, part of the code distribution provides an example of creating a very simple calculator based on the GenericCalcEng.

Adding a GUI

Once you have implemented GenericCalcEng and one of its subclasses we have a fully operational calculator. However, it is not one that is easy to use. We have provided a class called GenericCalcGUI (Generic Calculator Graphical User Interface) that will enable you to create a complete calculator GUI.

We will describe the process for a basic floating-point calculator (which you do not need to implement for this project). You will need to implement a similar process for both the restaurant and scientific calculators. The setup for these is exactly analogous to the basic calculator (just replace "Basic" with "Restaurant" or "Scientific" below). As you read this, please refer to the file GUIExample.java (given in the code distribution). It illustrates how to create a simple GUI with a couple of buttons. The behavior of GUIExample.java is trivial, and simply echoes back the user's selection.

In order for your calculator to possess the desired functionality, you must create a second instance variable in your BasicCalc class. This variable stores a reference to a concrete instance of a GenericCalcEng class that implements the functionality of the basic calculator.  Let's call it engine. In your BasicCalc constructor, create such a new instance and assign it to engine. Now, when the buttonSelected() callback is called, it needs to perform the following operations:

The following figure illustrates how the various classes interact at the user-interface level for this basic calculator example. The picture is similar for the restaurant and scientific calculator.  Remember, you don't need to implement this basic calculator.  We are just using it as an example of how to set up a GUI for any calculator.

Your Assignment

Classes you must define

For this homework you must define the following classes:

double value = 78.123;
DecimalFormat decimalFormat = new DecimalFormat("0.00");
String valueStr = decimalFormat.format(value);

                              A value of "78.12" will be stored in valueStr.

Packages you must define

In order to gain experience in designing a programming project involving packages, you must create the following packages and arrange your classes as described below. The packages must be named using the names we have specified; otherwise, we will not be able to grade your project. (Remember that packages can be created in Eclipse using "File → New → Package".)

Requirements

Sample Run

In this section we present two snapshots of the calculators you are expected to implement.  This will guide you in determining how to set up the GUIs.  If you take a look at the PublicTests.java file and the pub*.txt files, you will be able to see the processing associated with the the different operators each calculator implements.  As you can see, you can tests your implementation without using GUIs. 

Here is an example that shows two snapshots of the calculators you are expected to implement, in their initial states.

 

Writing a JUnit Test

We have provided a JUnit module representing the public tests.  However, you need to create your own JUnit module to test your project.  Define the tests as you see fit.  We expect at least three tests in the JUnit file.  Name your JUnit test file "MyJUnitTests.java".   Feel free to use the TestsSupport.processSeveralSelections method to process different key combinations, as we did in the PublicTests.java.


Challenge Problem

Remember that you are not required to implement the following problem. Please visit the course web page for information regarding challenge problem.

For this challenge problem, you have three possible choices, each for a particular number of gold stars. If you want to implement them all that is fine, however we can only grade one. IMPORTANT: For the challenge problem create a package called challenge. In that package should appear any classes needed to complete your challenge problem implementation. The challenge problems below may require you to modify the GenericCalcEng and other classes of your homework. Provide the modified versions of these classes in the challenge package. Make sure you provide, in the challenge package, a Challenge.java file with a main method that allows us to run the challenge problem calculator. Also make sure that your Challenge class has a default constructor.

Note: For the challenge problem you must use the scientific calculator. Make an entry in the timelog indicating which Challenge problem choice you have implemented.

Choice 1 (1 Gold Star)

Add an option to the calculator that allows the display to show the results using commas. For example, instead of "12345" the user would see "12,345". You should add a button to the GUI labeled "com" that allows the user to turn this feature on and off.

Step 2 (1 additional Gold Star, for a total of 2)

In addition to Choice 1, add the following memory functions to the calculator infrastructure:

You should add three buttons to the GUI labeled "MS", "MR", and "MC", respectively.

Choice 3 (1 additional Gold Star, for a total of 3)

In addition to Choice 1 and Choice 2, add parenthesis semantics to the calculator infrastructure. That means your calculator can process expressions surrounded by parenthesis, regardless of the level of nesting. You should add two buttons to the GUI labeled "(" and ")".

Feel free to place the GUI buttons wherever you consider to be best.


Submission

Submit your project using the submit project option associated with Eclipse. Remember to complete your time log before submitting your homework.