联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> Java编程Java编程

日期:2018-12-17 09:44

Project Requirements

Create a new Eclipse workspace named "Project_1234567890" on the desktop of your computer (replace

1234567890 with your student ID number). For each question below, create a new project in that workspace. Call

each project by its question number: "Question1", "Question2", etc. If you do not remember how to create a

workspace or projects, read the "Introduction to Eclipse" document which is on iSpace. Answer all the questions below.

At the end of the project, create a ZIP archive of the whole workspace folder. The resulting ZIP file must be called

"Project_1234567890.zip" (replace 1234567890 with your student ID number). Upload the ZIP file on iSpace.

Here are a few extra instructions:

Give meaningful names to your variables so we can easily know what each variable is used for in your program.

Put comments in your code (in English!) to explain WHAT your code is doing and also to explain HOW your program

is doing it. Also put comments in your tests.

Make sure all your code is properly indented (formatted). Your code should be beautiful to read.

Failure to follow these instructions will result in you losing points.

Question 1

In this project you need to write software for an electricity company. The electricity company has different kinds of

buildings connected to its electrical grid: electric power plants that generate electricity, different kinds of houses that

consume electricity, etc. All these buildings generate or consume a certain amount of electric power, expressed in watts.

Write a Consumer interface for electricity consumers, with the following UML specification:

+-------------------------------+

| <<interface>> |

| Consumer |

+-------------------------------+

| + getName(): String |

| + getPower (): int |

| + morePower(int amount): void |

+-------------------------------+

and a Building class that implements Consumer and has the following UML specification:

+------------------------------------+

| Building |

+------------------------------------+

| - name: String |

| - power: int |

+------------------------------------+

| + Building(String name, int power) |

| + getName(): String |

| + getPower(): int |

| # setPower(int power): void |

| + morePower(int amount): void |

| + testBuilding(): void |

+------------------------------------+

The name instance variable indicates the name of the building. The power instance variable indicates the amount of

power consumed by the building (to simplify the assignment we will assume that power is always expressed as an

integer number of watts).

The setPower method changes the amount of power consumed by the building. The setPower method is

protected, not public. This means that only subclasses of the Building class can use the setPower method.

All the other classes in the software cannot use the setPower method, so they cannot set the amount of power

consumed by a building.

The purpose of the morePower method is to increase the amount of power generated or consumed by a building

(depending on what kind of building it is) by the amount given as argument to the method. The morePower method of

the Building class is abstract, since we do not know what kind of building (a building generating power or a

building consuming power) the building is.

Also add to your program a Test class to test your Building class.

Question 2

Add a class PowerPlant that extends Building. The constructor of the PowerPlant class takes as arguments a

name and the amount of power generated by the power plant. The PowerPlant class does not have any instance

variable.

Warning: the constructor of the PowerPlant class takes as argument the amount of power generated by the power

plant, but the power instance variable of the Building class indicates how much power the building consumes!

Generating power is the same as consuming a negative amount of power (in accordance with the passive sign

convention of electrical engineering).

The morePower method of the PowerPlant class increases the amount of power generated by the power plant by

the amount of power given as argument to the method (so the power consumed by the power plant becomes more

negative!)

Here are some tests for your new PowerPlant class:

public static void testPowerPlant() {

PowerPlant p = new PowerPlant("UIC Power Plant", 1000000);

System.out.println(p.getName() == "UIC Power Plant");

System.out.println(p.getPower() == -1000000);

p.setPower(-2000000); // Sets the power consumed by the power plant.

System.out.println(p.getPower() == -2000000);

p.morePower(500000); // Increases the power generated by the power plant.

System.out.println(p.getPower() == -2500000);

p.morePower(-2510000); // Turn off the power plant: it now consumes electricity.

System.out.println(p.getPower() == 10000);

}

Question 3

Add a class House that extends Building. The constructor of the House class takes as arguments the name of the

house’s owner and the amount of power consumed by the house. If the amount of power given as argument is strictly

less than zero then the constructor must throw a NotAPowerGeneratorException with the message "A new

house cannot generate power". The House class does not have any instance variable.

The morePower method of the House class increases the amount of power consumed by the house by the amount of

power given as argument to the method (so the power consumed by the house becomes more positive!) For example, if

a house currently consumes 1000 watts and morePower(200) is called then the house consumes 1200 watts. It is fine

for the morePower method to be given a negative value as argument, which means the house then just consumes less

power. For example, if a house currently consumes 1000 watts and morePower(-200) is called then the house

consumes 800 watts. However, a house cannot generate power, so the amount of power consumed by the house must

always be positive or zero, never negative. If the argument given to the morePower method is too negative and would

change the house into a generator of power, then instead the amount of power consumed by the house must not

change and the morePower method must throw a NotAPowerGeneratorException with the message “A

house cannot generate XXX watts of power”, where XXX is replaced with the amount of power that the

house would generate if the house were wrongly allowed to become a power generator. For example, if a house

currently consumes 1000 watts and morePower(-1200) is called then the house still consumes 1000 watts and the

method throws a NotAPowerGeneratorException with the message “A house cannot generate 200

watts of power”.

Change other classes and interfaces as necessary.

Make sure you test your new House class.

Question 4

Add a class SolarHouse that extends House. The constructor of the SolarHouse class takes as arguments the

name of the solar house’s owner and the amount of power consumed by the solar house. The SolarHouse class does

not have any instance variable.

