AODC2019でElixirでHERE API超入門した話

こんにちは。

今日、Asia Open Data Challenge 2019で出会った
HERE API( =HERE社が提供する地図API)に入門しました

Asia OpenData Challenge2019について知りたいかたは↓↓を参照くださいませmm

[賞金 $3,500 - 4ヶ国で競うアジアのハック](https://note.mu/tomoaoki/n/nb1fa018a273b)

アジアのハックということで海外の地図。
今回はタイのバンコクエリアで、使っていきたいと思います

![Get started with HERE A](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/adf9f71b-7f0e-e0d5-c2b5-26c27d89a70f.png)


## 入門の流れ

1. アカウントを登録
  * Here社のdeveloper向けサイトは[こちら](https://developer.here.com/)

2. どんなAPIがあるのか確認
  * HEREのドキュメント([こちら](https://developer.here.com/documentation))を確認
  * 提供されているAPIからいくつかピックアップして使ってみます

3. 実際に使ってみる & 動かしてみる

## まずは Hereのdeveloperアカウントを登録します。

* 任意のブラウザで [Hereのdeveloeperサイト](https://developer.here.com)の開きます
  * Hereのページがページが表示されます
  
<img width="1429" alt="スクリーンショット 2019-07-07 10.01.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/93a54d93-dce2-e364-89aa-6c68b1dc0a9d.png">

* 右上の**GET STARTED FOR FREE** のボタンを押します。
  * ↓↓ようなアカウント登録の画面が表示されます

<img width="1432" alt="スクリーンショット 2019-07-07 10.03.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/f9a44e60-d825-ab7d-3250-dd7ee496e179.png">

* アカウント登録画面に情報を入力します
  * First Name(名) / Last Name(氏) / EMailに自身の情報を入力
  * Passwordには、強固なパスワードを入力
  * Country/regionは、適切な国を選択
    * 私は日本国籍・日本在住なので `Japan` を選択しています
  * Security Checkは画面に表示された文字列を適切に入力
* 一番下の **Register for a HERE account**  ボタンを押すとアカウント登録されます
  * ボタンを押す前に、Service Terms / Privacy Policyをちゃんと読みます
<img width="786" alt="スクリーンショット 2019-07-07 10.07.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/eb743661-546f-4da3-3ad1-23cf7b835008.png">

* 一番下の **Register for a HERE account**  を押すとアカウント登録されます
* EMail欄で入力したメールアドレス宛てに、 HEREからVeritifactionメールが届くのでCOnfirm、
  * **Welcome to HERE** という件名でした

## どんなAPIがあるのか確認してみる

* HEREの[ドキュメント](https://developer.here.com/documentation)を確認する
* 大きく分けると以下の種類のAPIが紹介されています
  * MAPS - `Highly accurate maps, available worldwide`
  * SEARCH AND GEOCODING - `Use latitude and longitude to search for addresses and 
POIs`

  * ROUTING AND NAVIGATION - `From voice-guided pedestrian routing, to intermodal routing, to optimized truck routing`
  * FLEET TELEMATICS - `Advanced location algorithms for complex fleet management use cases`
  * MORE APIS AND SDKS - `More and more`

## 実際に使ってみる & 動かしてみる 
* APIたくさんありますね。
* まずは基本。ということで、一番基本に近そうな上から２つ↓↓を使ってみたいと思います
  * MAPS
      * タイバンコク付近のインタラクティブな地図を表示
  * SEARCH AND GEOCODING
      * タイバンコク近辺のランドマークを検索

**これらのサンプルコードをひらすら写経**

* [インタラクティブなマップを表示 - Map at a specified location](https://developer.here.com/api-explorer/maps-js)
* [地図にZoomコントロールを表示- Map Controls and UI](https://developer.here.com/documentation/maps/topics/map-controls.html)
* [ジオコーディングAPIでランドマーク検索 - Reverse Geocode landmark](https://developer.here.com/api-explorer/rest/geocoder/reverse-geocode-landmarks)
* [地図にマーカーを表示 - Marker on the Map](https://developer.here.com/api-explorer/maps-js/markers/markers-on-the-map)
* [マーカーをクリックして吹き出し表示 - Opening an Infobubble on a Mouse Click
](https://developer.here.com/api-explorer/maps-js/infobubbles/open-infobubble)

**苦節すること2時間**

* 無事入門できました！

<img width="1107" alt="スクリーンショット 2019-07-07 14.51.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/adf9f71b-7f0e-e0d5-c2b5-26c27d89a70f.png">

* 地図上には、目標物のアイコンを表示しています。クリックすると(タイ語で目標物のラベルが表示される)

<img width="688" alt="スクリーンショット 2019-07-07 15.29.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79576/e45ec806-303a-7146-41c9-9d818bee4811.png">

## まとめ

* 無料で使えて素晴らしいHERE API。
* 途中様々苦戦したですが、なんとか、使うことができました
  * INTERACTIVE MAPS - サンプルの通りにやったが地図が出ない
      * 翌日試したら表示されました！
  * SEARCH AND GEOCODING - バンコク中心で検索すると、目標物のラベルもタイ語
      * 現地語以外にも対応しているのか..

* 残りのAPIに HERE の 持ち味が隠されていそうなので、引き続き残りの部分も使ってみます！
  * ROUTING AND NAVIGATION 
  * FLEET TELEMATICS

## 補足 (ジオコーディング の REST APIを叩くところだけ、構造が複雑だったので、コードの断片を残します)

* SEARCH AND GEOCODING の `reverse-geocode-landmarks` の [サンプル](https://developer.here.com/api-explorer/rest/geocoder/reverse-geocode-landmarks)と合わせて参照

* reverse-geocode-landmarks を呼び出すコード
  * ElixirのHTTPoisonで実装しています-m

```elixir
envs = Application.get_env(:iam_here, IamHere.Endpoint)

# HERE の reverse geocoder REST APIにリクエストを送信
http_response = HTTPoison.get!(
  "https://reverse.geocoder.api.here.com/6.2/reversegeocode.json", 
  "?app_id=" <> envs[:here_api_app_id] <> 
  "&app_code=" <> envs[:here_api_app_code] <> 
  "&mode=retrieveLandmarks" <>
  "&prox=13.72564,100.54106,1000")

# HERE の reverse geocoder REST APIのレスポンスをデコード
response_json = case http_response do
  %HTTPoison.Response{body: body, status_code: 200} ->  body | HTTPoison.decode!
  %HTTPoison.Error{reason: reason} -> raise "Oops, #{reason}"
end

landmarks = response_json |> Map.fetch!("Response") |> Map.fetch!("View") |> Enum.at(0) |> Map.fetch!("Result")
```

* landmarksの中に、以下のような構造のデータ(Map型のリスト)が入った状態になるので、これを表示します

```
[
  {
  "Relevance": 1,
  "Distance": 55.9,
  "MatchLevel": "landmark",
  "MatchQuality": {
    "Country": 1,
    "County": 1,
    "City": 1,
    "District": 1,
    "Subdistrict": 1,
    "PostalCode": 1,
    "Name": 1
  },
  "Location": {
    "LocationId": "NT_EfXFH4vWxnBKXMwx7Ogo.D",
    "LocationType": "canalWaterChannel",
    "Name": "คลองสาทร",
    "DisplayPosition": {
      "Latitude": 13.72391,
      "Longitude": 100.53719
    },
    "MapView": {
      "TopLeft": {
        "Latitude": 13.72595,
        "Longitude": 100.53034
      },
      "BottomRight": {
        "Latitude": 13.72187,
        "Longitude": 100.54398
      }
    },
    "Address": {
      "Label": "ทุ่งมหาเมฆ, สาทร, กรุงเทพมหานคร 10120, ประเทศไทย",
      "Country": "THA",
      "County": "กรุงเทพมหานคร",
      "City": "กรุงเทพมหานคร",
      "District": "สาทร",
      "Subdistrict": "ทุ่งมหาเมฆ",
      "PostalCode": "10120",
      "AdditionalData": [
        {
          "value": "ประเทศไทย",
          "key": "CountryName"
        },
        {
          "value": "กรุงเทพมหานคร",
          "key": "CountyName"
        }
      ]
    },
    "MapReference": {
      "CountryId": "22888206",
      "CountyId": "22883206",
      "CityId": "22883206",
      "DistrictId": "22887252",
      "PlaceId": "1436108393"
    }
  }
}
]
```