Tutorial: Make Pokemon Go like app using google maps for iOS in Swift 4

Developed using only Google Maps in Swift 4 — an iOS app just like Pokemon Go

Chaudhry Talha 🇵🇸
17 min readFeb 21, 2019
Morning, Evening and Night View of the game (Old Screenshots)

The Game (Dave Diamonds)

I’m calling the game Dave Diamonds and in this game we have a character named Dave and we have objects randomly floating around Washington DC, that Dave has to get close enough to be able to tap and add to collection.

Three type of objects (Diamond, Butterfly, Feather) are randomly placed in Washington DC and when user get in close enough range with any object he can tap the object and the object will be added (+1) in the inventory he has and will disappear from the map.

One extra feature that I’ve added, just to give it a cool feel is — Based on the time on your app it’ll change the map view to morning, evening or night. The game doesn’t use any 3D graphics, just simple GIF images used and google map settings make it look very close to the experience of Pokemon Go like app.

This is how the game will look like

Create xCode Project

Open xCode and create a new project:

Select Single View App and click Next
For Product Name type DaveDiamonds

As I am going to test the app on an iPhone and I encourage you do the same as you are going through this tutorial so you need to have a developer account to be able to test the app on iPhone.

Installing Pods

Open up terminal and type the following command:

$ cd <path to the project you just created>
It is always easy to type cd and the drag the project folder into terminal window and it’ll automatically fetch the path of the project

Next type:

$ touch Podfile
$ open Podfile -a textedit

First line will create and empty file without any extension names Podfile in the project folder. Second line will open the file in TextEdit.

Paste the following code in TextEdit, save it and close TextEdit.

use_frameworks!target ‘DaveDiamonds’ dopod ‘TPKeyboardAvoiding’
pod ‘GoogleMaps’
pod ‘PopupDialog’
end
The only required pod here is the google maps one. I’m using PopupDialog to better looking alerts and TPKeyboardAvoiding is not used anywhere in this tutorial so you can skip that I added this as I was building the project but then when writing this tutorial I didn’t end up using that.

Next in terminal type

$ pod install
A successful pods install will look like this

Getting Google Maps API Key

To complete this tutorial, you need a Google API key that’s authorized to use the Maps SDK for iOS.

GET A KEY

Click on New Project or project name which is selected by default.

If you already have other projects in developers console the click on the current project a new to add a new project

In Project Name type DaveDiamonds and click Create. Then click on Create credentials and select API key.

API key will generate for you next click on Restrict Key button.

Restricting key is good as it adds an additional protection layer

Select iOS apps under Application restrictions. Paste Bundle identifier from xCode General project settings and Save.

and finally you’ll have a fully secure API key for google maps.

Adding API key in xCode Project

Open xCode by selecting DaveDiamonds.xcworkspace file and then select AppDelegate.swift and add the following code:

import GoogleMaps

and then in didFinishLaunchingWithOptions add this line:

GMSServices.provideAPIKey(“PUT_YOUR_API_KEY_HERE”)
AppDelegate.swift file

Setting up User Interface

If you don’t want to play around with perfecting the UI you can skip to the next step: The Game Logic

In this section we will place objects from library on our ViewController. The interface is very simple, it consist of just one screen on which the map and the inventory is displayed. Our ViewController will consist of the following:

  • 4 UIView
  • 1 UIView → GMSMapView
  • 3 UIImageView
  • 3 UILabel

Open Main.storyboard and on ViewController add 4 UIView objects.

Match the Autoresizing setting as per the screenshot below:

The red arrows inside the box should be the ones that are turned on.

Open ViewController.swift and import the following:

import GoogleMapsimport CoreLocationimport PopupDialog

