联系方式

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

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

日期:2024-03-13 10:33

CS 3140 - SDE Spring 2024

HW 3: Apportionment Refactored

1. Getting Started

In Unit III of our course, you learned that code refactoring is like giving your code a makeover.

It's the process of improving the structure, organization, and functionality of your code without

changing its external behavior. Refactoring can not only make your code easier to read,

maintain, and debug, but it can also increase its performance and efficiency. It's a skill that every

developer should master, as it's often the key to unlocking the true potential of their code.

In this assignment, we will revisit and refactor HW1-C. You are given an implementation of HW1

written by Prof. Will McBurney, the course's original designer. For reasons of academic

honesty, this implementation code may not be reposted anywhere or shared with anyone.

The assignment is divided into 4 parts:

● Part A - Refactor an Apportionment method

● Part B - Add a new concrete implementer to ApportionmentFormat

● Part C - Designed three classes ApportionmentMethodFactory,

StateSupplierFactory, and RepresentationFormatFactory, to instantiate and

return the correct concrete implementation of the functionality of our software.

1

CS 3140 - SDE Spring 2024

● Part D - Reimplement a new command-line arguments system

You may tackle these parts in any order, though doing Part C before you do Part D is

recommended since the new Arguments implementation should use the Factories created in

Part C.

Note on Piazza: For this and future assignments, we are back to our regular Piazza policies,

meaning it's completely okay (and encouraged) to ask public questions on Piazza about the

specification, starter code, etc.

Team Repository: Teams of up to 3 are allowed. You may have teammates from your previous

team or find new ones. However, you can only work with the same person up to 4 times.

1. Decide if you are working alone or if you are working in a group of up to 3 members. All

team members must have their NetID in the team repository name. In this assignment,

you will add the prefix “Refactor” to your team name. For example, a team of netID1,

netID2, and netID3 must follow this format: “Refactor-netID1-netID2-netID3”

2. Click on this GitHub Classroom Invite: https://classroom.github.com/a/fB4JiPvY

and create the git repository you and your team will use. If you miss this step, make a

private "rename repo" request on Piazza.

3. Using IntelliJ, clone the repository to your local computer in the root directory of your

project (by default, named HW3-starter-repo).

2. Program Specifications

This implementation additionally has three extra features, including 2 apportionment methods

that were not in Homework 1:

● AdamsMethod.java, which is used by adding "--adams" to the command line

○ You will rewrite the argument handling in a later part. The implementation will no

longer have the "--adams" flag.

● JeffersonMethod.java, which is used by adding “--jefferson” to the command

line

○ You will rewrite the argument handling in a later part. The implementation will no

longer have the "--jefferson" flag.

● PopulationFormat.java, which can display the apportionment in order of

population (ascending or descending).

As a rule, do not change any existing public or protected class interfaces (that is, do not change

the method declarations, and do not change their behavior) unless explicitly told to do so.

Additionally, do not remove any existing tests except for ArgumentsTest, which you will want

to replace in Part D completely. These tests help ensure you don't "break" any working features

when adding new code. You may add additional tests if they help. However, be aware that we

will run all existing tests except those in ArgumentsTest (as well as new tests) when grading

your code, and you will lose points for any test failures.

2

CS 3140 - SDE Spring 2024

In general, I would expect you only to need to change the following source files:

● Arguments.java (which you will replace completely in part D)

● Any of the classes that you add

● ArgumentsTest.java (which you are encouraged to replace with your tests)

2.1. Part A - Reimplement an Apportionment Method

You will expand some features from Homework 1C in the HuntingtonHill Method. You will

re-design the Huntington-Hill to implement the ApportionmentMethod interface and return a

Representation. You can refer back to HW1-C for an example of implementing the

Huntington-Hill Method and reusing any code from Homework 1C from any team member. The

class declaration should be:

public class HuntingtonHillMethod implements ApportionmentMethod {}

This class should not have any constructors! We will instantiate it with an implicit zero-argument

constructor. As part of the ApportionmentMethod interface, the getRepresentation function

should calculate how many representatives each state receives using the Huntington-Hill

