ルーブリックを使ってみる

rubric は、教師が生徒の採点を行う際に使用できるテンプレートです。 提出します。Classroom API を使用すると、Google Classroom の 教師がルーブリックを管理します。

Classroom UI でのルーブリックの表示 図 1. Classroom の課題のサンプル ルーブリック。

このガイドでは、ルーブリック API の基本概念と機能について説明します。詳しくは、 これらについて詳しくは、 ルーブリックの構成と 採点は Classroom UI で行います。

前提条件

このガイドは、次のものがあることを前提としています。

デスクトップ アプリケーションの認証情報を承認する

エンドユーザーとして認証を行い、アプリ内でユーザーデータにアクセスするには、1 つ以上の OAuth 2.0 クライアント ID を作成する必要があります。クライアント ID は Google の OAuth サーバーに送信します。アプリが複数のプラットフォームで動作する場合 プラットフォームごとに個別のクライアント ID を作成する必要があります。

  1. Google Cloud の [認証情報] ページ( Google Cloud コンソール。
  2. [認証情報を作成] をクリックします。OAuth クライアント ID
  3. [アプリケーションの種類] >デスクトップ アプリ
  4. [名前] フィールドに、認証情報の名前を入力します。この名前は 表示されます。例: 「ルーブリック プレビュー クライアント」。
  5. [作成] をクリックします。[OAuth クライアントの作成] 画面が表示され、新しい クライアント ID とクライアント シークレット。
  6. [JSON をダウンロード] をクリックし、[OK] をクリックします。新しく作成された認証情報 [OAuth 2.0 クライアント ID] に表示されます。
  7. ダウンロードした JSON ファイルを credentials.json として保存し、ファイルを次の場所に移動します。 作業ディレクトリに移ります。
  8. [認証情報を作成] をクリックします。API キー] に移動し、API キーをメモしておきます。

詳細については、アクセス認証情報を作成するをご覧ください。

OAuth スコープを構成する

プロジェクトの既存の OAuth スコープによっては、 あります。

  1. OAuth 同意画面に移動します。
  2. [アプリを編集] をクリックします。[Save and Continue] をクリックして [Scopes] 画面に移動します。
  3. [スコープを追加または削除] をクリックします。
  4. 次のスコープを追加します(まだ追加していない場合)。 <ph type="x-smartling-placeholder">
      </ph>
    • https://www.googleapis.com/auth/classroom.coursework.students
    • https://www.googleapis.com/auth/classroom.courses
  5. 次に、[更新] をクリック >保存して次へ >保存して次へ > ダッシュボードに戻る

詳しくは、OAuth 同意画面を構成するをご覧ください。 できます。

classroom.coursework.students スコープは、以下に対する読み取りと書き込みのアクセスを可能にします。 ルーブリック(CourseWork へのアクセスを含む)、classroom.courses のスコープ 読み書きのコースを使用できます。

特定のメソッドに必要なスコープは、リファレンス ドキュメントに記載されています。 メソッドの引数。courses.courseWork.rubrics.create 認可スコープをご覧ください。 できます。Classroom のスコープについては、Google 向け OAuth 2.0 スコープ、 API。API はまだプレビュー版のため、ここではルーブリックについては触れません。

サンプルを構成する

作業ディレクトリに Python 用の Google クライアント ライブラリをインストールします。

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

クライアント ライブラリをビルドして承認する main.py というファイルを作成します。 YOUR_API_KEY の代わりに API キーを使用します。

import json
import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/classroom.courses',
          'https://www.googleapis.com/auth/classroom.coursework.students']

def build_authenticated_service(api_key):
    """Builds the Classroom service."""
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run.
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        # Build the Classroom service.
        service = build(
            serviceName="classroom",
            version="v1",
            credentials=creds,
            discoveryServiceUrl=f"https://classroom.googleapis.com/$discovery/rest?labels=DEVELOPER_PREVIEW&key={api_key}")

        return service

    except HttpError as error:
        print('An error occurred: %s' % error)

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

python main.py を使用してスクリプトを実行します。ログインと有効化を求めるメッセージが表示されます 同意します。

課題を作成

ルーブリックは課題または CourseWork に関連付けられており、 その CourseWork のコンテキストで意味のあるものになります。ルーブリックを作成できるのは 親 CourseWork アイテムを作成した Google Cloud プロジェクト。目的 スクリプトを使用して新しい CourseWork 割り当てを作成します。

main.py に以下を追加します。