The morePower method of the SolarHouse class increases the amount of power consumed by the house by the

amount of power given as argument to the method (so the power consumed by the house becomes more positive!) A

solar house can generate power using its solar panels, so the amount of power consumed by the house can become

negative without throwing any exception: a negative power consumption just means that the solar panels of the house

are currently generating more power than the rest of the house is consuming.

Change other classes and interfaces as necessary.

Make sure you test your new SolarHouse class.

Question 5

Add an ElectricityCompany class with the following UML specification:

+--------------------------------------------+

| ElectricityCompany |

+--------------------------------------------+

| - name: String |

| - consumers: ArrayList<Consumer> |

+--------------------------------------------+

| + ElectricityCompany(String name) |

| + addConsumer(Consumer consumer): void |

| + totalConsumption(): int |

| + getPower(String name): int |

| + morePower(String name, int amount): void |

| + testElectricityCompany(): void |

+--------------------------------------------+

When an electricity company is created, it has an arraylist of electricity consumers but the arraylist is empty (the

arraylist does not contain any electricity consumer).

The addConsumer method takes an electricity consumer as argument and adds the consumer to the arraylist of

consumers for the electricity company.

The totalConsumption method returns as result the total amount of power consumed by all the consumers of the

electricity company (if the result is negative then it means that the power plants of the electricity company generate

more power than the houses need and the electricity company can then sell some power to other electricity companies;

if the result is positive then it means that the houses consume more electricity than the power plants generate and the

electricity company must then buy some power from other electricity companies; if the result is zero then it means that

the power plants of the electricity company generate exactly enough powers for all the houses).

The getPower method takes as argument the name of an electricity consumer and returns as result the amount of

electric power currently consumed by this consumer. If the electricity company does not have a consumer with the

correct name then the getPower method must throw an UnknownConsumerException with the message

"Consumer XXX unknown", where XXX is replaced with the name of the consumer.

The morePower method takes as argument the name of an electricity consumer and an amount of electric power and

changes the amount of power currently consumed by that consumer. If the electricity company does not have a

consumer with the correct name then the morePower method must throw an UnknownConsumerException with

the message "Consumer XXX unknown", where XXX is replaced with the name of the consumer.

Note: the morePower method does not catch any exception, it only throws exceptions.

Make sure you test your new ElectricityCompany class.

Question 6

In this question and the next one we want to create a command line interface (CLI) for our electricity company software.

Add a CLI class with a main method. Your code then has two classes with a main method: the Test class that you

can use to run all your tests for all your classes, and the CLI class that you will now use to run the interactive text-based

interface of your program.

The CLI class does not have any testCLI method because this class is only used to allow users to use the software

interactively.

Add to the CLI class a private static input instance variable which is a Scanner object that reads input from the

standard input stream System.in:

private static Scanner input = new Scanner(System.in);

Always use this input scanner object when you need to read input. (Never close this scanner object, because this

would also close the standard input stream System.in, and then the next time you tried to read something from the

standard input stream you would get a NoSuchElementException!)

In addition to the main method and the input instance variable, the CLI class has two methods called readLine

and readPosInt.

The readLine method is static and private, it takes a string as argument, and returns another string as result. The

readPosInt method is static and private, it takes a string as argument, and returns a positive integer as result.

The readLine method uses System.out.print (not println) to print its string argument on the screen (later

when we use the readLine method, the string argument of the method will be a message telling the user to type

some text). Then the readLine method uses the input scanner object to read a whole line of text from the user of

the program and returns the text as result.

The readPosInt method uses System.out.print (not println) to print its string argument on the screen (later

when we use the readPosInt method, the string argument of the method will be a message telling the user to type some

integer). Then the readPosInt method uses the input scanner object to read an integer from the user of the

program.

After reading the integer, the readPosInt method must also use the scanner’s nextLine method to read the single

newline character that comes from the user pressing the Enter key on the keyboard after typing the integer (if you do

not read this newline character using the nextLine method inside the readPosInt method, then the newline

character will remain in the input stream, and, the next time you use the readLine method described above, the

readLine method will just immediately read only the newline character from the input stream and return an empty

string as result, without waiting for the user to type anything!)

If the user types something which is not an integer, then the nextInt method of the scanner will throw an

InputMismatchException. In that case the code of your readPosInt method must catch the exception, use

System.out.println to print the error message "You must type an integer!" to the user (use

System.out.println for this, not System.err.println, otherwise you might hit a bug in Eclipse...), use the

scanner’s nextLine method to read (and ignore) the wrong input typed by the user of the program (if you do not do

this, the wrong input typed by the user will remain in the input stream, and the next time you call the nextInt method

again, you will get an InputMismatchException again!), and then do the whole thing again (including printing

again the string argument of the readPosInt method) to try to read an integer again (hint: put the whole code of the

method inside a while loop).

After reading the integer and the newline character (which is just ignored), the readPosInt method tests the integer.

If the integer is bigger than or equal to zero, then the readPosInt method returns the integer as result. If the integer

is strictly less than zero, then the readPosInt method uses System.out.println to print the error message

"Positive integers only!" to the user (use System.out.println for this, not System.err.println,

otherwise you might hit a bug in Eclipse...), and then does the whole thing again (including printing again the string

argument of the readPosInt method) to try to read an integer again (hint: just print the error message, and then the

while loop you already have around the whole code will automatically do the whole thing again...)