algorithm and return an appropriate Representation.

Implementation Note: These methods may not change any code outside their class. Refrain

from modifying how command line arguments are handled (we will discuss that in Parts C and

D). You can reference existing code, but you must not change it! We intend to use

polymorphism to help ensure our new code can be added without changing existing code in

other software parts (though you can re-use code outside of the class, such as

Apportionment).

2.2. Part B - Add a New Feature: Relative Benefit

Since our code now supports a few apportionment methods, we want to add a Relative Benefit

feature to help users compare different apportionment methods. You will learn how to calculate

the relative benefit of an apportionment strategy and format it for display on the console. To do

this, you will implement a new class called RelativeBenefitFormat.

RelativeBenefitFormat

Looking at the table of the Jefferson method with our starting Divisor based on the Total

Population divided by the number of Representatives (described in Appendix A). The

RoundedDown column was replaced with the number of representatives given to the state.

Name Population Raw Final reps Benefit

Delaware 989948 0.808914 0 -0.808914

Maryland 6177224 5.04758 5 -0.04758

3

CS 3140 - SDE Spring 2024

Pennsylvania 13002700 10.62486 12 +1.37514

Virginia 8631393 7.052948 7 -0.052948

West Virginia 1793716 1.465695 1 -0.465695

From this table, we can see how much a state benefited from or was hurt by the

apportionment method:

Benefit = [final reps] - [raw]

In this case, we can say Pennsylvania benefitted the most from our use of the Jefferson

Apportionment method (then ended up with nearly 1.4 more reps than you would expect from

their raw number), whereas Delaware was hurt the most (they would expect roughly 0.8 reps -

they got 0). Using this information, here is how your printed format should look:

State | Reps|Benefits

Pennsylvania | 12| +1.375

Maryland | 5| -0.048

Virginia | 7| -0.053

West Virginia | 1| -0.466

Delaware | 0| -0.809

Format Description:

● A header row as shown above

● Vertical bars to indicate columns

● 16 characters left-aligned for state name

● 5 right-aligned for Reps. The number must be an integer

● 7 or 8 characters right-aligned for Benefit.(previously said 7, but example was 8, both ok)

○ the number must have exactly 3 decimal places,

○ + sign must be included for positive benefit values

○ - sign for negative numbers

○ 0.000 should have no sign.

That is, states should be sorted by benefit for the given algorithm. While this example uses the

Jefferson method, this relative benefit should work with ANY apportionment method.

The RelativeBenefitFormat class will also use our divisor. This could involve copying

commonly used code to a library accessible by many classes. Consider again how to approach

making our code D.R.Y. “Don’t Repeat Yourself”, and avoiding copying and pasting code.

The RelativeBenefitFormat should have a private field of type DisplayOrder which determines

the displayOrder class should have two constructors:

● public RelativeBenefitFormat() - defaults the DisplayOrder field to

DESCENDING.

4

CS 3140 - SDE Spring 2024

● public RelativeBenefitFormat(DisplayOrder displayOrder) - directly sets

the DisplayOrder field but throws an IllegalArgumentException if DisplayerOrder is

null.

Do not add any additional constructors.

I recommend looking at PopulationFormat when writing this class, as you should find that it

helps you out considerably, especially with how to handle DisplayOrder.

The interesting part of implementing this is getting each state's quota, since the function is

limited to taking in a Representation object. Be aware that you can calculate the quotas from

the Representation (either by writing the code yourself or re-using the default methods in

ApportionmentMethod.java).

2.3. Part C: Extracting Classes

By now, we should note that the Arguments class violates the Single Responsibility Principle:

"A class should only have one reason to change." Arguments could change because

1. We change the argument format

2. We implement new concrete implementations we want our program to use:

a. New input file format

b. New apportionment algorithm

c. New output String format

This means we have 4 reasons to change. Let's fix that before we start making changes to

Arguments class. You will make 3 Factory classes, each with 1-3 methods. These classes are

called Factory because they implement a creational design pattern called the Factory Pattern (to

be revealed later in the course). As a hint, all of these methods should be very simple,

