見出し画像

専属秘書を作ろう! - #09 空いている時間を検索する

前回は、Googleカレンダーの予定を一覧で表示する機能を実現しました。
これで、チャットボットっぽくなってきましたよね☝️

今回は、機能を拡張し、空いている時間の検索をしてみましょう。

ただ空いている時間を教えてくれるだけだとカレンダーを一覧で見ればよいよね!ってなりかねないので、指定した時間分空いているところを検索するようにしましょう。

⬇️ 過去の note をまだご覧になっていない方はこちら ⬇️



機能を追加する前に

機能を追加する前に、まずスプレッドシートやリッチメニューの内容を変更していきましょう。

"#04 リッチメニューを作成する①" では、テキスト(コマンド) を送らせる機能に対応することをお話しました。

⬇️ #04 リッチメニューを作成する① はこちら ⬇️

"#08 指定した日付の予定を確認する" では、日付指定用のダイアログを出してユーザーに日付指定してもらう機能に対応しました。

⬇️ #08 指定した日付の予定を確認する はこちら ⬇️

今回追加したい機能は「指定した日付の指定した空き時間の検索」なので、"日付と必要な空き時間を指定してもらいたい" ですよね。

そのため、前回の予定確認の時の "日付" に加えて、"時間" も必要になります。

予定の確認では "日時選択アクション" というものを使用して、やりたいことを実現しましたが、今回はどうしましょう💦

何度かメッセージをやりとりしても良いのですが、やはり指定するフォーマットの問題が出てきますので、少々やっかいです。

そこで、同じ "日時選択アクション" の "日時選択" を使用することにしましょう。

前回との違いは…、

【予定確認】
・日付選択 ⇒ 日付選択ダイアログ
【空き時間検索】
・日時選択 ⇒ 日付選択ダイアログ+時間選択ダイアログ

このように、"日付選択" の場合は、そのまま「送信」となりますが、"日時選択" の場合は、「次へ」と変わり、次のウィンドウで "時間" を指定します。

本来の使い方としては、"何時何分" と時刻を指定するのですが、今回はこれを流用して "何時間何分" と確保する時間を指定することにします。

つまり、"1:30" を選択すると、1時30分 ではなく、「1時間30分の空き時間」を指定したとして認識します。

日時指定アクションの使い方については以下をご参照ください。

⬇️ 日時指定アクションの詳細はこちら ⬇️

このようにすることで、時間についても日付と同様に様々な入力パターンに対応する必要がなくなるので、実装が簡単になります。

これを前提として、さっそく作っていきましょう☝️

スプレッドシートを変更する

機能(D列)に日付選択アクションを追加

前回作成した "日付選択" の下に、"日時選択" を追加しました。

プログラムに日時選択アクション対応を追加

機能によって設定項目を切り替えている箇所に "日付選択アクション" を追加します。

action = {
  "type": "datetimepicker",
  "label": allValues[i+j][RICHMENU_MESSAGE],
  "data": allValues[i+j][RICHMENU_MESSAGE],
  "mode": "datetime"
};

"日付選択" の場合は、mode=date でしたが、
今回は "日時選択" になりますので、mode=datetime になります。

他は全く変わりませんので、簡単ですね👍

これでボタンを押すと、日時選択ダイアログが表示されるようになります。

ボタンを押下した時に LINE から受信したデータを見てみると、

params に datetime データが入っていて、日付(2024-01-11)+時間(T03:02)が送られてきています。

予定確認の時の params には date データが入っていて、日付(2024-01-08)しか送られていません。

これでバッチリですね✨

datetime = 2024-01-11T03:02 を受信した場合、

・2024年1月11日 の予定
・3時間2分 の空き時間

という形で検索できます。

ただし、分刻みでの検索はあまり意味を成しませんので、プログラム上は "15分単位" での検索とすることにします。

※Googleカレンダーの基本設定が 15分刻みのため、それに合わせるようにしました。(キーボード入力すれば1分単位でも可能ですが…)

正式な設定内容に変更する

実際に使用できるように正しい内容に変更しましょう。

リッチメニュー画像の変更

リッチメニューA の画像内容を以下に変更します。

・リッチメニューA
 ・FUNC2 ⇒ 空き時間を捜す(アイコンも適切なものに)

前回とアイコン変わってるや~ん!とお気づきの方…、
そんなにいないとは思いますが😅、統一感のあるアイコンが入手できず自作したので変わっています。

ご容赦ください💦

※Mr.Green は、画像処理デバイス用の開発環境を作っていたので、フォトショ(Photoshop) も イラレ(Illustrator) も プレミアプロ(PremierePro) も AE(AfterEffects) も使いこなすよ💪

スプレッドシートの設定内容の変更

スプレッドシートの内容を以下のように変更します。

・リッチメニューA
 ・画像リンクの変更 ⇒ 新たに作成した画像A の URL
 ・FUNC2
  ・【機能】メッセージ ⇒ 【機能】日時選択
  ・【メッセージ】FunctionA-2 ⇒ 【メッセージ】空き時間検索

すでにプログラムは作成していますので、内容を変更してメニューから設定すれば LINE に反映されます。

"1月11日、1時間30分" を指定して送付したところ、

・data=空き時間検索
・params.datetime=2024-01-11T01:30

上記のデータを受信していますので、問題無く設定されていますね👍

受信データに対応する

それでは、実際に受信したデータに対応していきましょう。

日付選択アクションによって返ってくるデータは、以下となります。

// 日時選択アクションのポストバックイベントの場合
{
  "destination": "U7b74f9ba63d6d056e55577a2fxxxxx",
  "events": [{
    "replyToken": "b60d432864f44d079f6d8efe86cf404b",
    "type": "postback",
    "mode": "active",
    "source": {
      "userId": "Udfcd513ce7719a39fb2fd20523a8xxxx",
      "type": "user"
    },
    "timestamp": 1704721853752,
    "webhookEventId": "01HKMNEBSF0NDAAGTA6QXVZWCP",
    "deliveryContext": {
      "isRedelivery": false
    },
    "postback": {
      "data": "空き時間検索",
      "params": {
        "datetime": "2024-01-11T01:30"
      }
    }
  }]
}

今回の機能では、

・events[0].type : postback
・events[0].postback.data : 空き時間検索
・events[0].postback.params.date : 選択した日時
  (yyyy-MM-ddTHH:mm の形式)

が必要なデータとなります。

前回作成した analyzeMessage()関数に case SCHEDULE_SEARCH_FREETIME を追加しました。

function analyzeMessage(message)
{
  const data = JSON.parse(message);
  const ev = data.events[0];

  switch(ev.type)
  {
    case EVTYPE_POSTBACK:
      switch(ev.postback.data)
      {
        case SCHEDULE_CHECK:
          replySchedule(ev.replyToken,ev.postback.params.date);
          break;
        case SCHEDULE_SEARCH_FREETIME:
          searchFreetime(ev.replyToken,ev.postback.params.datetime);
          break;
      }
      break;
  }
}

タイプが "postback" で、かつ "空き時間検索" を受信した場合に searchFreetime() をコールして、空き時間を検索して返します。

searchFreetime() の内容は結構複雑ですので、ファイルを入手してからご確認ください💦

これで一通り、完成しました。

空き時間検索アルゴリズム

searchFreetime()関数自体は複雑ですので、説明を割愛させて頂きましたが、空き時間検索アルゴリズムは少しご説明しておこうと思います。

今回は、指定した複数のカレンダーの予定から空き時間を検索する必要がありますので、まずは予定を統合しなければなりません。

そこで、「1bit 15分(最小単位) として定義してビットデータとして登録し、ビット演算(OR)する」という手法をとりました。

以下のような予定があったとします。
※説明のために、短時間内に多くの予定を詰め込みました💦

これだと、パッと見、どの時間が空いているのかわかりませんよね…。

まずは、これらのすべての予定を "15分単位のビットデータとして変換" します。

変換したデータが以下です。

"0" が予定なし、"1" が予定あり、です。

例えば、カレンダー①-予定① の場合は、15分単位ですので、01時30分~02時30分までの 4bit 分 "1" になります。

同様にすべてのデータを変換します。

その後、すべてのデータを OR (ビット論理和) します。

この処理の意味は、「1つでも予定が入っていたら、それは空き時間ではないので、すべて "1" になるよ」ということです。

その結果、"0" になっているところが、フリータイム~🎉となります😁
※赤枠の部分が該当します。

このようにして空き時間を検索し、さらに指定した時間分空いている箇所を検索し回答するようにしています。

動作確認

一番左が「Googleカレンダーの予定」です。
※わかりやすいように、空き時間を追記しています。

また、真ん中に "1時間" "1時間30分" "2時間30分" 以上空いている時間帯に✅をいれた表を作成しました。
※✅がついているところが指定時間分空いている時間帯です。

一番右が、専属秘書みどりこちゃんが回答した結果です。

これを比較してみると、正しく回答してくれているようですね👍
バッチリです😁

実際の LINE の画面はこちら。

まとめ

今回は、指定した日付の空き時間を検索するアクションを追加しました。

いかがでしたでしょうか。

予定が詰まってくると、カレンダーで見てもどこに予定が入れられるか、どこだったら自分のことが出来るか、など一瞬では判断できないことがありますよね。

そんな時に時間を指定して探してくれたら便利です。

このようにどんどん機能を追加して "みどりこちゃん" に仕事してもらいましょう👍

最後に、動きも見たい!というお声もあると思いましたので、動画も置いておきます。
ぜひご覧ください。

もしわからないことがありましたら、お気軽に LINE公式アカウント でご質問ください。

何でも答えるよ~

今回のご提供ファイルのキーワードは【専属秘書みどりこV6】です。

LINE公式アカウントにご登録の上、キーワードを送信してくださいね。

⬇️LINE公式アカウントに登録してご連絡ください⬇️

ビジネスが加速するよ~

もし「サポートしたい!」という方がいらっしゃいましたら、ぜひぜひサポートをお願いいたします! 開発費や外注費などクリエイター活動の一部として使用させて頂きます✨