def get_latest_course(service):
    """Retrieves the last created course."""
    try:
        response = service.courses().list(pageSize=1).execute()
        courses = response.get("courses", [])
        if not courses:
            print("No courses found. Did you remember to create one in the UI?")
            return
        course = courses[0]
        return course

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

def create_coursework(service, course_id):
    """Creates and returns a sample coursework."""
    try:
        coursework = {
            "title": "Romeo and Juliet analysis.",
            "description": """Write a paper arguing that Romeo and Juliet were
                                time travelers from the future.""",
            "workType": "ASSIGNMENT",
            "state": "PUBLISHED",
        }
        coursework = service.courses().courseWork().create(
            courseId=course_id, body=coursework).execute()
        return coursework

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

次に、main.py を更新して、先ほどのテストクラスの course_id を取得します。 新しい課題の作成、新しい課題のサンプルの作成、課題の coursework_id:

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

    course = get_latest_course(service)
    course_id = course.get("id")
    course_name = course.get("name")
    print(f"'{course_name}' course ID: {course_id}")

    coursework = create_coursework(service, course_id)
    coursework_id = coursework.get("id")
    print(f"Assignment created with ID {coursework_id}")

    #TODO(developer): Save the printed course and coursework IDs.

course_idcoursework_id を保存します。これらはすべてのルーブリックの CRUD に必要です 必要があります。

これで、Classroom に CourseWork のサンプルが準備できました。

Classroom の UI に表示された課題 図 2. Classroom の課題のサンプルの表示。

ルーブリックを作成する

これで、ルーブリックの管理を開始する準備が整いました。

CourseWork でルーブリックを作成するには、Create 呼び出しに 完全なルーブリック オブジェクト。条件とレベルの ID プロパティは省略 (これらは作成時に生成されます)。

main.py に次の関数を追加します。

def create_rubric(service, course_id, coursework_id):
    """Creates an example rubric on a coursework."""
    try:
        body = {
            "criteria": [
                {
                    "title": "Argument",
                    "description": "How well structured your argument is.",
                    "levels": [
                        {"title": "Convincing",
                         "description": "A compelling case is made.", "points": 30},
                        {"title": "Passable",
                         "description": "Missing some evidence.", "points": 20},
                        {"title": "Needs Work",
                         "description": "Not enough strong evidence..", "points": 0},
                    ]
                },
                {
                    "title": "Spelling",
                    "description": "How well you spelled all the words.",
                    "levels": [
                        {"title": "Perfect",
                         "description": "No mistakes.", "points": 20},
                        {"title": "Great",
                         "description": "A mistake or two.", "points": 15},
                        {"title": "Needs Work",
                         "description": "Many mistakes.", "points": 5},
                    ]
                },
                {
                    "title": "Grammar",
                    "description": "How grammatically correct your sentences are.",
                    "levels": [
                        {"title": "Perfect",
                         "description": "No mistakes.", "points": 20},
                        {"title": "Great",
                         "description": "A mistake or two.", "points": 15},
                        {"title": "Needs Work",
                         "description": "Many mistakes.", "points": 5},
                    ]
                },
            ]
        }

        rubric = service.courses().courseWork().rubrics().create(
            courseId=course_id, courseWorkId=coursework_id, body=body,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
            ).execute()
        print(f"Rubric created with ID {rubric.get('id')}")
        return rubric

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

次に、main.py を更新して実行し、Course を使用してサンプル ルーブリックを作成します。 と、先ほどの CourseWork ID は次のとおりです。

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

    rubric = create_rubric(service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID)
    print(json.dumps(rubric, indent=4))

ルーブリック表現に関する注意点:

  • 条件とレベルの順序が Classroom の UI に反映されている。
  • スコア付きのレベル(points プロパティを持つレベル)はポイントで並べ替える必要があります 昇順か降順のいずれかになります(ランダムに並べ替えることはできません)。
  • 教師は、基準とスコア付けされたレベルを並べ替えることができる(ただし、スコアリングされないレベルに並べ替えられない) 含まれており、データ内の順序が変わります。

ルーブリックの構造に関する注意事項については、制限事項をご覧ください。

UI に戻ると、課題のルーブリックが表示されます。

Classroom UI でのルーブリックの表示 図 3. Classroom の課題のサンプル ルーブリック。

ルーブリックを読む

ルーブリックは、標準の List メソッドと Get メソッドを使用して読み取ることができます。