Then add the following right after class ViewController: UIViewController {

@IBOutlet weak var gameScoreView: UIView!@IBOutlet weak var diamondScoreView: UIView!@IBOutlet weak var butterflyScoreView: UIView!@IBOutlet weak var featherScoreView: UIView!

Connect the IBOutlets with the objects.

Select gameScoreView from the four UIView you have and apply the following settings in Size inspector and Attributes inspector:

X = 0, Y = 422
Width = 70, Height = 194

Hex Color = FFFFFF (White)
Opacity = 50%

Now drag the three UIView which are left under gameScoreView.

Select diamondScoreView and apply the following settings in Size inspector and Attributes inspector:

X = 10, Y = 10
Width = 50, Height = 50

Hex Color = 000000 (Black)
Opacity = 50%

Now select butterflyScoreView and apply the following settings in Size inspector and Attributes inspector:

X = 10, Y = 72
Width = 50, Height = 50

Hex Color = 000000 (Black)
Opacity = 50%

Finally, featherScoreView and apply the following settings in Size inspector and Attributes inspector:

X = 10, Y = 134
Width = 50, Height = 50

Hex Color = 000000 (Black)
Opacity = 50%

By now your app should look like this:

Open ViewController.swift and add this function:

//MARK: ScoreView
func setUpScoreView() {
self.view.bringSubviewToFront(gameScoreView)
gameScoreView.layer.cornerRadius = 10
gameScoreView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]

diamondScoreView.layer.cornerRadius = 25
butterflyScoreView.layer.cornerRadius = 25
featherScoreView.layer.cornerRadius = 25

diamondScoreView.layer.masksToBounds = true
butterflyScoreView.layer.masksToBounds = true
featherScoreView.layer.masksToBounds = true
}

Call this function in viewDidLoad method:

override func viewDidLoad() {super.viewDidLoad()setUpScoreView()}

Download this zip file, extract it and import the images in the Assets.xcassets

Open Main.storyboard and add 3 UIImageView and 3 UILabel to ViewController Scene and update Autoresizing (red arrows)

Add the following IBOutlets connect in ViewController.swift file and connect it with the UILabel objects on ViewController Scene.

@IBOutlet weak var diamondScoreLabel: UILabel!@IBOutlet weak var butterflyScoreLabel: UILabel!@IBOutlet weak var featherScoreLabel: UILabel!

Resize all the threeUIImageView you just added to:

Width = 25, Height = 25

Now select one UIImageView and Diamond Score Label and move it under Diamond Score View and do the same for the rest of the two Labels and image views. By now your Scene should look like this:

Give the following X and Y values to all the three Image View

X = 13, Y = 3

Give image name of top Image View: diamond-static
Give image name of middle Image View: butterfly-static
Give image name of bottom Image View: feather-static

Change Diamond Score Label, Butterfly Score Label, Feather Score Label values in Size Inspector and Attributes Inspector

X = 8, Y = 28

Width = 34, Height = 18

Font Size = 16

Font Family = System Bold

Font Color = FFFFFF (White)

Font Align = Center

Text = 00

Next add a UIView to ViewController set its Autoresizing too.

Change it’s class to GMSMapView in Identity Inspector.

Create it’s IBOutlet

Select mapView and apply the following settings in Size inspector and Attributes inspector:

X = -126
Y = 0
Width = 627
Height = 1118
Background = (Light Black)

Move Map View on the top of Game Score View in Document outline as show below. (Optional)

Run the app now and you’ll be able to see this:

Run the app and it should look like this

The Game Logic

Now that the UI is set, Map is visible, We are going to jump straight into the game coding part using the following steps:

  1. Adding GIF support file and gif images into project.
  2. Initialize Map with a default location, setting google map, apply theme based on the day and getting permission from user to access their location.
  3. Adding random markers to the map

1. Adding GIF support file and gif images into project

Create a new group in your project and rename it to GIF

Download Dave-Diamonds-GIFs.zip → Extract it and add the four GIF images in the GIF folder you just created (Don’t forget to check Copy items if needed)

These three types of objects that you just added in the GIF folder are the ones which Dave will collecting. I found these images by randomly searching on the internet. You might run into issues like lagging as these icons are heavy gif files and it is never preferred to store them locally but for the sake of this tutorial we are storing it locally.

Diamond — Butterfly — Feather

Add a new file in you project name it GIFSupport.swift and give it NSObject as subclass.

Copy and paste the following code in it:

Swift file that let you add GIF images in UIImageView