For example, if you want to check that your two methods readLine and readPosInt work correctly, put the

following code in the main method of your CLI class:

public static void main(String[] args) {

String str1 = readLine("Type some text: ");

System.out.println("Text read is: " + str1);

int i = readPosInt("Type an integer: ");

System.out.println("Integer read is: " + i);

String str2 = readLine("Type some text again: ");

System.out.println("Text read is: " + str2);

}

then running the main method of the CLI class should look like this (where aaaa bbbb, cccc, dddd eeee, -100,

-200, 1234, and ffff gggg are inputs typed by the user on the keyboard):

Type some text: aaaa bbbb

Text read is: aaaa bbbb

Type an integer: cccc

You must type an integer!

Type an integer: dddd eeee

You must type an integer!

Type an integer: -100

Positive integers only!

Type an integer: -200

Positive integers only!

Type an integer: 1234

Integer read is: 1234

Type some text again: ffff gggg

Text read is: ffff gggg

Question 7

Once you have checked that your methods readLine and readPosInt work correctly, remove all the code inside

the main method of the CLI class so that the main method is empty again.

In the rest of this question, use the readLine and readPosInt methods every time your program needs to read a

string or an integer from the user.

In the empty main method of the CLI class, create a single ElectricityCompany object with the name "UIC

Electric". The main method of the CLI class must then print a menu that allows the user of your software to do six

different actions that involve the electricity company object, and your program must then read an integer from the user

that indicates which action must be performed by the program (see below for the details of each action). Use the

readPosInt method to print the menu (give the string for the menu as the argument of readPosInt) and to read

the integer typed by the user.

For example, the menu should look like this:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

The user then types an integer between 1 and 6 to select the action.

For example (where 3 is an input from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

and your program then performs the selected action.

After an action has been performed by your program, your program must again print the menu and ask again the user of

the program for the next action to perform (hint: put the whole code of the main method inside a while loop, except

for the one line of code that creates the single electricity company object).

If the user types an integer which is not between 1 and 6, then your program must print an error message "Unknown

action!" to the user (hint: when testing the integer for the action, use the default case of a switch statement)

and then print the menu again (by just going back to the beginning of the while loop).

For example (where 7 is an input from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 7

Unknown action!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

If the user types something which is not an integer, the readPosInt method that you implemented in the previous

question will automatically repeat the menu and ask the user to type an integer again until the user actually types an

integer, so you do not have to worry about this in the code of the main method of your CLI class.

For example (where aaaa and bbbb cccc are inputs from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): aaaa

You must type an integer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): bbbb cccc

You must type an integer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Here are the detailed explanations for each action.

Action 1: printing the total amount of power consumed.

When the user of the software specifies action 1, your program must simply print on the screen the total amount of

power currently consumed by all the consumers of the electricity company. Then your program goes back to printing the

menu of actions (by just going back to the beginning of the while loop).

For example (where 1 is an input from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: 2000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Action 2: adding a new consumer to the electricity company.

When the user of the software specifies action 2, your program must add a new consumer to the electricity company. To

add a new consumer, your program needs to ask the user three things: the type of consumer (an integer read using

readPosInt: the integer 1 represents a power plant, the integer 2 represents a house, the integer 3 represents a

solar house, and any other integer must result in an error message "Unknown type of consumer!" being

printed and the software going immediately back to the main menu), the name of the consumer (a string read using

readLine), and the initial amount of power that the consumer generates (for a power plant) or consumes (for a house

or a solar house) when the consumer is created. You program must then create the correct consumer, add it to the

electricity company, and print an information message for the user of the software. The program then goes back to the

menu.

For example (where 1, 2, -100, 4, 2, 1, UIC PowerPlant, 5000, 1, 2, 2, Philippe, 1000, 1, 2, 3, Meunier,

2000, and 1 are inputs from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: 0

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): -100

Positive integers only!

Type the consumer type (power plant:1 house:2 solar house:3): 4

Unknown type of consumer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 1

Enter the name of the consumer: UIC PowerPlant

Enter the initial amount of power: 5000

Power plant "UIC PowerPlant" generating 5000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -5000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 2

Enter the name of the consumer: Philippe

Enter the initial amount of power: 1000

House of "Philippe" consuming 1000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -4000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 3

Enter the name of the consumer: Meunier

Enter the initial amount of power: 2000

Solar house of "Meunier" consuming 2000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -2000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Note that the readPosInt method prevents the initial amount of power from being negative, so the constructor for

the House class will never throw a NotAPowerGeneratorException when you create a house object.

Nevertheless the code of the main method of your CLI class must handle this exception by printing the error message

"BUG! This must never happen!" and immediately terminating the program using System.exit(1). The

same applies to a solar house.

Action 3: listing the amount of power consumed by a given consumer.

When the user of the software specifies action 3, your program must ask the user to type the name of a consumer, and

the program then prints the amount of power which is currently consumed by this consumer.

For example (where 3, UIC PowerPlant, 3, Philippe, 3, and Meunier are inputs from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

If the name of the consumer is wrong (the electricity company does not have a consumer with this name) then an

UnknownConsumerException will be thrown by the ElectricityCompany object. The code of the main

method of your CLI class must catch this exception, print the error message from the exception object, and then it just

goes back to printing the menu of actions (by just going back to the beginning of the while loop).

For example (where 3 and aaaa are inputs from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: aaaa

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Action 4: increasing the power of a given consumer.

When the user of the software specifies action 4, your program must ask the user to type the name of a consumer and

an amount of power, and the program then uses that amount of power to increase the amount of power generated or

consumed by the consumer. Then the program goes back to the main menu.

For example:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -6000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: Philippe

Enter the amount of power: -1000

Positive integers only!

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: Meunier

Enter the amount of power: 500

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2500 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

If the name of the consumer is wrong (the electricity company does not have a consumer with this name) then an

UnknownConsumerException will be thrown by the ElectricityCompany object. The code of the main

method of your CLI class must catch this exception, print the error message from the exception object, and then it just

goes back to printing the menu of actions (by just going back to the beginning of the while loop).

For example:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: aaaa

Enter the amount of power: 1000

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Note that, even if a consumer is a house, the readPosInt method prevents the typed amount of power from being

negative. This means a house will never throw a NotAPowerGeneratorException. Nevertheless the code of the

main method of your CLI class must handle this exception by printing the error message "BUG! This must

never happen!" and immediately terminating the program using System.exit(1).

Action 5: decreasing the power of a given consumer.

When the user of the software specifies action 5, your program must ask the user to type the name of a consumer and

an amount of power, and the program then uses that amount of power to decrease the amount of power generated of

consumed by the consumer. Then the program goes back to the main menu.

Note: the electricity company object that you are using does not have a method to decrease power. So, in the code of

the main method of the CLI class, simulate decreasing power by simply increasing power by a negative amount! For

example, decreasing the power of a house by 500 watts is the same as increasing the power of the house by -500 watts.

For example:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -6000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Philippe

Enter the amount of power: -1000

Positive integers only!

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2500 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Meunier

Enter the amount of power: 500

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

If the name of the consumer is wrong (the electricity company does not have a consumer with this name) then an

UnknownConsumerException will be thrown by the ElectricityCompany object. The code of the main

method of your CLI class must catch this exception, print the error message from the exception object, and then it just

goes back to printing the menu of actions (by just going back to the beginning of the while loop).

For example:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: aaaa

Enter the amount of power: 1000

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

If a consumer is a house and the amount of power typed by the user is too big then a

NotAPowerGeneratorException will be thrown by the House object. The code of the main method of your

CLI class must catch this exception, print the error message from the exception object, and then it just goes back to

printing the menu of actions (by just going back to the beginning of the while loop).

For example:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Philippe

Enter the amount of power: 2000

A house cannot generate 1000 watts of power

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 10000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses 5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Meunier

Enter the amount of power: 3000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses -1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6):

Action 6: quitting the program.

When the user of the software specifies action 6, your program must print a "Goodbye!" message, and terminate the

program using: System.exit(0).

For example (where 6 is an input from the user):

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 6

Goodbye!

Here is a more complete example of running the software:

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): aaaa

You must type an integer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): bbbb cccc

You must type an integer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): -100

