Fall 2021 CS159 - Advanced Programming Programming Assignment 2 UVIcast by 1. Learning Objectives This assignment is designed to help you learn several things. First, it will help you understand the difference between reference types and primitive types, the assignment of references, the difference between deep and shallow copies, and aliases. Second, it will give you some experience throwing and catching exceptions, and help you understand when exceptions should be used. Finally, as was the case for the previous assignment, it will give you some experience with good programming practices/processes. 2. Overview As you know, WeatherBits is a (fictitious) company that develops weather-related software of various kinds. They have asked you to write some additional classes for a product named UVIcast. Note that you may either use your implementation of the classes/enumerations from programming assignment 1 or the "solution" that was provided to you. 2.1. About the Product UVICast is a graphical user interface (GUI) application that can be used to display weather information (including the UVI) about both the current day and the next five days in the future. The Graphical User Interface (GUI) for UVIcast looks something like the following (though the details vary across operating systems). -1- 2.2. About the Current Assignment A version of the main class (UVIcast.java) has already been written, as have all of the classes/enumerations that were used in SunScreener. For this assignment, you must write and test the following classes: DailyUVReport.java MultiDayUVForecast.java The relationships between all of the components are illustrated in the following abstract UML class diagram. Classes in purple are part of the Java libraries, classes in green were written by the GUI development team, classes in blue were written as part of programming assignment 1, and classes in black are to be written by you for this assignment. Note that, the version of UVIcast.java that was written does not make use of the UVICalculator. Instead, it creates arbitrary UVI objects that are useful for system testing. 2.3. Existing Code The classes that comprise the GUI are available for download from the following URL: https://w3.cs.jmu.edu/bernstdh/web/cs159/pa2/pa2widgets.jar The source code for the main class is available for download from the following URL: -2- https://w3.cs.jmu.edu/bernstdh/web/cs159/pa2/UVIcast.java 3. Background Information See the background information for programming assignment 1. 4. The Classes/Enumerations to be Written You must write four classes/enumerations, each of which is described below. 4.1. The DailyUVReport Class A DailyUVreport is an encapsulation of information about a single day. It may contain either historical or forecasted information. 4.1.1 UML Class Diagram The following UML class diagram provides an overview of the attributes and methods in the DailyUVReport class (which must be in the default package). The temperature attribute will typically contain the average temperature for the day. The overcast attribute will be true if the sky is overcast for at least half of the day. 4.1.2 Detailed Design Specifications In addition to the specifications contained in the UML class diagram, the DailyUVReport class must conform to the following specifications. -3- 1. Validation of the Temperature 1.1. The temperature must be validated whenever it is set. 1.1.1.Invalid temperatures must be projected (using the minimum Euclidean distance projection) onto the interval VALID_TEMPERATURES. 2. Validation of the Low and High UVI 2.1. The low UVI must be validated whenever it is set. 2.1.1.If the low UVI parameter is null the corresponding attribute must be set to DEFAULT_LOW. 2.2. The high UVI must be validated whenever it is set. 2.2.1.If the high UVI parameter is null the corresponding attribute must be set to DEFAULT_HIGH. 2.3. After correcting for null parameters, the low and high UVI must be validated for consistency. 2.3.1.If the value of the low UVI is greater than the value of the high UVI then the value of the low UVI must be set to DEFAULT_LOW and the value of the high UVI must be set to DEFAULT_HIGH. 3. The getRange() Method 3.1. The getRange() method must return a String representation of the UVI range (from low to high) for the day that is formatted using the DEFAULT_FORMAT. 4.2. The MultiDayUVForecast Class A MultiDayUVForecast object is a collection of (deep copies of) DailyUVReport objects that contain forecasted information, all of which are "created at one time" (e.g., for the next seven days) and, hence, are interdependent (though the interdependence is not readily apparent). Deep copies are used so that an outside actor can't change a DailyUVReport object after it has been added to a MultiDayUVForecast object. 4.2.1 UML Class Diagram The following UML class diagram provides an overview of the attributes and methods in the MultiDayUVForecast class (which must be in the default package). 4.2.2 Detailed Design Specifications In addition to the specifications contained in the UML class diagram, the UVI class must conform to the following specifications. -4- 1. Constructor 1.1. The constructor must throw an IndexOutOfBoundsException if the parameter is not in the half- open interval [0, CAPACITY). 1.1.1.The message must be formatted using the IIOBE_FORMAT (where the integer value must be the CAPACITY). 1.2. Otherwise, the constructor must allocate memory for the reports array. 2. The addDailyUVReport() Method 2.1. The addDailyUVReport() method must throw a BackingStoreException if it is called too many times (i.e., if it is called more than CAPACITY times). 2.2. The addDailyUVReport() method must make and use a deep copy of the DailyUVReport object it is passed. (Note: Since the DailyUVReport class does not include a copy constructor, this requirement must be satisfied using the existing explicit value constructor in the DailyUVReport class.) 3. The getDailyUVReport() Method 3.1. The getDailyUVReport() method must throw an IndexOutOfBoundsException if it is passed a day-of-the-week (i.e., dow parameter) that is not in the half-open interval [0, CAPACITY). 3.2. The getDailyUVReport() method must return the DailyUVReport for Sunday if it is passed a 0, must return the DailyUVReport for Monday if it is passed a 1, etc. 3.2.1.If there is no DailyUVReport for the requested day-of-the-week then the getDailyUVReport() method must return null. 4.2.3 Typical Usage When a MultiDayUVForecast object is constructed, the day-of-the-week of the first day is set (where Sunday is denoted by 0). After that, daily information is added by calling the addDailyUVReport() method. Daily information must be added by the caller in order. So, for example, to construct a MultiDayUVForecast object that starts on Wednesday (which has a day-of-the-week of 3), one would declare and construct the MultiDayUVForecast as follows: MultiDayForecast forecast; forecast = new MultiDayForecast(3); Then, to add information about Wednesday (which must be added first) contained in a DailyUVReport named report that has already been declared and constructed, one would call the addDailyUVReport() method as follows: forecast.addDailyReport(report); Subsequent days would then be added in a similar fashion. Note that it is the responsibility of the caller to call the addDailyReport() method in the appropriate order. 5. Testing You are responsible for testing all of the code that you write. Until we discuss testing, you may test your code using whatever techniques that you would like to use. (Later in the semester, you will be required to use a particular set of tools.) -5- This section contains several recommended tests for each of the classes you must write. You are not required to use them, but you would be wise to do so. You should also spend some time thinking about why each of the tests is important. That is, you should think about what part of the code each test is trying to ensure is correct. (Actually, there are some tests that probably aren't necessary. You should also try and identify them because it will help you write fewer tests in the future.) 5.1. Tests for the DailyUVReport Class You should construct at least one test for each of the following: • The constructor and the simple accessors. • The getRange() method. • Specification 1.1.1 using the constructor. • Specification 1.1.1 using the setter. • Specification 2.1.1 using the constructor. • Specification 2.2.1 using the constructor. • Specification 2.3.1 using the constructor. • Specification 2.1.1 using the setter. • Specification 2.2.1 using the setter. • Specification 2.3.1 using the setter. 5.2. Tests for the MultiDayUVForecast Class You should construct at least one test for each of the following: • Specification 1.1 for a small value. • Specification 1.1 for a large value. • Specification 2.1. • Specification 3.1 for a small value. • Specification 3.1 for a large value. • Specification 3.2.1 • Specification 3.2, checking all of the accessors. • Specification 2.2, checking all of the accessors. -6- 6. Submission You must submit (using Autolab) a .zip file named pa2.zip that contains: 1. Your implementation of the required classes/enums (including those that were developed for this assignment and those that were developed for PA1). Do not include the main classes or the classes that comprise the GUI. There is no limit on the number of submissions and no penalty for excessive submissions. 7. Grading Your code will first be graded by Autolab and then by the Professor. The grade you receive from Autolab is the maximum grade that you can receive on the assignment 7.1. Autolab Grading Your code must compile (in Autolab, this will be indicated in the section on "Does your code compile?") and all class names and method signatures comply with the specifications (in Autolab, this will be indicated in the section on "Do your class names, method signatures, etc. comply with the specifications?") for you to receive any points on this assignment. Autolab will then grade your submission as follows: Conformance to the Course Style Guide: 10 points (All or Nothing; Success Required) Correctness: 90 points (Partial Credit Possible) Note that "Conformance to the Course Style Guide" is described as being "Success Required" for this assignment. This means that Autolab will not assess subsequent criteria unless these criteria are satisfied. So, there is no point in submitting your code to Autolab unless it conforms to the style guide. 7.2. Manual Grading After the due date, the Professor may manually review your code. At this time, points may be deducted for inelegant code, inappropriate variable names, bad comments, etc. 8. Recommended Process Since nobody will be looking over your shoulder, you can use any process that you would like to use. However, it is strongly recommended that you use the process describer here. 8.1. Get Started 1. Create a project for this assignment. (Remember, do not create a module.) 2. Copy either your code from PA1 or the solution to PA1 into the default package of the project. (This step isn't actually necessary, you could accomplish the same thing by changing the "Build Path" in Eclipse. However, making a copy will prevent you from changing the code you wrote for PA1.) -7- 8.2. Work on the DailyUVReport Class 1. Create a version of the DailyUVReport class that has all of the required attributes. 2. Write the accessors in the DailyUVReport class. 3. Write the getRange() method in the DailyUVReport class. 4. Desk check the getRange() method. In other words, check to make sure that every specification has been satisfied. (Hint: Use the specification as a checklist. That is, read each entry in the specification and put a check next to it if your implementation satisfies it.) 5. Write the setOvercast() method in the DailyUVReport class. 6. Desk check the setOvercast() method. 7. Write the setTemperature() method in the DailyUVReport class. 8. Desk check the setTemperature() method. 9. Write the setConditions() method in the DailyUVReport class. 10. Desk check the setConditions() method. 11. Write the constructor for the DailyUVReport class. 12. Test the constructor for the DailyUVReport class. 13. Test and debug the remainder of the class. 8.3. Work on the MultiDayUVForecast Class 1. There are several different ways that you can use an array of size 7 to keep track of 7 days of information (starting on any arbitrary day of the week). Think about at least 2. 2. Choose the approach you think is best. 3. Create a version of the MultiDayUVForecast class that has all of the required attributes. 4. Write the constructor. 5. Desk check the constructor. 6. Write the getFirstDayOfWeek() method. 7. Test the constructor and getFirstDayOfWeek() method. 8. Write the getDailyUVReport() method. 9. Desk check the getDailyUVReport() method. 10. Write the addDailyUVReport() method. 11. Desk check the addDailyUVReport() method. -8- 12. Test and debug the addDailyUVReport() and getDailyUVReport() methods. 8.4. Perform System Testing 1. Download pa2widgets.jar. 2. Add pa2widgets.jar to the project. (See the Department's Wiki for help.) 3. Download UVIcast.java. 4. Add UVIcast.java to the project. 5. Use UVIcast to perform system tests. (Note: UVIcast uses command-line argument 0 to determine the first day of the week in the forecast.) 6. Carefully check the information actually displayed in the GUI with the information you expect to see in the GUI (given what is being done in UVIcast). Use any symptoms (i.e., differences between the expected and actual information) to locate and correct the faults in your code (i.e., debug your code). 9. Looking Back - The Big Picture By the time you complete this assignment you should have learned many things, including but not limited to the following "big picture" issues. • UML can be used to illustrate complex systems at different levels of abstraction (i.e., with different levels of detail) and these different levels of abstraction are appropriate at different stages of the design/development process. • It is important to use decomposition when working on complex systems. For example, the fact that you implemented and tested the classes used in SunScreener before you started working on this assignment made it much easier to complete this assignment. In other words, if the two assignments had been combined into one and you had worked on the whole thing at once, it would have taken you much longer to complete (and been much more difficult to complete). • It is important to understand the advantages and disadvantages of alternative implementations before you start typing. • We often distinguish between "shallow" and "deep" copies but, in fact, there are many levels of depth. In order to make a "truly deep" copy of an object, every object has to be able to make a deep copy of itself 10. Questions to Think About The following question will help you understand the material from this assignment (and from earlier in the semester). You do not have to submit your answers, but you should make sure that you can answer them. 1. To make attributes in a class accessible to objects in other classes one can either: (a) declare the attribute to be public; (b) declare the attribute to be private and include a public "getter"; or (c) declare the attribute to be private and include a public "getter" and a public "setter". Compare these three options for prinmitive types. -9- 2. Now, compare the three options above for reference types. In particular, why are even "getters" dangerous with reference types? -10-