Homework 6 – A-routes – due December 15
Your objective in this homework is to learn how to marry data and code—or state and behaviors—into objects. You will do this in the context of writing a program that maps routes of runs (or jogs or walks) in Google Earth or Google Maps. The intent of the program is to promote exercise by making available a catalog of routes that are interesting in that they trace out meaningful or humorous shapes or words. In this homework, we name such routes A-routes, or Arts for short.
This assignment is more involved and less easy to test in small chunks than your previous assignments. Plan accordingly.
Before we dig into the specification, let’s talk about the structure of an A-route and its file format.
A-route
Consider the following file that describes an A-route:
artist Chris Johnson name Helleau, Claire! description This is how I greet each day. enddescription leg name h closed false waypoint 44.801799 -91.491848 waypoint 44.799473 -91.492579 waypoint 44.800465 -91.492256 waypoint 44.799940 -91.489048 waypoint 44.798897 -91.489402 endleg leg name base of i closed false waypoint 44.798638 -91.487889 waypoint 44.799698 -91.487546 waypoint 44.801051 -91.487363 endleg leg name jot of i closed true waypoint 44.801744 -91.487277 waypoint 44.802452 -91.487889 waypoint 44.802916 -91.486591 waypoint 44.802178 -91.486323 endleg
Let’s walk through this file in chunks. Here’s the first section:
artist Chris Johnson name Helleau, Claire! description This is how I greet each day. enddescription
This section defines who designed the A-route and gives it a meaningful name and description. Following are descriptions of the route’s three legs, like this one:
leg name h closed false waypoint 44.801799 -91.491848 waypoint 44.799473 -91.492579 waypoint 44.800465 -91.492256 waypoint 44.799940 -91.489048 waypoint 44.798897 -91.489402 endleg
As suggested by the name, this leg draws a lowercase H. It is not closed; it does not end where it started. It consists of five latitude-longitude pairs, or waypoints, that define the path.
Normal runs consist of a single leg. To support more kinds of drawing, however, we allow A-routes to consist of a series of disconnected legs. In a sense, each leg is a separate stroke, in between which the runner “lifts the pen.” Here, the second and third legs draw the two parts of a lowercase I.
KML
In this homework, we’ll collect a bunch of these A-routes into a catalog of the routes organized by artist. This catalog is expressed in the Keyhole Markup Language (KML). The name derives from Keyhole, Inc., a geoinformatics company acquired by Google in 2004 as part of its expansion into mapping services.
If our catalog contains only the example above, our program produces the following KML file:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>A-routes by Artist</name>
<Style id="polylineStyle">
<LineStyle>
<color>b3004dff</color>
<width>10</width>
</LineStyle>
</Style>
<Folder>
<name>Chris Johnson</name>
<Folder>
<name>Helleau, Claire!</name>
<description>This is how I greet each day.</description>
<Placemark>
<name>h</name>
<styleUrl>#polylineStyle</styleUrl>
<LineString>
<coordinates>
-91.491848,44.801799
-91.492579,44.799473
-91.492256,44.800465
-91.489048,44.799940
-91.489402,44.798897
</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>base of i</name>
<styleUrl>#polylineStyle</styleUrl>
<LineString>
<coordinates>
-91.487889,44.798638
-91.487546,44.799698
-91.487363,44.801051
</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>jot of i</name>
<styleUrl>#polylineStyle</styleUrl>
<LineString>
<coordinates>
-91.487277,44.801744
-91.487889,44.802452
-91.486591,44.802916
-91.486323,44.802178
-91.487277,44.801744
</coordinates>
</LineString>
</Placemark>
</Folder>
</Folder>
</Document>
</kml>
When we view this file in Google Earth, we see this map:
You can test this yourself by saving the file to your computer and opening it in Google Earth.
In general, we can expect many files to be in the catalog, with many artists having designed many runs. These can be navigated using the hierarchy in the left pane.
Google Maps
KML files can also be viewed in Google Maps. To load a KML file into Google Maps, follow these steps:
- Visit maps.google.com.
- Click on the hamburger icon (the stack of three horizontal lines) on the top-left.
- Navigate to Your Places / Maps.
- Click Create Map.
- Import the KML file.
However, Google Maps doesn’t support all features of KML. In particular, it doesn’t acknowledge the hierarchical organization of the artist catalog. For this reason, we recommend downloading and testing with Google Earth.
Creating Your Own
To create your own map, handcraft an A-route file. To determine the waypoints, visit Google Maps, find some roads or trails that will support the shapes or words that you want to trace, and identify the latitude-longitude pairs by tapping on the map or right-clicking and selecting What’s Here? A small dialog will appear at the bottom of the screen. Click on the latitude-longitude, which will load a panel from which you can copy and paste the coordinates.
Requirements
Complete the classes described below. Place all classes in package hw6
.
Main
Write class Main
with a main
method, which you are encouraged to use to test your code. Nothing in particular is required of it, but it must exist.
Waypoint
Write class Waypoint
with the following methods:
- A constructor that accepts two parameters in the following order:
- a latitude of type
double
- a longitude of type
double
- a latitude of type
- Methods
getLatitude
that returns the waypoint’s latitude as adouble
. - Methods
getLongitude
that returns the waypoint’s longitude as adouble
.
Leg
Write class Leg
that represents one stretch of an A-route. It encapsulates a named collection of waypoints and has the following methods:
- A default constructor that initializes this leg of an A-route to have the name
"Unnamed Leg"
, to not be a closed leg, and to not have any waypoints. - A constructor that initializes this leg of an A-route by parsing a leg specification from an A-route file. It accepts as its sole parameter a
Scanner
that is poised to read the leg specification. For example, it might read this text:name jot of i closed true waypoint 44.801744 -91.487277 waypoint 44.802452 -91.487889 waypoint 44.802916 -91.486591 waypoint 44.802178 -91.486323 endleg
The name of theLeg
is the entire remainder of the line aftername
. However, the whitespace appearing betweenname
and the next non-space character is not included in the name. For example, the commandname Figure 8
produces the nameFigure 8
. (Look at theString
class for methods that remove whitespace at the beginning of aString
.) Thename
,closed
, andwaypoint
commands may appear in any order. However, when this leg is run, the waypoints are passed through in their order of appearance. If thename
orclosed
commands are absent, these properties take on their default values. - Method
isClosed
that returns this leg’s closed property as aboolean
. A closed leg is one that ends where it started. - Method
setClosed
that accepts as its sole parameter the leg’s new closed property of typeboolean
. It sets the closedness of the leg. - Method
getName
returns the leg’s name as aString
. - Method
setName
that accepts as its sole parameter a name of typeString
. It sets the leg’s name to the given name. - Method
addWaypoint
that accepts as its sole parameter the next waypoint on this leg, of typeWaypoint
. It appends the waypoint to the leg. - Method
getWaypointCount
that returns as anint
the current number of waypoints on this leg. - Method
getWaypoint
that accepts as its sole parameter the index of a waypoint within this leg, of typeint
. It returns theWaypoint
specified by the index. - Method
toKml
that accepts as its sole parameter aPrintWriter
. It emits output in the following form to thePrintWriter
:The capitalized words are placeholders; they should be replaced with the actual properties of this leg. The latitudes and longitudes are formatted to include 6 digits after the decimal point. If the leg is closed, the final line of the<Placemark> <name>NAME</name> <styleUrl>#polylineStyle</styleUrl> <LineString> <coordinates> WAYPOINT0-LONGITUDE,WAYPOINT0-LATITUDE WAYPOINT1-LONGITUDE,WAYPOINT1-LATITUDE WAYPOINT2-LONGITUDE,WAYPOINT2-LATITUDE ... </coordinates> </LineString> </Placemark>
coordinates
element is a repeat of the first line, containing the longitude and latitute of waypoint 0.
Aroute
Write class Aroute
that represents an A-route. It encapsulates a collection of legs and has the following methods:
- A default constructor that initializes this A-route to have the name
"Unnamed A-route"
, to be designed by the artist"Unknown"
, to have a blank description, and to have 0 legs. - A constructor that initializes this A-route by parsing an A-route specification from a file. It accepts as its sole parameter a
File
. For example, the file might include this text:artist Chris Johnson name Helleau, Claire! description This is how I greet each day. enddescription leg name h closed false waypoint 44.801799 -91.491848 waypoint 44.799473 -91.492579 waypoint 44.800465 -91.492256 waypoint 44.799940 -91.489048 waypoint 44.798897 -91.489402 endleg leg name base of i closed false waypoint 44.798638 -91.487889 waypoint 44.799698 -91.487546 waypoint 44.801051 -91.487363 endleg leg name jot of i closed true waypoint 44.801744 -91.487277 waypoint 44.802452 -91.487889 waypoint 44.802916 -91.486591 waypoint 44.802178 -91.486323 endleg
Theartist
andname
commands follow the same whitespace rules as described above for a leg’sname
command. A route’s description consists of the lines of text sandwiched betweendescription
andenddescription
. Theartist
,name
,description
, andleg
commands may appear in any order. However, when this route is run, the legs are passed through in their order of appearance. If any command is absent, the missing property takes on its default value. - Getters for the artist, name, and description, named according to convention (
getProperty
) and each returning the property as aString
. - Setters for the artist, name, and description, named according to convention (
setProperty
) and each accepting aString
as its sole parameter. - Method
addLeg
that accepts as its sole a parameter aLeg
. It appends the leg to the route’s list of legs. - Method
getLegCount
that returns as anint
the current number of legs on this A-route. - Method
getLeg
that accepts as its sole parameter the index of a leg within this route, of typeint
. It returns theLeg
specified by the index. - Method
toKml
that accepts as its sole parameter aPrintWriter
. It emits output in the following form to thePrintWriter
:The capitalized words are placeholders; they should be replaced with the actual properties of this A-route. The legs should be emitted in the KML format specified for<Folder> <name>NAME</name> <description>DESCRIPTION</description> LEG0 LEG1 LEG2 ... </Folder>
Leg
.
ArtistCatalog
Write class ArtistCatalog
that represents a collection of A-routes organized by their artists. This class is meant to act as an array that is indexed not by an integer, but by an artist name. To retrieve all A-routes designed by artist Footographer
, for example, we’d write catalog.get("Footographer")
.
We recommend you implement this class using two parallel lists: one for artist names and the other for the A-routes designed by the artist that appears in the corresponding slots of the artist names list. In future courses you will learn of implementations that make better use of memory and the CPU using a technique called hashing.
This class has the following methods:
- A default constructor that initializes this catalog to have 0 artists and routes.
- Method
getArtists
that returns the list of artists in the order that were added to the catalog. The list is returned as anArrayList<String>
. - Method
has
that accepts as its sole a parameter an artist of typeString
and returns aboolean
. It returns true if and only if this artist is included in the catalog. - Method
get
that accepts as its sole a parameter an artist of typeString
. It returns the list of the artist’s A-routes, ornull
if the artist is not included in the catalog. - Method
put
that accepts as its sole a parameter an A-route of typeAroute
. It appends the route to the list of routes designed by the new route’s artist. - Method
toKml
that accepts as its sole parameter aPrintWriter
. It emits output in the following form to thePrintWriter
:The capitalized words are placeholders; they should be replaced with the actual properties of the artists and routes. The A-routes should be emitted in the KML format specified for<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <name>A-routes by Artist</name> <Style id="polylineStyle"> <LineStyle> <color>b3004dff</color> <width>10</width> </LineStyle> </Style> <Folder> <name>ARTIST0</name> ARTIST0-AROUTE0 ARTIST0-AROUTE1 ARTIST0-AROUTE2 </Folder> <Folder> <name>ARTIST1</name> ARTIST1-AROUTE0 </Folder> ... </Document> </kml>
Aroute
.
Utilities
Write class Utilities
with the following method:
- Static method
directoryToKml
that accepts two parameters in the following order:- A directory of type
File
containing 0 or more A-route files - A KML file of type
File
to which to write an artist catalog
listFiles
in theFile
class is useful here, but its results are not guaranteed to be in any particular order—which leads to indeterminate results and complicates testing. Before adding the files to the catalog, it sorts the files by name usingArrays.sort
. The catalog is written to the specified KML file, which can then be viewed in Google Earth or Google Maps. - A directory of type
Extra
For an extra credit participation point, create an A-route file for a run of your own design. Share your file and screenshot of it from Google Earth or Google Maps on Piazza under folder ec6
by the due date. The submission garnering the most votes will be honored in some way.
Submission
To check your work and submit it for grading:
- Run the SpecChecker by selecting
hw6 SpecChecker
from the run configurations dropdown in IntelliJ IDEA and clicking the run button. - Fix problems until all tests pass.
- Commit and push your work to your repository.
- Verify on GitLab that your submission uploaded successfully.
A passing SpecChecker does not guarantee you credit. Your grade is conditioned on a few things:
- You must meet the requirements described above. The SpecChecker checks some of them, but not all.
- You must not plagiarize. Write your own code. Talk about code with your classmates. Ask questions of your instructor or TA. Do not look at others’ code. Do not ask questions specific to your homework anywhere online but Piazza. Your instructor employs a vast repertoire of tools to sniff out academic dishonesty, including: drones, CS 1 moles, and a piece of software called MOSS that rigorously compares your code to every other submission. You don’t want to live in a world serviced by those who achieved their credentials by questionable means. For your future self, career, and family, do your own work.
- Your code must be submitted correctly and on time. Machine and project issues are common—anticipate them. Commit early and often to Git. Extensions will not be granted. If you need more time to make things work, start earlier.