Positive integers only!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 7

Unknown action!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: 0

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): -100

Positive integers only!

Type the consumer type (power plant:1 house:2 solar house:3): 4

Unknown type of consumer!

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 1

Enter the name of the consumer: UIC PowerPlant

Enter the initial amount of power: 5000

Power plant "UIC PowerPlant" generating 5000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -5000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 2

Enter the name of the consumer: Philippe

Enter the initial amount of power: 1000

House of "Philippe" consuming 1000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -4000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2

Type the consumer type (power plant:1 house:2 solar house:3): 3

Enter the name of the consumer: Meunier

Enter the initial amount of power: 2000

Solar house of "Meunier" consuming 2000 watts of power added

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -2000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: aaaa

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -6000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: Philippe

Enter the amount of power: -1000

Positive integers only!

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: Meunier

Enter the amount of power: 500

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2500 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -1500

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 4

Enter the name of the consumer: aaaa

Enter the amount of power: 1000

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses -5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Philippe

Enter the amount of power: -1000

Positive integers only!

Enter the amount of power: 1000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Meunier

Enter the amount of power: 500

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses 2000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: -2000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: aaaa

Enter the amount of power: 1000

Consumer aaaa unknown

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Philippe

Enter the amount of power: 2000

A house cannot generate 1000 watts of power

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Philippe

Philippe uses 1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: UIC PowerPlant

Enter the amount of power: 10000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: UIC PowerPlant

UIC PowerPlant uses 5000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 5

Enter the name of the consumer: Meunier

Enter the amount of power: 3000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 3

Enter the name of the consumer: Meunier

Meunier uses -1000 watts

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 1

Total amount of power consumed: 5000

Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 6

Goodbye!

Question 8

We now want to create a graphical user interface (GUI) for our electricity company software. Since we want our

electricity company software to have multiple views, we will use the Model-View-Controller design pattern.

First, create a ModelListener interface with the following UML specification:

+-------------------+

| <<interface>> |

| ModelListener |

+-------------------+

| + update(): void |

+-------------------+

This interface will be implemented by views and the model will use this interface to notify the views that they need to

update themselves.

Second, the ElectricityCompany class is the class that contains all the data for the electricity company. Therefore

the ElectricityCompany class plays the role of the model. Therefore the ElectricityCompany class needs to

have an arraylist of model listeners that needs to be notified every time the electricity company (the model) changes.

Therefore add to the ElectricityCompany class an arraylist of ModelListener. Also add to the

ElectricityCompany class an addListener method that takes a ModelListener as argument and adds it to

