memorandums

日々の生活で問題解決したこと、知ってよかったことなどを自分が思い出すために記録しています。

ChatGPTのおかげで前から欲しかったプログラム(GAS)ができた

前置き

Googleが恐れMSが投資するChatGPTですが個人的に活用するには至っていませんでした。

できるだけ使っていこうと思い、今朝から何か調べものをするときにChatGPTを使うようにしていました。

そんな状況の中、次の作業が発生しました。ちょっと長いですが。。。背景から說明していきます。

学生が提出した課題ファイルを研究データとして利用しているのですが(プログラミング学習過程の分析)、課題の提出先はGoogle Classroomにしています。

Google Classroomの提出ファイルはGoogle Driveの「Classroom」というフォルダ内にクラス(科目)ごとにフォルダが生成されて、その中に課題ごとのフォルダが生成されるようになっています。これはGoogle Classroomの仕様ですね。

このフォルダ内に受講生全員の課題ファイルが格納されているのですが、学生さんによっては提出期間内に何度も提出しなおす方がいまして、Google Driveの仕様で同一ファイル名であっても上書きされず別のファイルが生成される仕様になっています。

ややこしくなってきましたが。。。Google Classroomに提出されるファイルのGoogle Driveでのフォルダ構造は以下のような感じになります。

Google Drive ー Classroom ー クラス(科目) ー 課題 ー 全員の提出ファイル(docx、pdf、zip、7zなど)

ソースコードを解析するためには途中のファイルは不要で、学生ごとのファイルが得られれば良いのですが。。。そのファイルだけ選り分けることは少なくともGoogle DriveのUIだけではできないんですね。

これまではとりあえず課題フォルダごとダウンロードして中身をみて選別してきました。

やっと背景の話しが終わったのですが。。。お疲れ様でした。

で、最初に戻って、物は試しということでChatGPTに質問を投げてみたんですね。

ChatGPTとのインタラクション

最初が以下でした。Googleのキーワード検索のようにどう尋ねたらいいかまだ勘所がわかっていませんが。。。とりあえず思いつく質問文を投げてみました。するとかなり詳しいというか的を得た回答がありました。すげ。

本題とは関係ないのですが、グレードブックって聞き慣れなかったので聞いてみました。回答はありましたが、ちょっとよくわからなかったです💦

で、本題が以下です。最初の質問に対する2番目の回答が使えそうだったので尋ねてみると。。。なんとコードが示されたんですね。。。これは凄い。

function extractLatestSubmissions() {
  // Define the folder containing the submissions
  var folder = DriveApp.getFolderById("FOLDER_ID");
  // Get all the files in the folder
  var files = folder.getFiles();
  
  // Create an empty object to store file IDs and their corresponding modification dates
  var fileData = {};
  
  // Loop through the files in the folder
  while (files.hasNext()) {
    var file = files.next();
    var fileId = file.getId();
    var modificationTime = file.getLastUpdated();
    // Check if the file ID already exists in the fileData object
    if (fileData.hasOwnProperty(fileId)) {
      // If it does, check if the modification time is more recent
      if (modificationTime > fileData[fileId]) {
        // If it is, update the fileData object with the new modification time
        fileData[fileId] = modificationTime;
      }
    } else {
      // If the file ID does not exist in the fileData object, add it with the current modification time
      fileData[fileId] = modificationTime;
    }
  }
  
  // Get the IDs of the latest versions of the files
  var latestFileIds = Object.keys(fileData);
  
  // Create a new folder to store the latest versions of the files
  var latestFolder = DriveApp.createFolder("Latest Submissions");
  
  // Loop through the latest file IDs
  for (var i = 0; i < latestFileIds.length; i++) {
    var file = DriveApp.getFileById(latestFileIds[i]);
    // Move the file to the latest folder
    file.makeCopy(latestFolder);
  }
}

実際にGoogle Driveのトップにこのスクリプトを新規作成し、コード中のFOLDER_IDをClassroomの課題フォルダのIDに置き換えて実行すると。。。なんどエラーもなく動作しました!?

ただ、実際に動かしてみるとちょっとファイルが多いんです。調べてみると、同一学生が同じファイルを複数回提出した場合はGoogle Driveでいう版管理にはならず別ファイルになる(ファイルIDがそれぞれ異なる)ようでした。ChatGPTが示してくれたコードはあくまでファイルIDが同一のファイルで更新日付が最新のものを抽出するため、ファイルIDが異なると選別できないわけでした。

どういうコードになったか?

引き続きChatGPTに対してコードの改良方法を「同一ファイル名をコピー対象から除外するスクリプトは」などと問い合わせてみたのですが。。。うまくいきませんでした。なぜか示されたコードが途中で切れる。。。という状況で。

でも、ここまでヒントをもらったら十分です。あとはGASのコードを見ながらあれこれ考えてコードを改良して目的のコードが得られました。

変更点はキーがファイルIDではうまく行かないので、ファイルのオーナー(学生のメアド)+ファイル名をキーとして、同一のキーをもつファイルの最新版のみを取得するように変更しました。

Google Driveのドキュメントは以下です。例も書かれていますからファイルごとのメアドやファイル名のとり方もすぐにわかりました。

developers.google.com

以下が変更後のコードになります。

変更したのは「// -?-」のところだけです。ファイルIDをキーとしてその更新日付の新しいものを見つけていたのですが、一応、以下書いておきます。

// -1- ハッシュのキーを「fileId」から「ユーザID+ファイル名」に変更。 // -2- ファイルごとの最終更新日時の変数をfileDataからfileTimeに変更。 // -3- ファイルごとのfileIdをいれる入れ物を作成。 // -4- コピーに必要なfileIdはキーではなく値なのでObject.keysをObject.valuesに変更

30分くらいでしょうか。最初からGoogle検索だけだったらもっと時間がかかったでしょう。

いや。。。驚きです。

抱えている問題に対する情報を手早く入手するプラットフォームとしてChatGPTがいかに有用かわかりました。

どんどん使っていきたいですね。

というか、既に問題になっていると思いますが、これで学校の課題とかやる人も増えてくるでしょうから。。。ChatGPTを活用することを前提とした課題の出し方を考えていかないといけないですね。。。便利なものを使うな、というのはおかしいですから、使いこなして自分のものにしていく経験を積んでもらいたいと思います。

でわ。