LoginSignup
36
13

More than 3 years have passed since last update.

世界初!異色のコラボ!「ラブライブ!」と「ワイルド・スピード」の聖地を教えてくれるLINEbot!

Last updated at Posted at 2020-08-26

「ラブライブ!」大好き!「ワイルド・スピード」も大好き!
そんな欲張りさん向けにLINEbotを作りました。よかったら最後までご覧ください♪

作品の背景

聖地巡礼が好きな私。ロサンゼルスにワイスピの聖地巡礼に行きたいと考えているものの、コロナで旅行も行けず・・・。

「ワイルド・スピード」シリーズは、スピンオフも含めて、これまでに9作品上映されているのですが、
3作目となる「ワイルド・スピードX3 TOKYO DRIFT」は、なんと東京が舞台!

東京なら巡礼できる!と思い、ワイスピ聖地巡礼bot東京版を作ることにしました!!

ところがどっこい!!
意気揚々と調べたものの、CGで作られていたり、すでに取り壊されていたりと、聖地情報が希薄・・・。泣

これではbotとして成り立たないので、大好きな「ラブライブ!」と組み合わせ、世界初のコラボレーションを実現しました。

デモ動画

完成したものがコチラです!
位置情報を送ると、最寄りの聖地を教えてくれます。

ワイスピの聖地は本当少ないので、隠しコマンドみたいになってます。笑

作る時のポイント

LINEbotの作り方

いつもこちらの記事を参考にさせていただいております!
1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest

2点間の距離の測り方

こちらが1番苦戦しました。。。
何から手をつけていいのかわからずで、Qiitaにも質問記事を投稿しました。

▶投稿した質問:LINEbotで現在地情報を送ったら、近くのスポットを返すコードを書きたい【Javascript/Node.js】

すると、@uasi さんがとても親切に教えていただき、すぐに解決することができました。
本当にありがとうございます。

Qiitaの回し者ではないですが、質問投稿するの本当勉強になります。
初心者エンジニアの方にオススメです。

できたコードがこちら。

// 角度をラジアンに変換
function toRad(deg) {
    return deg / 180 * Math.PI;
  }

  // 2点間の大円距離を計算(返り値は km 単位)
  // 参考: http://www.orsj.or.jp/archive2/or60-12/or60_12_701.pdf
  function distance(lat1, lon1, lat2, lon2) {
    lat1 = toRad(lat1);
    lon1 = toRad(lon1);
    lat2 = toRad(lat2);
    lon2 = toRad(lon2);

    return 6370 * Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
  }

  // 与えた緯度経度の地点からもっとも近い場所を返す
  function getNearestLocation(lat, lon) {
    // dataWithDistance は [ [場所1, 指定地点と場所1の距離], [場所2, 指定地点と場所2の距離], ... ]
    let dataWithDistance = data.map(item => [item, distance(lat, lon, item.lat, item.lon)]);

    // 距離がもっとも近い場所を取り出す
    // reduce() の解説: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
    return dataWithDistance.reduce((nearest, current) => current[1] < nearest[1] ? current : nearest)[0] || null;
  }

これで最寄りのスポットを抽出することができるようになりました。

▶参考記事:【LINE BOT】位置情報と目的地の距離を発信

メッセージの見やすさ

抽出した最寄りスポットを見やすくするために、
説明文・画像・地図をメッセージとして返せるようにしました。

Image from Gyazo

違うメッセージタイプのものを一緒に送る方法が最初わからなかったのですが、
シンプルに[]でまとめれば上手く行きました♪

async function handleEvent(event) {
  // 位置情報のみに入力制限
  if (event.type !== 'message' || event.message.type !== 'location') {
    return Promise.resolve(null);
  }
  // 取得した位置情報をログに表示
  console.log(event.message.latitude + ' : ' + event.message.longitude);

  const nearestLocation = getNearestLocation(event.message.latitude, event.message.longitude);

  console.log(nearestLocation);

  return client.replyMessage(event.replyToken,[
    {
      type: 'text',
      text: '【作品】' + nearestLocation.category + '' +nearestLocation.memo,
    }, 
    {
      type:'image',
      originalContentUrl:nearestLocation.image,
      previewImageUrl:nearestLocation.image,
    },
    {
      type: 'location',
      title: nearestLocation.spot,
      address:nearestLocation.address,
      latitude: nearestLocation.lat,
      longitude: nearestLocation.lon,
    }
  ]);
}

改善点

▶最寄りだけじゃなくて、半径●キロ以内とかにある全スポットを出せるといいな!
▶位置情報だけじゃなくて、キーワード検索もできるようにしたい
▶もっと自力で検索して実装できるようにしたい!

今回も皆さまのおかげで最低限の形にはなりましたが、まだまだスキルが足りないので精進したいです・・・!

おわりに

まだ未完成な部分があるので、完成したらデプロイして、ソースコードとQRコードも載せる予定・・・!
聖地ではなく、好きなお店とかにアレンジして作るとより実用性高いものになると思うので、
ぜひ皆さんも作ってみてください~♪

(*^^)v「よろしければLGTMも宜しくお願いします!」

36
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
13