the arraylist of listeners. Also add to the ElectricityCompany class a private notifyListeners method that

takes nothing as argument and calls the update method of all the listeners of the electricity company. Then change the

addConsumer and morePower methods so that they call the notifyListeners every time a change is made to

the electricity company's data (only the addConsumer and morePower methods change the electricity company’s

data, so only these two methods need to call the notifyListeners method; the totalConsumption and

getPower methods do not change the electricity company's data, they only inspect the data, so they do not need to

call the notifyListeners method).

Use the Test class to make sure all your tests still work. Use the CLI class to make sure your command line interface

still works.

Third, create a ViewSimple class that extends JFrame, implements the ModelListener interface, and has the

following UML specification:

+--------------------------------------------------------+

| ViewSimple |

+--------------------------------------------------------+

| - m: ElectricityCompany |

| - c: ControllerSimple |

| - label: JLabel |

+--------------------------------------------------------+

| + ViewSimple(ElectricityCompany m, ControllerSimple c) |

| + update(): void |

+--------------------------------------------------------+

The constructor of the ViewSimple class registers the view with the model (the electricity company) using the

addListener method of the model, creates a JLabel object, stores it in the label instance variable of the

ViewSimple class, initializes the label to display the total amount of power consumed by all the consumers of the

electricity company, and adds the label to the view (which is a frame). The update method of the ViewSimple class

updates the text of the label as necessary so that the label always displays the current total amount of power

consumed by all the consumers of the electricity company.

Fourth, create a ControllerSimple class with the following UML specification:

+------------------------------------------+

| ControllerSimple |

+------------------------------------------+

| - m: ElectricityCompany |

+------------------------------------------+

| + ControllerSimple(ElectricityCompany m) |

+------------------------------------------+

Since the ViewSimple does not have any button, it cannot perform any action, therefore the corresponding controller

ControllerSimple does nothing. (We still want to have the ControllerSimple class so that our application

follows the correct Model-View-Controller design pattern.)

Fifth, create a GUI class with a main method. In this main method, create an anonymous class that implements the

Runnable interface with a run method and use the javax.swing.SwingUtilities.invokeLater method

to run that code on the event dispatch thread.

Sixth, we need to connect the model, the view, and the controller to each other. So in the run method of the

anonymous class:

create a ElectricityCompany object (the model object) with the name "UIC Electric"; then create a ControllerSimple object (the controller object) that takes the model object as argument;

then create a ViewSimple object that takes the model object and the controller object as arguments.

Use the GUI class to run your GUI: you should see a window that shows the total amount of power consumed by all the

consumers of the electricity company. This total amount must be zero, since the electricity company (model object) you

just created above does not have any consumer!

As a test, in the run method of the anonymous class, you can try to manually add to your electricity company (model

object) some power plants, houses, and solar houses to check that your GUI displays the correct total amount of power

consumed by all the consumers of the electricity company. For example:

Question 9

In the next questions we want to add more views. So, to simplify the next questions, create a View class which is going

to be the superclass of all views. This View class is generic, extends JFrame, implements the ModelListener

interface, and has the following UML specification:

+------------------------------------------+

| View<T extends Controller> |

+------------------------------------------+

| # m: ElectricityCompany |

| # c: T |

+------------------------------------------+

| + View(ElectricityCompany m, T c) |

| + update(): void |

+------------------------------------------+

The m and c instance variables of the View class are protected (so that they can be easily used in all the subclasses

of View). In the constructor of the View class, the view registers itself with the model. The update method of the

View class is abstract.

Then modify the ViewSimple class to be a subclass of the View<…> class. The ViewSimple class must then have

only one instance variable: the label. To simplify a little the code of the next questions, also move the

setDefaultCloseOperation method call from the constructor of ViewSimple to the constructor of View. Also

make sure that the ViewSimple does not directly register itself with the model anymore, since this is now done in the

superclass View.

Also create a Controller class which is going to be the superclass of all controllers. This Controller class has the

following UML specification:

+------------------------------------------+

| Controller |

+------------------------------------------+

| # m: ElectricityCompany |

+------------------------------------------+

| + Controller(ElectricityCompany m) |

+------------------------------------------+

The m instance variable of the Controller class is protected (so that it can be easily used in all the subclasses of

Controller).

Then modify the ControllerSimple class to be a subclass of the Controller class. (Note: since

ControllerSimple does nothing anyway, we could just remove it and replace it with Controller in the

definition of ViewSimple and in the run method of the GUI class, but here we keep ControllerSimple just to

make the Model-View-Controller design pattern very clear.)

Run your GUI and check that it still works as before.

Question 10

We now want to add a new “get power” view that allows the user of the software to check how much power a specific

consumer is consuming.

Create a ViewGetPower class that extends View<ControllerGetPower> and has the following UML

specification:

+------------------------------------------------------------+

| ViewGetPower |

+------------------------------------------------------------+

| - t: JTextField |

+------------------------------------------------------------+

| + ViewGetPower(ElectricityCompany m, ControllerGetPower c) |

| + update(): void |

+------------------------------------------------------------+

The ViewGetPower shows the text field called t (where the user can type text) and a button. Use a grid layout

manager to position the two components. For example:

The user can type in the text field t the name of a consumer. For example:

When the user then clicks on the button, the action listener of the button must read the name of the consumer that was

typed in the text field (using the getText method of the text field) and must call the getPower method of the