basically just if-statements or switch statements that return new instances of the intended class.

The "default" factory methods should just be one-line return statements! If you find that any

method is more than 8 or so lines of code, you need to do something differently!

Factory 1: StateSupplierFactory

● public StateSupplier getStateSupplier(String filename) - Returns a new

StateSupplier (either CSVStateReader or SpreadsheetStateReader) depending on the

ending of the filename. This method will be very similar to the existing getStateSupplier

method in Arguments, but this method takes in the filename directly, rather than

extracting it from the command-line arguments. It should throw an

UnsupportedFileFormatException for invalid filenames.

5

CS 3140 - SDE Spring 2024

Factory 2: ApportionmentMethodFactory

○ public ApportionmentMethod getDefaultApportionmentMethod()-

Returns a new instance of the default apportionment method, HuntingtonHillMethod

○ public ApportionmentMethod getApportionmentMethod(String method)-

Returns a new instance of ApportionmentMethod (JeffersonMethod, AdamsMethod, or

HuntingtonHillMethod). The input string will be the command-line parameter associated

with the --method argument you will implement in Part D. Specifically, the input String

will be either "adams", "jefferson", or "huntington". Any other string input should

result in an IllegalArgumentException with a meaningful error message.

Factory 3: RepresentationFormatFactory

● public RepresentationFormat getDefaultRepresentationFormat() - Returns a

new instance of the default representation format, AlphabeticalFormat

● public RepresentationFormat getRepresentationFormat(String name) -

Returns a new instance of implementation of RepresentationFormat

(AlphabeticalFormat, RelativeBenefitFormat, or PopulationFormat). The input string will

be the command-line parameter associated with the --format argument that you will

implement in Part D. Specifically, the input String will be either "alpha", "benefit", or

"population". For benefit and population, use their default displayOrder (descending

and ascending respectively). Any other string input should result in an

IllegalArgumentException with a meaningful error message.

● public RepresentationFormat getRepresentationFormat(String name,

DisplayOrder order) - Does the same thing as getRepresentationFormat(String),