1 つの課題に含めることのできるルーブリックは 1 つまでであるため、「List」は 直感的ではありませんが、ルーブリック ID がないと便利です。もし に CourseWork に関連付けられたルーブリックがない場合、List の回答は空です。

main.py に次の関数を追加します。

def get_rubric(service, course_id, coursework_id):
    """
    Get the rubric on a coursework. There can only be at most one.
    Returns null if there is no rubric.
    """
    try:
        response = service.courses().courseWork().rubrics().list(
            courseId=course_id, courseWorkId=coursework_id,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
            ).execute()

        rubrics = response.get("rubrics", [])
        if not rubrics:
            print("No rubric found for this assignment.")
            return
        rubric = rubrics[0]
        return rubric

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

main.py を更新して実行し、追加したルーブリックを取得します。

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

    rubric = get_rubric(service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID)
    print(json.dumps(rubric, indent=4))

    #TODO(developer): Save the printed rubric ID.

ルーブリックの id プロパティは、後の手順で使用するためメモしておきます。

Get は、ルーブリック ID があれば適切に機能します。関数での Get の使用 次のようになります。

def get_rubric(service, course_id, coursework_id, rubric_id):
    """
    Get the rubric on a coursework. There can only be at most one.
    Returns a 404 if there is no rubric.
    """
    try:
        rubric = service.courses().courseWork().rubrics().get(
            courseId=course_id,
            courseWorkId=coursework_id,
            id=rubric_id,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
        ).execute()

        return rubric

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

この実装では、ルーブリックがない場合に 404 が返されます。

ルーブリックを更新する

ルーブリックを更新するには、Patch の呼び出しを使用します。構造が複雑であるため 更新は「読み取り - 変更 - 書き込み」のパターンで行う必要があります。 criteria プロパティ全体が置き換えられます。

更新ルールは次のとおりです。

  1. ID なしで追加された条件またはレベルが考慮されます 追加機能
  2. これまでに不足している基準またはレベルが考慮されます 削除
  3. 既存の ID であってもデータは変更されている条件またはレベルは考慮されます 編集。変更されていないプロパティはそのまま残ります。
  4. 新しい ID または不明な ID で指定された条件やレベルは考慮されます エラーです。
  5. 新しい条件とレベルの順序は、新しい UI の順序とみなされます。 (前述の制限事項があります)。

ルーブリックを更新する関数を追加します。

def update_rubric(service, course_id, coursework_id, rubric_id, body):
    """
    Updates the rubric on a coursework.
    """
    try:
        rubric = service.courses().courseWork().rubrics().patch(
            courseId=course_id,
            courseWorkId=coursework_id,
            id=rubric_id,
            body=body,
            updateMask='criteria',
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
        ).execute()

        return rubric

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

この例では、criteria フィールドの変更に指定されており、 updateMask

次に、main.py を変更して、前述の更新ごとに変更を行います。 ルール:

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

    # Get the latest rubric.
    rubric = get_rubric(service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID)
    criteria = rubric.get("criteria")
    """
    The "criteria" property should look like this:
    [
        {
            "id": "NkEyMdMyMzM2Nxkw",
            "title": "Argument",
            "description": "How well structured your argument is.",
            "levels": [
                {
                    "id": "NkEyMdMyMzM2Nxkx",
                    "title": "Convincing",
                    "description": "A compelling case is made.",
                    "points": 30
                },
                {
                    "id": "NkEyMdMyMzM2Nxky",
                    "title": "Passable",
                    "description": "Missing some evidence.",
                    "points": 20
                },
                {
                    "id": "NkEyMdMyMzM2Nxkz",
                    "title": "Needs Work",
                    "description": "Not enough strong evidence..",
                    "points": 0
                }
            ]
        },
        {
            "id": "NkEyMdMyMzM2Nxk0",
            "title": "Spelling",
            "description": "How well you spelled all the words.",
            "levels": [...]
        },
        {
            "id": "NkEyMdMyMzM2Nxk4",
            "title": "Grammar",
            "description": "How grammatically correct your sentences are.",
            "levels": [...]
        }
    ]
    """

    # Make edits. This example will make one of each type of change.

    # Add a new level to the first criteria. Levels must remain sorted by
    # points.
    new_level = {
        "title": "Profound",
        "description": "Truly unique insight.",
        "points": 50
    }
    criteria[0]["levels"].insert(0, new_level)

    # Remove the last criteria.
    del criteria[-1]

    # Update the criteria titles with numeric prefixes.
    for index, criterion in enumerate(criteria):
        criterion["title"] = f"{index}: {criterion['title']}"

    # Resort the levels from descending to ascending points.
    for criterion in criteria:
        criterion["levels"].sort(key=lambda level: level["points"])

    # Update the rubric with a patch call.
    new_rubric = update_rubric(
        service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID, YOUR_RUBRIC_ID, rubric)

    print(json.dumps(new_rubric, indent=4))

