# Assignment 4: Documents And MapKit
**Due: Apr 26, 2020, 11:59:59 pm, v1**

NOTE THAT THIS IS AN EVOLVING DOCUMENT and will surely change to
incorporate more information and hints as the two weeks go by. UPDATE
FREQUENTLY.


## Goals
Learn to use:
- UIDocument abstractions
- Document Browser
- MapKit

You will build a biking or running GPS tracker app that saves and displays tracks
through the document browser. See the following for a short demo of a
running version of this app:

![](https://sedna.cs.umd.edu/436clips/assign4.mov)

## Tasks

The following is a suggested series of steps for you to take, together
with approximate points that each step will be worth. You can ignore
all this and just emulate the first video above. Doing that gets you
full points. However, the following set of steps is a good approach to
building this app methodically.

## Step 1: Circles (20 pts)

-Emulate the functionality of the [Circles](https://sedna.cs.umd.edu/436clips/circles.mp4) app from 4/7.


In your version:
- the browser should work,
- "+" brings up another view controller that allow you to visibly
  create something (circles are easy), saved back to a file that can
- later be-reopened

You do NOT have to create the Circles app, but slavishly
following what I did in the demo and turning in Circles will get you
20 pts (and count as a Good Faith Attempt).

## Step 2: Showing a Map (10 pts)

Go through the videos on 4/8 for [Core Location](https://sedna.cs.umd.edu/436clips/OUT12coreLocation.mp4) and [MapKit](https://sedna.cs.umd.edu/436clips/OUT12mapkit.mp4).
On clicking a "+" button we see the map *with* the user's current
position marked, if in view. A button allows the map to be
dismissed. No tracking or line drawing needed, an empty Circles file
could be written to the file system.

## Step 3: Tracking the Rider (20 pts)

- Set up location updating to get location updates.
- Keep the user centered in the middle of the screen in a region with
  an appropriate zoom level. Do this by choosing the *last* point given in
  each location update (there may be many), and creating a
  `MKCoordinateRegion` with that point as the center, and a radius of
  300 meters. 

## Step 4: Drawing the Line (20 pts)

- At each call of your `locationManager(manager:, didUpdateLocations:)`,
you will be given an array of one or more `CLLocation`s. Draw a
polyline connecting the last previous point to all the points given in
this call.
- Overload `mapView(mapView:, rendererFor overlay: )` to give your
  line appropriate attritutes: red, and lineWidth 3.

Make it work on different-sized phones, w/ orientation changes. Make
it look decent. Add a control to toggle between map and satellite views. 

## Step 5: Saving the File and Viewing Saved Files (20 pts)

Write important information to the file. Define a `GPXTrack` that
contains information about the track, including but not limited to the
set of GPS points received from Core Location.

You will need to have routines to serialize to and from JSON, which is
cast as a `Data`, which is then written/read to/from the file.


## Step 5: Somethin' Else
(10 pts)

No, I'm not talking about a classic jazz album, I mean that you must
pick and implement one of the items from the list below to get the
final 10 pts.

## Hints
- My first app used the simple format specified below.

```
struct GPXPoint: Codable {
    var latitude: Double
    var longitude: Double
    var altitude: Double
    var time: Date
}

struct GPXSegment: Codable {
    var coords : [GPXPoint]
}

struct GPXTrack : Codable {
    var name : String
    var link : String
    var time : String
    var segments : [GPXSegment] = []
    var distance = "-"
    var feetClimbed = "-"
}
```
- Your GPXDocument override both `contents()` and `load()`, and should
  probably have a property that holds a reference to the current track.

[This](assign4Example.gpx436) is an example `GPXTrack` using the default JSON
serialization to put to a file (use a text editor to look at).
  
  
## Additional Task, and Extra Credit
Pick one or two of the tasks below for the last 10 points of this project.

Pick up to another three for 10 pts bonus for each you accomplish (up to a max of three), or a donut each,
your choice. You'd have to come by to pick up the donut.  The points
will be appliable on either the `assign5` or the final (which will be
out of 200 pts):
- (5 pts) *Get your app to read and write files with the .gpx extension*.  Instead of
  reading and writing .gpx436, read and write .gpx. Here, I'm just
  asking you to get the UTI setup correct so that the document and
  browser will allow you to read and write files with the `.gpx`
  extension. Doesn't matter what you write.  Note that this is more difficult
  as the straightforward descriptions on how to do this (google) did not work
  for me. My version of the app can write to `.gpx`, but only because I use a
  very general UTI that allows me to read and write everything. I'd like
  someone to discover the trick of doing this correctly. Might take you five
  minutes. Or not.
- (5 pts) *Get your app to read and write real gpx files*. Your app should be
  able to write read and write RideWithGPX files. Don't worry, look at
  [this file](https://gitlab.cs.umd.edu/keleher/iosstudents/-/blob/master/assign4bmwRS1200GS.gpx) and you will see the format is dirt simple (though
  there may be multiple `trkseg`s).
- (5 pts) *Show a pre-planned route*. Show the route (w/ a
  different color) from another gpx file as you are recording a ride, so that the rider can
  follow a pre-planned route. Allow the user to choose which other
  ride to use by adding a button to the screen which showing a
  pre-recorded ride. Must be able to turn this off as well.
- (10 pts) *Poor man's turn-by-turn navigation* - The best way to do turn-by-turn
  navigation is to know when and where you turn onto a different
  street. We don't have that information, so you can try to use
  heuristics, like "turned left or right between 70 and 110 degrees
  and stayed on the new heading two or three points". Display the
  navigation in a line overlaying the map at the top of the
  screen. Navigation cues should be of the form: "Turn right in 50
  feet", just showing the next turn. Of course, this only works if you
  have a pre-planned route as above.
- (5 pts) *Map orientation button* - Display a little icon (maybe check out *MKCompassButton*) that when
  clicked upon changes the map orientation so that either the current
  direction of travel is "up", or north is "up". 
- (5 pts) *Tracking vs not tracking map*  By default, our app *tracks* the
  rider on the map: keeps him/her centered in the middle of the screen with a set
  magnification. Cease tracking when you detect that the rider has manipulated the display,
  either moving, zooming, or rotating. Allow the rider to restart
  tracking by hitting a button, ideally the above map orientation button.