Initialize Map with a default location, setting google map, apply theme based on the day and getting permission from user to access their location.

Open ViewController.swift and extend with GMSMapViewDelegate and CLLocationManagerDelegate

class ViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate {

After that declare the following variables:

var locationManager = CLLocationManager() //Help in setting up user locationvar userLocation = CLLocation() //Keep track of user locationvar bearingAngle = 270.0 //Bearing is the orientation of the camera. Bearing is the direction in which determines where the map camera will face.var angleOfView = 65.0 //In google maps 65 is the maximum value and also this is the angle that will give it a bit of 3D look.var zoomLevel:Float = 18 //This is about right level of zoom as per the size of character we are using.var capitolLat = 38.889815 //Default location if the map if user location is not available will be US capital.var capitolLon = -77.005900 //Default location if the map if user location is not available will be US capital.var userMarker = GMSMarker() //Marker to represent user locationlet userMarkerimageView = UIImageView(image: UIImage.gifImageWithName(“player”)) //Initializing the Image view of player marker gif iconvar diamond1Score = 00

Let’s add the themes for day, evening and night modes. Experiments with google has this really cool wizard that let you add styles to the map, it’s called Styling Wizard: Google Maps APIs. You can explore it of your own but for now you can DOWNLOAD THESE THREE JSON FILES and add them to the project. I’ve added them in a new group I made in project called MapViews.

Create a function after viewDidLoad() called func setMapTheme(theme: String)

func setMapTheme(theme: String) {if theme == “Day” {do {if let styleURL = Bundle.main.url(forResource: “DayStyle”, withExtension: “json”) {mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)} else {NSLog(“Unable to find DayStyle.json”)}} catch {NSLog(“One or more of the map styles failed to load. \(error)”)}} else if theme == “Evening” {do {if let styleURL = Bundle.main.url(forResource: “EveningStyle”, withExtension: “json”) {mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)} else {NSLog(“Unable to find EveningStyle.json”)}} catch {NSLog(“One or more of the map styles failed to load. \(error)”)}} else {do {if let styleURL = Bundle.main.url(forResource: “NightStyle”, withExtension: “json”) {mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)} else {NSLog(“Unable to find NightStyle.json”)}} catch {NSLog(“One or more of the map styles failed to load. \(error)”)}}}

Next we will create a function which will center the map at user location. So after set map theme function create a new function called func centerMapAtUserLocation()