controller with that consumer name as argument. The getPower method of the controller returns a string as result

which must then be displayed back to the user using a message dialog (using the showMessageDialog method of

the JOptionPane class). For example:

The update method of the ViewGetPower class does nothing, because the ViewGetPower class does not

graphically display any data from the electricity company (the model).

Also create a ControllerGetPower class that extends Controller and has the following UML specification:

+--------------------------------------------+

| ControllerGetPower |

+--------------------------------------------+

+--------------------------------------------+

| + ControllerGetPower(ElectricityCompany m) |

| + getPower(String name): String |

+--------------------------------------------+

The getPower method takes the name of a consumer as argument. The getPower method of the controller then

calls the getPower method of the electricity company to get the amount of power currently consumed by that

consumer. The getPower method of the controller then transforms the integer result of the getPower method of

the electricity company into a string and returns that string as result (to the view). If the getPower method of the

electricity company throws an UnknownConsumerException then the getPower method of the controller must

catch this exception and return as result the error message from the exception object.

Modify the run method of the GUI class to add a ViewGetPower view that uses a ControllerGetPower

controller and the same model as before (not a new model!)

Run your GUI and check that you can correctly use the new view to query the amount of power used by different

consumers of your electricity company (obviously your electricity company must have some consumers to test this: see

the last paragraph of Question 8).

Also check that querying the amount of power for an unknown consumer correctly shows an error message. For

example:

Question 11

We now want to add a new “more power” view that allows the user of the software to increase the power of a specific

consumer.

Create a ViewMorePower class that extends View<ControllerMorePower> and has the following UML

specification:

+--------------------------------------------------------------+

| ViewMorePower |

+--------------------------------------------------------------+

| - t1: JTextField |

| - t2: JTextField |

+--------------------------------------------------------------+

| + ViewMorePower(ElectricityCompany m, ControllerMorePower c) |

| + update(): void |

+--------------------------------------------------------------+

The ViewMorePower shows the two text field called t1 and t2 (where the user can type text) and a button. Use a

grid layout manager to position the three components. For example:

The user can type in the first text field the name of a consumer and can type in the second text field an amount of power.

For example:

When the user then clicks on the button, the action listener of the button must read the name of the consumer that was

typed in the first text field (using the getText method of the text field) and the amount of power that was typed in the

second text field (using again the getText method) and must call the morePower method of the controller with

these two strings as arguments. The morePower method of the controller then returns a string as result. If the string

returned by the morePower method of the controller is different from the empty string "" then this string must be

displayed back to the user using a message dialog (using the showMessageDialog method of the JOptionPane

class). If the string returned by the morePower method of the controller is equal to the empty string "" then nothing

happens in ViewMorePower.

The update method of the ViewMorePower class does nothing, because the ViewMorePower class does not

graphically display any data from the electricity company (the model).

Also create a ControllerMorePower class that extends Controller and has the following UML specification:

+-------------------------------------------------+

| ControllerMorePower |

+-------------------------------------------------+

+-------------------------------------------------+

| + ControllerMorePower(ElectricityCompany m) |

| + morePower(String name, String amount): String |

+-------------------------------------------------+

The morePower method takes the name of a consumer and an amount of power (as a string) as arguments. The

morePower method of the controller then transforms the amount of power from a string to an integer (using the

Integer.parseInt static method) and calls the morePower method of the electricity company to increase the

amount of power generated or consumed by that consumer by the given amount.

If no exception occurs then the morePower method of the controller returns the empty string.

If the morePower method of the electricity company throws an UnknownConsumerException then the

morePower method of the controller must catch this exception and return as result the error message from the

exception object.

If the morePower method of the electricity company throws a NotAPowerGeneratorException then the

morePower method of the controller must catch this exception and return as result the error message from the

exception object.

If the parseInt method of the Integer class throws a NumberFormatException (because the user typed

something which is not an integer) then the morePower method of the controller must catch this exception and

return as result the error message from the exception object.

Note: to keep things simple, it is allowed for a user of your software to increase the amount of power of a consumer by a

negative amount, so there is no need to check for that.

Modify the run method of the GUI class to add a ViewMorePower view that uses a ControllerMorePower

controller and the same model as before (not a new model!)

Run your GUI and check that you can correctly use the new view to increase the power for different consumers of your

electricity company (obviously your electricity company must have some consumers in it to test this: see the last

paragraph of Question 8).

Check that, when you increase a consumer’s power, the simple view is automatically correctly updated to show the

new total amount of power for all the consumers of the electricity company.

Also use the “get power” view to check that the consumer’s power correctly changed.

Also check that increasing the power for an unknown consumer correctly shows an error message. For example:

? Also check that increasing the power of a house by a large negative number correctly shows an error message. For

example:

Also check that trying to increase the power of a consumer by an amount which is not an integer correctly shows an

error message (do not worry about the content of the error message). For example:

Question 12

We now want to add a new “create” view that allows the user of the software to create a new consumer for the

electricity company.

Create a ViewCreate class that extends View<ControllerCreate> and has the following UML specification:

+--------------------------------------------------------+

| ViewCreate |

+--------------------------------------------------------+

| - t1: JTextField |

| - t2: JTextField |

| - cb: JComboBox<String> |

+--------------------------------------------------------+

| + ViewCreate(ElectricityCompany m, ControllerCreate c) |

| + update(): void |

+--------------------------------------------------------+

