# teaching machines

## 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.

• 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.

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
• Methods getLatitude that returns the waypoint’s latitude as a double.
• Methods getLongitude that returns the waypoint’s longitude as a double.

#### 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 the Leg is the entire remainder of the line after name. However, the whitespace appearing between name and the next non-space character is not included in the name. For example, the command name Figure 8 produces the name Figure 8. (Look at the String class for methods that remove whitespace at the beginning of a String.) The name, closed, and waypoint commands may appear in any order. However, when this leg is run, the waypoints are passed through in their order of appearance. If the name or closed commands are absent, these properties take on their default values.
• Method isClosed that returns this leg’s closed property as a boolean. 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 type boolean. It sets the closedness of the leg.
• Method getName returns the leg’s name as a String.
• Method setName that accepts as its sole parameter a name of type String. 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 type Waypoint. It appends the waypoint to the leg.
• Method getWaypointCount that returns as an int 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 type int. It returns the Waypoint specified by the index.
• Method toKml that accepts as its sole parameter a PrintWriter. It emits output in the following form to the PrintWriter:
<Placemark>
<name>NAME</name>
<styleUrl>#polylineStyle</styleUrl>
<LineString>
<coordinates>
WAYPOINT0-LONGITUDE,WAYPOINT0-LATITUDE
WAYPOINT1-LONGITUDE,WAYPOINT1-LATITUDE
WAYPOINT2-LONGITUDE,WAYPOINT2-LATITUDE
...
</coordinates>
</LineString>
</Placemark>

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 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
The artist and name commands follow the same whitespace rules as described above for a leg’s name command. A route’s description consists of the lines of text sandwiched between description and enddescription. The artist, name, description, and leg 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 a String.
• Setters for the artist, name, and description, named according to convention (setProperty) and each accepting a String as its sole parameter.
• Method addLeg that accepts as its sole a parameter a Leg. It appends the leg to the route’s list of legs.
• Method getLegCount that returns as an int 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 type int. It returns the Leg specified by the index.
• Method toKml that accepts as its sole parameter a PrintWriter. It emits output in the following form to the PrintWriter:
<Folder>
<name>NAME</name>
<description>DESCRIPTION</description>
LEG0
LEG1
LEG2
...
</Folder>

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 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 an ArrayList<String>.
• Method has that accepts as its sole a parameter an artist of type String and returns a boolean. 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 type String. It returns the list of the artist’s A-routes, or null if the artist is not included in the catalog.
• Method put that accepts as its sole a parameter an A-route of type Aroute. It appends the route to the list of routes designed by the new route’s artist.
• Method toKml that accepts as its sole parameter a PrintWriter. It emits output in the following form to the PrintWriter:
<?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>

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 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
This method creates an artist catalog and adds to it all A-route files found in the directory. It assumes the directory contains nothing but A-route files. Method listFiles in the File 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 using Arrays.sort. The catalog is written to the specified KML file, which can then be viewed in Google Earth or Google Maps.

### 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

1. Run the SpecChecker by selecting hw6 SpecChecker from the run configurations dropdown in IntelliJ IDEA and clicking the run button.