but allows the DisplayOrder to be specified (note that for AlphabeticalFormat, the

display order should be ignored.

Do not add any constructors to these Factories! All instantiation should be done using the

implicit zero argument constructor that all classes without an explicit constructor have.

Additionally, the classes shouldn't have any instance variables, though you are welcome to use

static constants. (public static final [type] [variable name])

Example Factory usage: If working correctly, then your usage of a given Factory will look

something like this:

StateSupplierFactory factory = new StateSupplierFactory();

StateSupplier supplier = factory.getStateSupplier(filename);

In this case, if the filename is a .csv file, the supplier will be an instance of CSVStateReader. If

the filename is an .xls or .xlsx file, the supplier will be an instance of SpreadsheetStateReader.

6

CS 3140 - SDE Spring 2024

2.4. Part D - Arguments rewrite

Note: You should implement Part C before attempting to implement this part.

Now that we have extracted the factories, we can re-implement Arguments based on the new

specification for handling requirements and ensure our project is scalable.

Tips: I recommend starting by deleting all of the implementations of all methods in

Arguments.java, but leaving the method declarations. You should also delete/comment

out all of the previous tests in ArgumentsTest.java, as those tests are incompatible with

the format of the new argument.

We can re-implement Arguments based on the new specification for handling requirements.

Arguments will still handle the same basic tasks:

● Take in the String[] args from Main via the Constructor.

● Providing the methods:

○ public StateSupplier getStateSupplier()

○ public int getRepresentatives()

○ public ApportionmentMethod getApportionmentMethod()

○ public RepresentationFormat getRepresentationFormat()

○ (these methods must still be present! - no interface change!)

However, rather than Arguments selecting which concrete implementers to use for

Configuration, it simply interacts with the Factories we wrote in Part C to do so. We are setting

up a framework for having a more customizable approach. So we're going to reset our

command-line arguments. We will still require one argument:

java -jar Apportionment.jar filename

Where filename is the name of the census population file (such as census2020.csv) - this

needs to accept both .csv and .xlsx files. From there, we want all our other arguments done in a

way that many modern programs handle optional arguments: … with flags!

Long Flag arguments

For simplicity, you can assume everything is case sensitive - we will only test your arguments

with lowercase letters.

java -jar Apportionment.jar census2020.xlsx --reps 1000 --format benefit

--algorithm jefferson

In this example, we have three optional arguments defined:

● --reps 1000 - run apportionment with 1000 representatives

● --format benefit - print results using RelativeBenefitFormat

● --algorithm jefferson - use JeffersonMethod

7

CS 3140 - SDE Spring 2024

In this case, the flag specifies the name of the argument, and the next argument specifies the

value of the argument. It's important that the optional arguments can be in any order, but

the argument must follow the flag directly. For example, the following is also a valid command.

java -jar Apportionment.jar census2020.xlsx --algorithm jefferson --reps 1000

List of optional arguments: This lists all optional arguments.

● --reps [integer] - must be followed by a positive (non-zero, non-negative) integer.

Throw a meaningful exception if the input is invalid.

○ Defaults to --reps 435

● --format formatName - set the format name. Format choices:

○ --format alpha - print States (AlphabeticalApportionmentFormat)

○ This is the default value

○ --format benefit - prints States by benefit (RelativeBenefitFormat)

○ --format population - prints States by population (PopulationFormat)

○ Anything else is invalid, a meaningful exception should be thrown

● --algorithm strategyName - set the Apportionment method

○ --algorithm adams - use Adams Apportionment algorithm

○ --algorithm jefferson - use Jefferson Apportionment algorithm

○ --algorithm huntington - use Huntington-Hill Apportionment algorithm

○ This is the default value

Short Flag arguments:

Short flags work largely the same way as long flags. For instance, long flag arguments:

java -jar Apportionment.jar census2020.xlsx --reps 1000 --format benefit

--algorithm jefferson

Could also be written as a short flag form:

java -jar Apportionment.jar census2020.xlsx -r 1000 -f benefit -a jefferson

That is:

● -r is short for --reps

● -f is short for --format

● -a is short for --algorithm

However, unlike long flags, short flags can be combined. For example,

java -jar Apportionment.jar census2020.xlsx -rfa 1000 benefit jefferson

Specifically, -rfa means that:

● The next argument (1000) is -r (--reps)

8

CS 3140 - SDE Spring 2024

● The argument after that (benefit) is -f (--format)

● And the argument after that (jefferson) is -a (--algorithm)

Just like long flags, these can go in any order, and only include some arguments:

java -jar Apportionment.jar census2020.xlsx -af jefferson alpha

The above means:

● Use the Jefferson Apportionment algorithm

● Print states alphabetically

● Use 435 reps (default)

A few words of encouragement: If you have followed the instructions and implemented the

code to the end of this part, congratulations! You have written a pretty complex piece of software

with several long and short flag arguments! This is no small feat, as it demonstrates a mastery

of functional and clean code design. I hope you take pride in what you have accomplished.

Keep up the awesome work, and continue to push yourselves to new heights in your future

projects!

3. Submission and Grading

Ensure all work has been merged to the main branch, then submit, as usual, answer the

questions on the Questions.md.

The coding portion of this assignment will be graded solely based on correct functionality, like

Homework 1 and 2. While we encourage practicing good style and testing (as they will likely

make developing the homework more efficient), we will not be grading anything other than the

functionality for the coding portion. Make sure your class and method names match this

document - we will use automated testing during this assignment to ensure efficient grading.

You should try to make your code DRY, but you will not be graded.

Functionality: We are only grading how correctly your code functions:

● Team Declaration: 5%

● Code Submission

○ Part A - 20%

○ Part B - 20%

○ Part C - 15%

○ Part D - 25%

● Submission and Reflection Questions - 20% (including 5% for Team Declaration)

○ 10% for answering the questions in Questions.md

○ 5% for filling out the Github information and setting up repo correctly

9

CS 3140 - SDE Spring 2024

4. Frequently Asked Questions

Q: Can I add code my team implemented in HW1-C?

A: Yes, you may add code that your team developed from HW1-C

Q: How do we access methods from an Apportionment if they are private?

A: You are welcome to **increase** the visibility level of any method (i.e., any private method

can be made protected or public, and any protected method can be made public).

Q: If a flag is syntactically incorrect/invalid ("-reps", "reps", or "--numreps") or if some

flag is missing, should we throw an error or should we allow the program to continue

running with the default configurations?

A: Any invalid flags or arguments not attached to flags should throw an error.

Q: Can I change the Method Signatures of Factory Classes?

A: No, you must adhere to the specification as given, only because it will make the grading job

more accessible if they can just use the automated test which relies upon a specific interface.

Q: May we use an external library to implement Arguments?

A: Yes. This is acceptable and in my view an intelligent thing to do. If you find the wheel that

works perfectly well, you don't need to invent a new one. Just make sure you do a proper import

through Gradle Dependencies.

Appendix A - Jefferson Apportionment Method

In this assignment, we will extend the pool of Apportionment methods with a new algorithm:

Jefferson Apportionment Method. As in Homework 1 with Hamilton and Huntington-Hill, we will

quickly illustrate the Jefferson Apportionment Method starting with these five states. For the first

few steps, this will look a lot like Hamilton. This Youtube video on Apportionment describes the

Jefferson Apportionment algorithm starting at the 13-minute mark.

In this example, we will be using 25 representatives once again.

Name Population

Delaware 989948

Maryland 6177224

Pennsylvania 13002700

Virginia 8631393

10

CS 3140 - SDE Spring 2024

West Virginia 1793716

Like with the Hamilton Method from HW1-A/B, we are going to get the total population

(30,594,981) and divide by our number of representatives (25) to get our divisor (roughly

1,223,799.24). And just like in Hamilton, we will divide every state by the divisor (Raw, in the

table below) and then Round all states DOWN (RoundedDown in the table below.)

Name Population Raw Rounded Down

Delaware 989948 0.808914 0

Maryland 6177224 5.04758 5

Pennsylvania 13002700 10.62486 10

Virginia 8631393 7.052948 7

West Virginia 1793716 1.465695 1

Now, if we were to allocate reps equal to the number rounded down, we would be allocating 23

representatives, which is two fewer than we should.

This is the part where we break away from Hamilton. In the Jefferson method, rather than

dealing with remainders, we instead change the divisor. That is, we start decreasing the value

of our divisor until we have allocated all 25 representatives.

So, for instance, if we change our divisor to 1.1 million (1,100,000), then our table becomes:

Name Population Raw Rounded Down

Delaware 989948 0.899953 0

Maryland 6177224 5.615658 5

Pennsylvania 13002700 11.82064 11

Virginia 8631393 7.846721 7

West Virginia 1793716 1.630651 1

We've allocated 24 representatives, but we are still short of 25. If we drop our divisor to 1

million (1,000,000), however, then we end up allocating too many representatives:

11

CS 3140 - SDE Spring 2024

Name Population Raw Rounded Down

Delaware 989948 0.989948 0

Maryland 6177224 6.177224 6

Pennsylvania 13002700 13.0027 13

Virginia 8631393 8.631393 8

West Virginia 1793716 1.793716 1

So that means 1 million is too small. I then tried 1.08 million (1,080,000) and got 25:

Name Population Raw Rounded Down

Delaware 989948 0.916619 0

Maryland 6177224 5.719652 5

Pennsylvania 13002700 12.03954 12

Virginia 8631393 7.992031 7

West Virginia 1793716 1.660848 1

Since we now have 25 representatives allocated, we stop here and accept this number. Yes,

this leaves Delaware without representation, but for the sake of simplicity, you should not try to

enforce "every state gets at least one representative" here. This would be the correct

Apportionment for this input.

Fun fact: In 1992, if Congress had been apportioned by the Jefferson method, Al Gore would

have won the 2000 Presidential Election even if no votes were changed. This is because

Jefferson heavily favors larger states.

12


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

python代写
微信客服:codinghelp