The ViewCreate shows the two text field called t1 and t2 (where the user can type text), the combo box cb (where

the user can select one option from a menu) and a button. Use a grid layout manager to position the four components.

For example:

The user can type in the first text field the name of a new consumer and can type in the second text field an amount of

power for the new consumer. The combo box offers three menu options: "Power Plant", "House", and "Solar

House". For example:

When the user then clicks on the button, the action listener of the button must read the name of the new consumer

that was typed in the first text field (using the getText method of the text field), read the amount of power that was

typed in the second text field (using again the getText method), and read which menu option was selected in the

combo box (using the getSelectedIndex method of the combo box, which returns the integer 0 or 1 or 2

depending on which menu option the user selected in the combo box), and calls the create method of the controller

with these two strings and the integer as arguments. The create method of the controller then returns a string as

result. If the string returned by the create method of the controller is different from the empty string "" then this

string must be displayed back to the user using a message dialog (using the showMessageDialog method of the

JOptionPane class). If the string returned by the create method of the controller is equal to the empty string ""

then nothing happens in ViewCreate.

The update method of the ViewCreate class does nothing, because the ViewCreate class does not graphically

display any data from the electricity company (the model).

Also create a ControllerCreate class that extends Controller and has the following UML specification:

+----------------------------------------------------------+

| ControllerCreate |

+----------------------------------------------------------+

+----------------------------------------------------------+

| + ControllerCreate(ElectricityCompany m) |

| + create(String name, String amount, int type): String |

+----------------------------------------------------------+

The create method takes as arguments the name of a new consumer, an amount of power (as a string), and an integer

representing the type of consumer to create (where the integer 0 means a power plant, the integer 1 means a house,

and the integer 2 means a solar house). The create method of the controller then transforms the amount of power

from a string to an integer (using the Integer.parseInt static method), creates an object from the correct class

(based on the type of consumer specified by the user: power plant, or house, or solar house), and calls the

addConsumer method of the electricity company to add the new consumer object to the electricity company.

If no exception occurs then the create method of the controller returns the empty string.

If the constructor of the House class throws a NotAPowerGeneratorException then the create method

of the controller must catch this exception and return as result the error message from the exception object.

If the parseInt method of the Integer class throws a NumberFormatException (because the user typed

something which is not an integer) then the create method of the controller must catch this exception and return

as result the error message from the exception object.

Modify the run method of the GUI class to add a ViewCreate view that uses a ControllerCreate controller and

the same model as before (not a new model!)

Note: if at the end of Question 8 you had manually added to your electricity company (model object) some consumers

for testing, then you must now remove those consumers from the run method of the anonymous class inside the GUI

class. You do not need these test consumers anymore because you have now a graphical user interface to create new

consumers!

Run your GUI and check that you can correctly use the new view to create different consumers for your electricity

company, with different types of consumers.

Check that, when you create a new consumer, the simple view is automatically correctly updated to show the new

total amount of power for all the consumers of the electricity company.

Also use the “get power” view to check that the consumers are correctly created with the correct names and

correct amounts of power.

Also check that trying to create a house with a negative amount of power correctly shows an error message. For

example:

Also check that trying to create a consumer with an amount of power which is not an integer correctly shows an

error message (do not worry about the content of the error message). For example:

After you created a new consumer, you can also check whether the new consumer is a house or not by using the

“more power” view to increase the amount of power of the consumer by a big negative amount:

o if the new consumer you created is a power plant or a solar house then increasing the amount of power by a

big negative amount will work and the amount of power consumed by the consumer will just become negative

(you can then check that using the “get power” window);

o if the new consumer you created is a house then increasing the amount of power by a big negative amount will

fail with an error message and the amount consumed by the house will not change (you can then check that

using the “get power” window).

Question 13

We now want to add a new “history” view that allows the user of the software to keep track of how the total amount of

power consumed by all the consumers of the electricity company changes over time.

Before we can add such a view to the GUI, first we need to change the model (the ElectricityCompany class) to

keep track of how the total amount of power consumed by all the consumers of the electricity company changes over

time. Therefore, in the ElectricityCompany class, add a new private instance variable called history which is an

arraylist of integers. This arraylist must be initialized to contain only one value: zero (meaning that, when the electricity

company is created, it is not generating or consuming any power).

We know that the data of the electricity company can change only in two methods of the ElectricityCompany

class: in the addConsumer method and in the morePower method (this is why these two methods both call

notifyListeners: to tell the views that data has changed and that the views must update themselves). Therefore it

is in these two methods addConsumer and morePower that we must keep track of how the total amount of power

of all the consumers of the electricity company changes over time. Therefore, in these two methods addConsumer

and morePower, call the totalConsumption method and add the result to the history arraylist.

Note: in each of the two methods addConsumer and morePower, you must call the totalConsumption method

and add the result to the history arraylist before calling notifyListeners, otherwise the “history” view that you

are going to create below will not show the correct results when it is notified by the electricity company that it must

update itself!

Also add to the ElectricityCompany class a getHistory method that returns as result the arraylist of integers

which is the electricity company’s history.

Create a HistoryPanel class that extends JPanel. The constructor of HistoryPanel takes as argument a model

object of type ElectricityCompany, which you need to store in some private instance variable. Add to the

HistoryPanel class two private methods called historyMax and historyMin that take an arraylist of integers

as argument and return as result the maximum and minimum number in the arraylist, respectively (you can assume that

the arraylist contains at least one number). Then add to the HistoryPanel class a private method called