これで、変更内容が Classroom の教師に反映されます。

Classroom の UI に表示された更新されたルーブリックを表示 図 4. 更新されたルーブリックの表示。

ルーブリックで採点された提出物を表示する

現在のところ、生徒の提出物を API でルーブリックを使って採点することはできませんが、 提出物のルーブリックの成績を確認できます。 Classroom の UI。

Classroom の UI で、生徒として課題のサンプルを提出します。 次に、教師が手動でルーブリックを使用して課題を採点します。

Classroom UI でのルーブリック成績の表示 図 5. 採点中に教師に表示されるルーブリック。

ルーブリックで採点された生徒の提出物には、新たに 2 つの提出物が プロパティ: draftRubricGradesassignedRubricGrades。 下書き段階と割り当てられた採点時に教師が選択した点とレベル 構成されます。

また、関連するルーブリックと生徒の提出物には rubricId が含まれます。 できます。これは Google Workspace に関連付けられた 最新のルーブリックで CourseWork。この値は、教師が ルーブリックを使用します

既存の studentSubmissions.GetstudentSubmissions.List メソッドで採点済みの提出物を表示できます。

main.py に次の関数を追加して、生徒の提出物を一覧表示します。

def get_latest_submission(service, course_id, coursework_id):
    """Retrieves the last submission for an assignment."""
    try:
        response = service.courses().courseWork().studentSubmissions().list(
            courseId = course_id,
            courseWorkId = coursework_id,
            pageSize=1,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
        ).execute()
        submissions = response.get("studentSubmissions", [])
        if not submissions:
            print(
                """No submissions found. Did you remember to turn in and grade
                   the assignment in the UI?""")
            return
        submission = submissions[0]
        return submission

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

次に、main.py を更新して実行し、提出物の成績を確認します。

if __name__ == '__main__':
    service = build_authenticated_service(YOUR_API_KEY)

    submission = get_latest_submission(
        service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID)
    print(json.dumps(submission, indent=4))

draftRubricGradesassignedRubricGrades には次のものが含まれます。

  • 対応するルーブリック条件の criterionId
  • 教師が各基準に割り当てた points。たとえば、 教師によって上書きされる可能性もあります。
  • 各条件に対して選択されたレベルの levelId。教師が レベルを選択しているものの、その評価基準の点数がまだ割り当てられている場合、このフィールドには ありません。

これらのリストには、教師が次のいずれかの条件に該当する項目のみが含まれます。 選択します。たとえば、教師が 採点中に 1 つの基準(draftRubricGrades と ルーブリックが多数あっても、assignedRubricGrades には 1 つの項目しか含まれません。 できます。

ルーブリックを削除する

ルーブリックは、標準の Delete リクエストで削除できます。次のコードでは、 図に示されていますが、採点機能はすでに 現在のルーブリックは削除できません。

def delete_rubric(service, course_id, coursework_id, rubric_id):
    """Deletes the rubric on a coursework."""
    try:
        service.courses().courseWork().rubrics().delete(
            courseId=course_id,
            courseWorkId=coursework_id,
            id=rubric_id,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
        ).execute()

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

ルーブリックのエクスポートとインポート

ルーブリックは Google に手動でエクスポート可能 教師がスプレッドシートを再利用できる。

コード内でルーブリックの条件を指定するだけでなく、 エクスポートしたシートからルーブリックを更新するには、 criteria ではなくルーブリック本文の sourceSpreadsheetId:

def create_rubric_from_sheet(service, course_id, coursework_id, sheet_id):
    """Creates an example rubric on a coursework."""
    try:
        body = {
            "sourceSpreadsheetId": sheet_id
        }

        rubric = service.courses().courseWork().rubrics().create(
            courseId=course_id, courseWorkId=coursework_id, body=body,
            # Specify the preview version. Rubrics CRUD capabilities are
            # supported in V1_20231110_PREVIEW and later.
            previewVersion="V1_20231110_PREVIEW"
            ).execute()

        print(f"Rubric created with ID {rubric.get('id')}")
        return rubric

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error

フィードバック

問題が見つかった場合や、ご意見がある場合は、フィードバックをお寄せください。