開始使用評分量表

rubric 是老師評分學生提交內容時可使用的範本。Classroom API 可讓您代替老師管理這些評量標準。

Classroom UI 中的評分量表 圖 1. 查看 Classroom 作業的範例評分量表。

本指南說明 Rubrics API 的基本概念和功能。請參閱這些說明中心文章,瞭解評量表的一般結構,以及如何在 Classroom UI 中評分

必要條件

本指南假設您具備下列條件:

授權電腦版應用程式的憑證

如要以使用者身分驗證,並存取應用程式中的使用者資料,您需要建立一或多個 OAuth 2.0 用戶端 ID。用戶端 ID 可讓 Google 的 OAuth 伺服器識別單一應用程式。如果您的應用程式在多個平台上執行,則必須為每個平台建立專屬的用戶端 ID。

  1. 前往 Google Cloud 控制台的「憑證」頁面。
  2. 依序點選「建立憑證」 >「OAuth 用戶端 ID」
  3. 依序點選「應用程式類型」 >「桌面應用程式」
  4. 在「Name」欄位中輸入憑證名稱。這個名稱只會顯示在 Google Cloud 控制台中。例如「Rubrics Preview 用戶端」。
  5. 按一下「建立」,系統會顯示「OAuth client created」(已建立 OAuth 用戶端) 畫面,顯示新的用戶端 ID 和用戶端密碼。
  6. 依序按一下「Download JSON」和「OK」。新建立的憑證會顯示在 OAuth 2.0 用戶端 ID 下方。
  7. 將下載的 JSON 檔案儲存為 credentials.json,然後將檔案移至工作目錄。
  8. 依序按一下「Create Credentials」(建立憑證) >「API Key」(API 金鑰),並記下 API 金鑰。

詳情請參閱「建立存取憑證」。

設定 OAuth 範圍

視專案現有的 OAuth 範圍而定,您可能需要設定額外範圍。

  1. 前往 OAuth 同意畫面
  2. 依序點選「編輯應用程式」 >「儲存並繼續」,前往「範圍」畫面。
  3. 按一下「新增或移除範圍」
  4. 如果尚未擁有下列權限範圍,請新增:
    • 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 授權範圍 範例。您可以在「Google API 適用的 OAuth 2.0 範圍」中查看所有 Classroom 範圍。由於 API 仍處於預覽階段,因此這裡未提及評量標準。

設定範例

在工作目錄中安裝 Python 適用的 Google 用戶端程式庫:

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

建立名為 main.py 的檔案,使用 API 金鑰取代 YOUR_API_KEY,藉此建構用戶端程式庫並授權使用者:

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 執行指令碼。系統會提示您登入並同意 OAuth 範圍。

建立指派項目

評分標準與作業 (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 中的範例作業畫面。

建立評分量表

您現在可以開始管理評量標準了。

您可以使用包含完整評分量表物件的 Create 呼叫,在 CourseWork 上建立評分量表,其中會省略準則和等級的 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,使用先前的 CourseCourseWork 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 作業的範例評分量表。

查看評分量表

您可以使用標準的 ListGet 方法讀取評量標準。

作業最多只能包含一個評分量表,因此 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

在這個範例中,我們指定使用 updateMask 修改 criteria 欄位。

接著修改 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 使用者介面中查看更新後的評分量表 圖 4. 更新後的評分量表。

查看已使用評分量表評分的提交內容

目前,API 無法使用評分量表為學生繳交的作業評分,但您可以透過 Classroom UI 查看已使用評分量表評分的繳交作業的評分量表成績。

以學生身分登入 Classroom 使用者介面,完成並繳交範例作業。 然後,老師可以使用評分量表手動評分作業

在 Classroom 使用者介面中查看評分標準成績 圖 5.老師在評分期間查看評分量表。

使用評分量表評分的學生提交內容有兩個新的屬性:draftRubricGradesassignedRubricGrades,分別代表老師在草稿和指派的評分狀態期間所選擇的分數和等級。

此外,即使在評分前,學生繳交的作業如果有相關聯的評分量表,也會包含 rubricId 欄位。這個值代表與 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。如果老師未選擇等級,但仍為評量標準指派點數,則不會顯示這個欄位。

這些清單只包含老師選取等級或設定分數的條件項目。舉例來說,如果老師選擇在評分期間只與一個標準互動,draftRubricGradesassignedRubricGrades 就只會有一個項目,即使評分標準包含多個標準。

刪除評分量表

您可以使用標準的 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 試算表,方便老師重複使用。

除了在程式碼中指定評分標準外,您也可以在評分量表主體中指定 sourceSpreadsheetId (而非 criteria),藉此透過這些匯出的試算表建立及更新評分量表:

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

意見回饋

如有任何問題或意見,歡迎提供意見回饋