historyRange that takes an arraylist of integers as argument and returns as result the difference between the max

and min of the integers in the arraylist, or returns as result 200 if the difference between the man and min of the

integers in the arraylist is strictly less than 200.

Override the protected void paintComponent(Graphics g) method inherited from JPanel, and, inside

your new paintComponent method, draw graphically how the total amount of power of all the consumers of the

electricity company changes over time, as follows:

Compute the following variables (where history is the result of calling the getHistory method of the model):

int min = historyMin(history);

int range = historyRange(history);

int maxX = getWidth() - 1;

int maxY = getHeight() - 1;

int zero = maxY + min * maxY / range;

Draw a blue line between the point (0, zero) and the point (maxX, zero) (this blue line then represents the

horizontal “zero” axis).

For each value v at index i in the history arraylist that you want to draw:

o Use x = 10 * i for the horizontal coordinate;

o Use y = zero - v * maxY / range for the vertical coordinate;

o Draw red lines between all the points (x, y) (if there is only one value in the arraylist then just draw a red

rectangle of size 1 by 1 at position (x, y)).

Create a ViewHistory class that extends View<ControllerHistory> and has the following UML specification:

+----------------------------------------------------------+

| ViewHistory |

+----------------------------------------------------------+

+----------------------------------------------------------+

| + ViewHistory(ElectricityCompany m, ControllerHistory c) |

| + update(): void |

+----------------------------------------------------------+

The ViewHistory shows only a HistoryPanel object, nothing else. The update method of the ViewHistory

class calls Swing’s repaint method (this forces Swing to redraw everything every time the model changes, which in

turn forces Swing to automatically call the paintComponent method of the HistoryPanel to redraw the updated

version of the electricity company’s history).

Also create a ControllerHistory class that extends Controller and has the following UML specification:

+----------------------------------------------------------+

| ControllerHistory |

+----------------------------------------------------------+

+----------------------------------------------------------+

| + ControllerHistory(ElectricityCompany m) |

+----------------------------------------------------------+

Since the ViewHistory does not receive any input from the user, the ControllerHistory does nothing. (Note:

since ControllerHistory does nothing anyway, we could just remove it and replace it with Controller in the

definition of ViewHistory and in the run method of the GUI class, but here we keep ControllerHistory just

to make the Model-View-Controller design pattern very clear.)

Modify the run method of the GUI class to add a ViewHistory view that uses a ControllerHistory controller

and the same model as before (not a new model!)

Run your GUI and check that adding new consumers and changing the power consumed by consumers correctly updates

the graphical history of the electricity company’s total amount of power consumed. For example, if the user of the

software creates a power plant which generates 2000 watts, then creates a house that consumes 2500 watts, then

creates a solar house that consumes 500 watts, then increases the power consumption of the solar house by -2000

watts (in other words, the solar house starts generating 1500 watts of power), then the graphical history of the

electricity company’s total amount of power consumed must look like this (the last value is -1000 because it is the -2000

watts consumed by the power plant plus the 2500 watts consumed by the house plus the -1500 watts consumed by the

solar house):

Check that all the other features of your software still work correctly. Also run your tests and the CLI to make sure

everything still works correctly.

Question 14

We now want to store the electricity company’s information (consumers and history, but not the electricity company’s

name and not the electricity company’s listeners) into a binary file using object serialization.

Add to the ElectricityCompany class a new private file instance variable. In the constructor, initialize the file

instance variable to be a File object for a binary file named "XXX.bin" (where XXX is replaced with the name of the

electricity company). Add to the ElectricityCompany class a new public method called savaData that takes no

argument, returns nothing, and uses object serialization to save into the binary file the consumers and history

arraylists of the electricity company. Modify the constructor of the ElectricityCompany class to read all the

information from this binary file, if it exists, and put it into the corresponding arraylists (if the binary file does not exist

then the arraylists must be initialized as before).

Make other classes implement Java’s Serializable interface as appropriate.

Add to the Controller superclass a protected shutdown method that:

calls the saveData method of the model;

manually terminates the program using System.exit(0).

Then modify the View superclass to:

hide the frame when the user clicks on the “close” button;

add a “window closing” event handler (use an anonymous window adapter) that calls the controller’s shutdown

method.

Run your GUI, add some consumers, make some changes to the power consumed by some consumers, exit the software,

run the GUI again, and check that all the consumers and history information is still there and is correct. Also check that

the binary file is correctly created inside the folder for your Eclipse project (it is a binary file though, so you cannot read

its content).

Note that the command line interface that you created in Question 7 reads all the information saved into the binary file

when you start the command line interface (because the constructor of the ElectricityCompany class will

automatically read the content of the binary file if it exists and has the correct name) but it does not write the

information back into the binary file when you quit the command line. This is easy to fix: in the main method of the

CLI class, just before printing the "Goodbye!" message, call the savaData method of the

ElectricityCompany object that you created at the start of the main method.

Run the command line interface and check that any change you make to the electricity company’s information using the

command line interface is correctly saved into the binary file when you quit the command line interface. You can run the

GUI to check this (but do not run the GUI and the CLI at the same time).

Use the Test class to run all the tests for the software and check that all the tests still work (delete the binary file

before you do this, otherwise the ElectricityCompany constructor that you use in your tests will read consumer

data from the binary file, which will change the results of your tests).

The end. That was fun!


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp