最高の勉強法をGASとLINEで作ってみた

# 動機
最近資格や検定を取りたいと思い、勉強を始めた。が、頭に全然入ってこないのと自分の傾向として長期的に覚えていることが少ないように思えた。そこで「科学的根拠に基づく最高の勉強法」という本を手に取り読んだ結果試してみたいと思った反面、自分なりに効率よく続けるにはどうしたらいいか考えた結果、GASとLINE、Googleのスプレッドシートを使って、始められるんじゃないかと思いやってみることにした。
[科学的根拠に基づく最高の勉強法](https://amzn.asia/78qTto1)

# やりたいこと
- 当書で紹介されている以下の4つの観点に基づく方法をもとに再現を行う
    - この記事では本書の内容に関しては特に触れず、用語だけ用いていく（気になる方はぜひ読んでみてください！）
    - アクティブリコール
    - 分散的学習
    - 精緻的質問と自己説明
    - インターリービング
- 以下の点をLINEから行えるようにしたい
    - 問題作成
    - 出題
    - 答え合わせ
    - 自分の中における理解度のスコア記録
- スプレッドシートで問題やスコアの記録・管理をしたい
    - 記録したいこと
        - 出題文
        - 模範回答
        - スコア
        - 分野
- LINEとスプレッドシートをつなげる役割としてGASを用いる

# 学習の流れ(全体像)
### 自分で学びたい内容を勉強する
- インプットする際に「なぜ」「どうして」と確認しながら学習していく
- 一気に勉強するのではなく、章ごとに勉強する
    - 問題を作成するため
    - ひたすら似たような内容が続くようであれば、章を変えてみる(インターリービング)
### 勉強した内容から振り返り、「ここ理解できてるか」と確認するように問題を作成・記録する(精緻的質問と自己説明)
- 学習した章において出てきた単語や概念に対して「〇〇は何ですか？」「〇〇はどういうことですか？」というように質問・問題を考える
### 問題を解く(アクティブリコール)
- 何もみることなく、記憶の中から情報を取り出す
- 回答を単語とかではなく、説明する形など記述で答えるようにする
- 複数の単元に跨った問題をとく(インターリービング)
### 解いた問題を答え合わせを行い、採点・自己評価し、記録する(精緻的質問と自己説明)
- すぐに答えが出たり、迷わずに答えれたりして、間違えてなかったら100点

# 作成手順
### スプレッドシートを作成
はじめに、問題文や模範回答、スコア、カテゴリーを蓄積・管理するためのスプレッドシートを用意する。
今回必要な要素は上記の4つに日付を加えた5つのため、以下のようにシートを作成する

![スクリーンショット 2024-09-29 17.12.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1906633/9fb376ec-b69c-8970-68d4-e8f665cd2c57.png)

### LINEチャネルの作成
以下のサイトの「作成したチャネルをLINEに追加」という章まで行ってください！
[LINE Messaging API×GASで家計簿管理用のLINE botを作成する：LINEとGASの連携まで](https://prtn-life.com/blog/gas-linebot)

### チャネルアクセストークンの設定
チャネルを作成したら、長期のチャネルアクセストークンを取得し、GASの上の方で設定している該当部分に貼ってください！
- チャネルアクセストークンの取得方法
    - [LINE Developersコンソール](https://developers.line.biz/console/)にアクセス
    - 遷移先で該当のチャネルを選択
    - 「Messaging API設定」のタブを選択
    - ページ下の方にあるチャネルアクセストークンから取得する

### 問題を記録するためのスクリプトの作成・デプロイ
今回LINEからスプレッドシートに問題やスコアを記録したり、問題を出題してもらったりするが、ここでは問題を記録するためのスクリプトを作成してくれるので実際に書いていく。

- GAS(Google Apps Script)を作成
先ほど作成したスプレッドシートの「拡張機能」タブの中にある「Apps Script」を選択する。するとGASを書くためのファイルを作成してくれる。

<details><summary>今回作成したスクリプト</summary>

```JavaScript
// LINE developerで登録したチャネルアクセストークン
var ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
// LINEへ応答メッセージを送るAPI
var LINE_ENDPOINT = "https://api.line.me/v2/bot/message/reply";
// GoogleスプレッドシートのID
var SHEET_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

/*
  LINEからPOSTリクエストが渡されてきたときに実行される処理
*/
function doPost(e) {

  // LINEからPOSTされるJSON形式のデータをGASで扱える形式(JSオブジェクト)に変換
  var json = JSON.parse(e.postData.contents);

  // LINE側へ応答するためのトークンを作成(LINEからのリクエストに入っているので、それを取得する)
  var reply_token= json.events[0].replyToken;
  if (typeof reply_token === 'undefined') {
    return;
  }

  // LINEから送られてきたメッセージを取得
  var user_message = json.events[0].message.text;
  // 改行で区切って配列にする
  var user_msgarray = user_message.split(/\r\n|\n/);

  // 応答メッセージ本文
  var resultMsg = "";

  // スプレッドシートへの書き込み
  resultMsg = registQustion(user_msgarray);
  
  // 応答用のメッセージを作成
  var message = {
                  "replyToken"  : reply_token,
                  "messages"    : [{"type": "text",      // メッセージのタイプ(画像、テキストなど)
                                    "text" : resultMsg}] // メッセージの内容
                };

  // LINE側へデータを返す際に必要となる情報
  var options = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json; charset=UTF-8",  // JSON形式を指定、LINEの文字コードはUTF-8
      "Authorization" : "Bearer " + ACCESS_TOKEN           // 認証タイプはBearer(トークン利用)、アクセストークン
    },
    "payload" : JSON.stringify(message)                    // 応答文のメッセージをJSON形式に変換する
  };

  // LINEへ応答メッセージを返す
  UrlFetchApp.fetch(LINE_ENDPOINT, options);
}


/*
  問題文・模範回答・カテゴリーをスプレッドシートに書き込む
*/
function registQustion(user_msgarray){

  var msg = "";

  // 対象のスプレッドシートを取得
  var spreadSheet = SpreadsheetApp.openById(SHEET_ID);

  // 本日の日付を取得
  var today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');

  // 書き込む対象のシートを取得
  var sheetName = '問題';
  var targetSheet = spreadSheet.getSheetByName(sheetName);

  if (targetSheet != null){

    // 最終行を取得
    var lastRow = targetSheet.getLastRow();
    var targetRow = lastRow + 1;

    // 書き込み
    targetSheet.getRange(targetRow, 1).setValue(today);  // 日付
    targetSheet.getRange(targetRow, 2).setValue(user_msgarray[0]);  // 問題文
    targetSheet.getRange(targetRow, 3).setValue(user_msgarray[1]);  // 模範回答
    targetSheet.getRange(targetRow, 5).setValue(user_msgarray[2]);  // カテゴリー
    msg = "書き込み完了";
  }
  else{
    // 対象のシートが見つからない場合
    msg = "シート名：" + sheetName + "\nが見つかりません";
  }
  return msg;
}
```
</details>

- デプロイ
    - GASの右上メニューから「新しいデプロイ」
    - 種類は「ウェブアプリ」を選択
    - 次のユーザーとして実行を「自分」、アクセスできるユーザーを「全員」にしてデプロイを押下
        - 「アクセスを承認」を出た場合には、「承認」を押下して進める(自己判断で)
        - 「Go to 無題のプロジェクト(unsafe)」を押下する
    - デプロイが完了したら、ウェブアプリのURLをコピーする
        - このページを閉じずに置いておくと後々助かるかも！

### LINE DevelopersにGASのURLを設定
先ほどデプロイしたウェブアプリのURLをLINE Developersに設定する。
- [LINE Developersコンソール](https://developers.line.biz/console/)にアクセス
- 遷移先で該当のチャネルを選択
- 「Messaging API設定」のタブを選択
- Webhook URL欄に先ほどコピーしたURLを貼る
- 「検証」をクリック
- 「成功」と出てきたら問題ないです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1906633/8cd22378-3f97-98f7-9a47-c7476551f3d5.png)

### LINEでメッセージを送ってみる
ここまで設定できたら設定は完了してます！
試しにLINEからメッセージを送信して確認してみましょう！

- 1行目：テスト
- 2行目：てすと
- 3行目：test

書き込み完了と帰ってくれば終了です！
スプレッドシートも一緒に確認してみると送信した内容が書き込まれているのがわかります！

![スクリーンショット 2024-09-29 18.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1906633/3ebc00da-6c46-2a78-fa3a-5526e70a8e55.png)

# やってみて
この記事をまとめることも含め、約3時間ほどでここまでできた。ただ当初やりたかったスコアを記録することや問題を出題させるところまでできていないので、まだ別の記事とかで書いていければと思う。

# 参考サイト
- [科学的根拠に基づく最高の勉強法](https://amzn.asia/78qTto1)
- [LINE Messaging API×GASで家計簿管理用のLINE botを作成する：スプレッドシートへの書き込み](https://prtn-life.com/blog/gas-linebot-regist-spreadsheet#toc5)
- [LINE Messaging API×GASで家計簿管理用のLINE botを作成する：LINEとGASの連携まで](https://prtn-life.com/blog/gas-linebot)