func centerMapAtUserLocation() {//get user current location coordinateslet locationObj = locationManager.locationlet coord = locationObj?.coordinatelet lattitude = coord?.latitudelet longitude = coord?.longitude//Uncomment isMyLocationEnabled to hide blue marker underneath the player//mapView.isMyLocationEnabled = trueuserMarkerimageView.frame = CGRect(x: 0, y: 0, width: 40, height: 70)//center camera on those coordinateslet camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: lattitude ?? capitolLat, longitude: longitude ?? capitolLon, zoom: zoomLevel, bearing: bearingAngle, viewingAngle: angleOfView)self.mapView.animate(to: camera)}

As it is a requirement that we need to have user’s location so we are going to ask user for it even if they deny it. So let’s create a function func checkUserPermission()

func checkUserPermission() {locationManager.delegate = selfif CLLocationManager.locationServicesEnabled() {switch (CLLocationManager.authorizationStatus()) {case .notDetermined:perform(#selector(presentNotDeterminedPopup), with: nil, afterDelay: 0)case .restricted, .denied:perform(#selector(presentDeniedPopup), with: nil, afterDelay: 0)case .authorizedAlways, .authorizedWhenInUse:self.locationManager.desiredAccuracy = kCLLocationAccuracyBestself.locationManager.startUpdatingLocation()locationManager.startUpdatingHeading()centerMapAtUserLocation() //step 3}} else {perform(#selector(presentDeniedPopup), with: nil, afterDelay: 0)}}

The two selector methods that are missing and giving this error are the methods which will determine what is the status of user location permission and will show the dialogue as per. I’ve used PopupDialog a nice UI library to show alerts, it’s not mandatory but as I like nice UI even for the small projects I do that is why I’ve used it. Go ahead and Add the following two methods:

@objc private func presentNotDeterminedPopup() {let title = “Allow Location”let message = “Allow location to discover and collect diamonds near you.”let image = UIImage(named: “userLocation-cover”)let popup = PopupDialog(title: title, message: message, image: image)let skipButton = CancelButton(title: “Skip for now”) {//print(“You canceled the car dialog.”)self.dismiss(animated: true, completion: nil)}let okButton = DefaultButton(title: “Okay”) {//self.locationManager.delegate = selfself.locationManager.requestWhenInUseAuthorization()}popup.addButtons([skipButton, okButton])self.present(popup, animated: true, completion: nil)}@objc private func presentDeniedPopup() {let title = “Allow Location”let message = “Allow location to discover and collect diamonds near you. Open setting and allow location when in use.”let image = UIImage(named: “userLocation-cover”)let popup = PopupDialog(title: title, message: message, image: image)let skipButton = CancelButton(title: “Skip for now”) {print(“You canceled the car dialog.”)}let settingsButton = DefaultButton(title: “Open Settings”, dismissOnTap: false) {guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {return}if UIApplication.shared.canOpenURL(settingsUrl) {UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)}}popup.addButtons([skipButton, settingsButton])self.present(popup, animated: true, completion: nil)}

By now all the errors should be resolved. We are almost done with this part and the last method will bring all of these method together.

As we want to check the status every time user loads the app so we need to add this delegate method didChangeAuthorization so that in case user has changed the authorization we can push them to allow it.

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {switch status {case .notDetermined:perform(#selector(presentNotDeterminedPopup), with: nil, afterDelay: 0)case .restricted, .denied:perform(#selector(presentDeniedPopup), with: nil, afterDelay: 0)case .authorizedAlways, .authorizedWhenInUse:self.locationManager.desiredAccuracy = kCLLocationAccuracyBestself.locationManager.startUpdatingLocation()locationManager.startUpdatingHeading()self.centerMapAtUserLocation() //step 3}}

Next Make a new method called initializeMap()

func initializeMap() {self.mapView.delegate = selflet camera = GMSCameraPosition.camera(withLatitude: capitolLat, longitude: capitolLon, zoom: zoomLevel, bearing: bearingAngle,viewingAngle: angleOfView)self.mapView.camera = camera//set map modelet hour = Calendar.current.component(.hour, from: Date())switch hour {case 7..<15 : setMapTheme(theme: “Day”)case 15..<18 : setMapTheme(theme: “Evening”)default: setMapTheme(theme: “Night”)}//Interaction with mapself.mapView.settings.tiltGestures = falseself.mapView.settings.rotateGestures = falseself.mapView.settings.zoomGestures = falseself.mapView.settings.compassButton = truemapView.settings.allowScrollGesturesDuringRotateOrZoom = truemapView.settings.indoorPicker = false//mapView.isBuildingsEnabled = falseself.mapView.settings.scrollGestures = false//CenterMap with user locationcheckUserPermission() //step 2}

This method is setting the map to a default location in case we don’t have user permission for the location and then it is determining which hour of the day it is and setting the theme accordingly and finally we have the setting that don’t let user scroll though the map with gestures in other words we are restricting user to move in order to discover diamonds on the map.

Next set the NSLocationWhenInUseUsageDescription in info.plist

<key>NSLocationWhenInUseUsageDescription</key><string>Location is required so that you can move and discover diamonds.</string>

As a last thing call initializeMap() from viewDidLoad() method.

Run the app now and this is pretty what the app will be doing right now:

So now you have achieved a 3D looking map. Based on my local time it’s 11:36PM which means it’s night so that is why the map is dark. But the issue with this right now is that even though I’ve allowed my location it’s still at US Capitol building. It’s missing the delegate methods that we need to add. These methods will keep an eye out for any user location changes. So go ahead and add the following method:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {userLocation = locations.last ?? CLLocation(latitude: capitolLat, longitude: capitolLon)}

As we also want to rotate the map as user rotates their phone so we need to add another delegate method didUpdateHeading which will determine in which direction user is heading.

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude, zoom: zoomLevel, bearing: bearingAngle, viewingAngle: angleOfView)self.mapView.animate(to: camera)mapView.animate(toBearing: newHeading.magneticHeading)//delete the old user location marker firstuserMarker.map = niluserMarker.position = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)userMarker.iconView = userMarkerimageViewuserMarker.groundAnchor = CGPoint(x: 0.5, y: 1.0)userMarker.map = mapView}

This method is first creating the camera and animating with coordinates as per last user location and then animating the user heading and finally adding the custom user marker to the map. Now if you’ll run the app it’ll take you to user location will move the user marker as you move and also rotate the map as you rotate your phone. But, right now the map is empty meaning there is nothing to do and we need to add markers so our next step is:

Adding random markers to the map

First we will create a function that will return the distance in meters between two markers:

func distanceInMeters(marker: GMSMarker) -> CLLocationDistance {let markerLocation = CLLocation(latitude: marker.position.latitude , longitude: marker.position.longitude)let metres = locationManager.location?.distance(from: markerLocation)return Double(metres ?? -1) //will be in metres}

Next we will add the function addMarkers which will randomly place markers over DC. So I randomly hard coded 100 DC lat and lon values, if you are at a different location you won’t be able to view them as it might be very far for you.

func addMarkers() {let diamond1Gif = UIImage.gifImageWithName(“diamond1”)let diamond1GifView = UIImageView(image: diamond1Gif)diamond1GifView.frame = CGRect(x: 0, y: 0, width: 70, height: 70)let randomLatDC = [38.921074,38.87501,38.920387,38.876737,39.120045,39.099376,39.083673,39.123513,38.990249,39.107709,38.982456,39.025387,39.095661,38.989724,38.975,38.977933,38.99237538,38.990639,38.977093,39.102099,39.094103,39.076331,39.102212,38.992679,38.999388,38.997033,39.114688,39.110314,38.923583,38.90706,38.898536,38.908473,38.878433,38.873755,38.862753,38.999634,38.96115,38.899703,38.837666,38.873219,38.869418,38.941154,39.103091,39.097636,38.997445,38.928121,38.917761,38.889935,38.930282,38.896544,38.905126,38.88732,38.844711,38.876393,38.850337,38.896923,38.9024,38.885801,38.896355,38.878854,38.922649,38.928743,38.882788,38.88397,38.884734,38.888553,38.888767,38.87887,38.894573,38.893237,38.89593,38.89054,38.88081,38.881044,39.085394,38.900358,38.952369,38.975219,38.920682,38.866471,38.839912,39.119765,38.964992,39.084379,38.984691,38.88992,38.903663,38.804378,38.894941,38.869442,38.898243,38.897612,38.901755,38.801111,38.82175,38.802677,38.820064,38.82595,38.820932]let randomLonDC = [-77.031887,-77.0024,-77.025672,-76.994468,-77.156985,-77.188014,-77.149162,-77.15741,-77.02935,-77.152072,-77.091991,-77.044563,-77.159048,-77.023854,-77.01121,-77.006472,-77.100104,-77.100239,-77.094589,-77.200322,-77.132954,-77.141378,-77.177091,-77.029457,-77.031555,-77.025608,-77.171487,-77.182669,-77.050046,-77.015231,-76.931862,-76.933099,-77.03023,-77.089233,-77.05428,-77.109647,-77.088659,-77.008911,-77.09482,-77.082104,-77.095596,-77.062036,-77.196442,-77.196636,-77.023894,-77.023795,-77.04062,-76.93723,-77.055599,-76.96012,-77.056887,-76.983569,-76.987823,-77.107735,-77.100989,-77.086502,-77.02622,-77.097745,-77.078408,-77.005727,-77.077271,-77.012457,-77.103148,-77.10783,-77.093485,-77.032429,-77.02858,-77.1207,-77.01994,-77.086063,-77.089006,-77.08095,-77.090792,-77.111768,-77.145803,-77.012108,-77.002721,-77.016855,-76.995876,-77.076131,-77.087083,-77.166093,-77.103381,-77.146866,-77.094537,-77.071301,-77.067668,-77.060866,-77.09169,-77.104503,-77.026235,-77.080851,-77.051084,-77.068952,-77.047494,-77.063562,-77.057619,-77.058541,-77.053096]for i in 0..<randomLonDC.count {var marker: GMSMarker?let position = CLLocationCoordinate2D(latitude: randomLatDC[i], longitude: randomLonDC[i])marker = GMSMarker(position: position)marker?.title = “Distance Left: \(round(100*distanceInMeters(marker: marker!)*0.00062137)/100) miles” //converting meters to milesmarker?.map = mapViewmarker?.iconView = diamond1GifView}}

This method first created the image view for the diamond gif. Then initialize lat and lon for Washington DC and finally add them to the map. I’ve added title of the marker to the distance in miles. So when you’ll select a marker on map it’ll show how far are you from that point . Also I’ve only added one type of diamond for the sake of tutorial.

Add addMarker() method in viewDidload() and run the app.

I can see two markers near my location so that means out of the 100 I’ve added there are 98 more…

So now you have the map rotating in with user, user icon that moves as you change location and animated diamonds which you can tap to see how far were you from them.

Next all you need to do is to see when user tap on a marker and they are close to it (I’ve given close distance to be at least 0.2 miles) then it’ll be added to user collection otherwise it’ll show a popup that it’s too far. To achieve this we’ll take help of the delegate method didTap marker

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {let distanceinMiles = round(100*distanceInMeters(marker: marker)*0.00062137)/100print(distanceinMiles)if distanceinMiles < 0.2 {let title = “Added to collection”let message = “Marker added to your collection”let popup = PopupDialog(title: title, message: message)let okButton = DefaultButton(title: “Yayyy!”) {self.diamond1Score = self.diamond1Score + 1self.diamondScoreLabel.text = “\(self.diamond1Score)”//destory that markermarker.map = nil}popup.addButton(okButton)self.present(popup, animated: true, completion: nil)} else {let title = “Too Far!”let message = “You’re too far from this diamond. Get closer!”let popup = PopupDialog(title: title, message: message)let okButton = DefaultButton(title: “Ok”) {}popup.addButton(okButton)self.present(popup, animated: true, completion: nil)}return true}

RUN IT!

The final game view will look like this

Ending Note:

Here is the full project: https://github.com/ibjects/DaveDiamonds

Do share in comments if you can think of any cool idea which can be made using this approach, I’ve share some below. Also feel free to ask questions and post suggestions on how can I improve this article or what other functionality I can add to it and finally don’t forget to hit that clap button! :)

Some cool ideas that you can make using this approach:

  1. Pass the Torch: The idea is when you help a poor/homeless person on your way just drop a pin so that other people can also discover them and can help them. You would need to do a research that how often do they change their spots but what I’ve seen generally is they are at the same spot most of the times.
  2. Make a fitness app that encourages people to walk around, find and collect different objects from which they can claim prizes related to fitness like track suit, water bottle, Cell Phone Armbands etc. For example if the objects are diamond, butterfly and feather it’ll take them 20 diamonds, 50 Butterfly and 80 feathers to claim cell phone armband.
  3. Make a networking/dating app in which when you turn on the app you can walk around and see other people in real time on the app and you can go talk to them just like walking dog networking app.
  4. Scavenger hunt app in which all users registered with the app are required to collect certain types of objects and before the time runs out the user who has the most objects from the list will be the winner.
  5. Take a brand on board let’s say McDonalds and for a day they put a free meal offer at one of their franchise and users have to find it in order to avail it.
  6. Discover Music App. Explore the songs that people have dropped on the map. As you are walking towards your destination pick up songs along the way and listen to what people have dropped at a specific pin as some songs are just right for that moment and view. Same thing can be applied where people can share free ebooks and other type of media like podcasts.
  7. A public short video sharing platform, where people can go to a location and records a video message and post it while they are there. Other people when they are at that exact point can see that messages. Let’s say someone posted a video 3 years ago and they discover it again, that would be cool right.

--

--