Wprowadzenie do ocen cząstkowych

rubric to szablon, którego nauczyciele mogą używać do oceniania prac uczniów. Interfejs Classroom API umożliwia zarządzanie tymi ocenami cząstkowymi w imieniu nauczyciela.

Widok oceny cząstkowej w interfejsie Classroom Rysunek 1. Widok przykładowej oceny cząstkowej za projekt w Classroom.

W tym przewodniku przedstawiono podstawowe pojęcia i funkcje interfejsu Rubrics API. W tych artykułach w Centrum pomocy znajdziesz informacje na temat ogólnej struktury ocen cząstkowych i sposobu oceny cząstkowej w interfejsie Classroom.

Wymagania wstępne

W tym przewodniku przyjęto założenie, że masz:

Autoryzowanie danych logowania do aplikacji komputerowej

Aby uwierzytelnić się jako użytkownik i uzyskać dostęp do danych użytkownika w aplikacji, musisz utworzyć co najmniej 1 identyfikator klienta OAuth 2.0. Identyfikator klienta wskazuje konkretną aplikację na serwerach OAuth Google. Jeśli Twoja aplikacja działa na wielu platformach, musisz utworzyć oddzielny identyfikator klienta dla każdej z nich.

  1. Otwórz stronę danych logowania GCP w konsoli Google Cloud.
  2. Kliknij Utwórz dane logowania > Identyfikator klienta OAuth.
  3. Kliknij Typ aplikacji > Aplikacja komputerowa.
  4. W polu Nazwa wpisz nazwę danych logowania. Ta nazwa jest widoczna tylko w konsoli Google Cloud. Na przykład „Klient wersji testowej ocen cząstkowych”.
  5. Kliknij Utwórz. Pojawi się ekran utworzonego klienta OAuth z nowym identyfikatorem klienta i tajnym kluczem klienta.
  6. Kliknij Pobierz JSON, a potem OK. Nowo utworzone dane logowania będą widoczne w sekcji Identyfikatory klienta OAuth 2.0.
  7. Zapisz pobrany plik JSON jako credentials.json i przenieś go do katalogu roboczego.
  8. Kliknij Utwórz dane logowania > Klucz interfejsu API i zapisz ten klucz.

Więcej informacji znajdziesz w artykule Tworzenie danych logowania.

Skonfiguruj zakresy OAuth

W zależności od istniejących zakresów OAuth w projekcie może być konieczne skonfigurowanie zakresów OAuth.

  1. Otwórz ekran zgody OAuth.
  2. Kliknij Edytuj aplikację > Zapisz i kontynuuj, aby przejść do ekranu Zakresy.
  3. Kliknij Dodaj lub usuń zakresy.
  4. Dodaj te zakresy, jeśli jeszcze ich nie masz:
    • https://www.googleapis.com/auth/classroom.coursework.students
    • https://www.googleapis.com/auth/classroom.courses
  5. Następnie kliknij Aktualizuj > Zapisz i kontynuuj > Zapisz i kontynuuj > Powrót do panelu.

Więcej informacji znajdziesz w artykule Konfigurowanie ekranu zgody OAuth.

Zakres classroom.coursework.students zapewnia dostęp do ocen cząstkowych z możliwością odczytu i zapisu (wraz z dostępem do CourseWork), a zakres classroom.courses – na kurs czytania i pisania.

Zakresy wymagane dla danej metody są wymienione w jej dokumentacji. Przykład znajdziesz w sekcji Zakresy autoryzacji courses.courseWork.rubrics.create. Wszystkie zakresy Classroom znajdziesz w artykule Zakresy OAuth 2.0 dla interfejsów API Google. Nie są tu wymienione oceny cząstkowe, ponieważ interfejs API jest nadal w wersji testowej.

Konfigurowanie przykładu

W katalogu roboczym zainstaluj bibliotekę klienta Google dla języka Python:

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

Utwórz plik o nazwie main.py, który kompiluje bibliotekę klienta i autoryzuje użytkownika, używając klucza interfejsu API zamiast 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)

Uruchom skrypt za pomocą polecenia python main.py. Pojawi się prośba o zalogowanie się i wyrażenie zgody na zakresy OAuth.

Utwórz zadanie

Ocena cząstkowa jest powiązana z projektem (CourseWork) i ma znaczenie tylko w kontekście tego elementu CourseWork. Oceny cząstkowe można tworzyć tylko w projekcie Google Cloud, w którym utworzono nadrzędny element CourseWork. Na potrzeby tego przewodnika utwórz nowe przypisanie CourseWork za pomocą skryptu.

Dodaj następujące elementy do grupy reklam 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

Zaktualizuj teraz main.py, aby pobrać course_id utworzonej przed chwilą zajęć testowych, utwórz nowy przykładowy projekt i pobierz coursework_id projektu:

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.

Zapisz course_id i coursework_id. Są one potrzebne w przypadku wszystkich operacji na CRUD w ocenach cząstkowych.

Teraz w Classroom powinien być widoczny przykład CourseWork.

Wyświetlanie projektu w interfejsie Classroom Rysunek 2. Widok przykładowego projektu w Classroom.

Tworzenie oceny cząstkowej

Możesz teraz zacząć zarządzać ocenami cząstkowymi.

Ocenę cząstkową można utworzyć w elemencie CourseWork za pomocą wywołania Create zawierającego pełny obiekt oceny cząstkowej, przy czym właściwości ID kryteriów i poziomów są pomijane (są generowane podczas tworzenia).

Dodaj tę funkcję do funkcji 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

Następnie zaktualizuj i uruchom main.py, aby utworzyć przykładową ocenę cząstkową przy użyciu wcześniejszych identyfikatorów Course i CourseWork:

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))

Kilka uwag na temat prezentacji oceny cząstkowej:

  • Kolejność kryteriów i poziomów jest odzwierciedlana w interfejsie Classroom.
  • Poziomy punktowane (z właściwością points) muszą być sortowane według punktów w kolejności rosnącej lub malejącej (nie mogą być uporządkowane losowo).
  • Nauczyciele mogą ponownie posortować w interfejsie kryteria i ocenione poziomy (ale nie poziomy bez punktacji), co zmienia ich kolejność w danych.

Więcej informacji o zastrzeżeniach dotyczących struktury ocen cząstkowych znajdziesz w sekcji Ograniczenia.

W interfejsie powinna być widoczna ocena cząstkowa projektu.

Widok oceny cząstkowej w interfejsie Classroom Rysunek 3. Widok przykładowej oceny cząstkowej za projekt w Classroom.

Czytanie oceny cząstkowej

Oceny cząstkowe można odczytywać przy użyciu standardowych metod List i Get.

Projekt może zawierać maksymalnie 1 ocenę cząstkową, więc funkcja List może wydawać się nieintuicyjna, ale może się przydać, jeśli nie masz jeszcze identyfikatora oceny cząstkowej. Jeśli z elementem CourseWork nie jest powiązana żadna ocena cząstkowa, odpowiedź List jest pusta.

Dodaj tę funkcję do funkcji 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

Zaktualizuj i uruchom polecenie main.py, aby pobrać dodaną ocenę cząstkową:

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.

Na późniejszych krokach zanotuj właściwość id w ocenie cząstkowej.

Funkcja Get działa dobrze, gdy masz identyfikator oceny cząstkowej. Zamiast tego użycie w funkcji Get może wyglądać tak:

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

W przypadku braku oceny cząstkowej ta implementacja zwraca kod 404.

Aktualizowanie oceny cząstkowej

Aktualizowanie oceny cząstkowej odbywa się za pomocą połączeń Patch. Ze względu na złożoną strukturę oceny cząstkowej aktualizacje należy wprowadzać za pomocą wzorca odczyt-modyfikacja-zapis, w którym zastępowana jest cała właściwość criteria.

Zasady aktualizacji są następujące:

  1. Kryteria lub poziomy dodane bez identyfikatora są uważane za dodatki.
  2. Kryteria lub poziomy, których brakuje wcześniej, są uznawane za usunięcia.
  3. Kryteria lub poziomy mające istniejący identyfikator, ale zmodyfikowane dane są uznawane za zmiany. Niezmodyfikowane właściwości pozostają bez zmian.
  4. Kryteria lub poziomy dostarczone z nowymi lub nieznanymi identyfikatorami są uznawane za błędy.
  5. Kolejność nowych kryteriów i poziomów jest uznawana za nową kolejność w interfejsie (z wspomnianymi wcześniej ograniczeniami).

Dodawanie funkcji aktualizowania oceny cząstkowej:

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

W tym przykładzie pole criteria jest określone do modyfikacji za pomocą updateMask.

Następnie zmodyfikuj main.py, aby wprowadzić zmianę w każdej z wymienionych wcześniej reguł aktualizacji:

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))

Zmiany powinny być widoczne dla nauczyciela w Classroom.

Widok zaktualizowanej oceny cząstkowej w interfejsie Classroom Rysunek 4. Widok zaktualizowanej oceny cząstkowej.

Wyświetlanie zadań z oceną cząstkową

Obecnie zadania uczniów nie mogą być oceniane za pomocą oceny cząstkowej przez interfejs API, ale w interfejsie Classroom możesz odczytywać oceny cząstkowe za projekty, dla których została oceniona ocena cząstkowa.

Jako uczeń korzystający z interfejsu Classroom ukończ i oddaj przykładowy projekt. Następnie jako nauczyciel możesz ręcznie ocenić projekt przy użyciu oceny cząstkowej.

Widok oceny cząstkowej w interfejsie Classroom Rysunek 5. Widok oceny cząstkowej dla nauczyciela podczas oceniania.

Zadania uczniów, które zostały ocenione przy użyciu oceny cząstkowej, mają 2 nowe właściwości: draftRubricGrades i assignedRubricGrades, które reprezentują odpowiednio punkty i poziomy wybrane przez nauczyciela w trakcie tworzenia wersji roboczej oraz przypisane stany oceniania.

Dodatkowo zadania przesłane przez uczniów z powiązaną oceną cząstkową zawierają pole rubricId, nawet przed ocenianiem. Reprezentuje ona najnowszą ocenę cząstkową powiązaną z elementem CourseWork i może się zmienić, jeśli nauczyciele usuną i odtworzy ocenę cząstkową.

Do wyświetlania ocenionych zadań możesz użyć istniejących metod studentSubmissions.Get i studentSubmissions.List.

Dodaj do narzędzia main.py tę funkcję, aby wyświetlić listę zadań przesłanych przez uczniów:

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

Następnie zaktualizuj i uruchom main.py, aby wyświetlić oceny za przesłanie.

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))

draftRubricGrades i assignedRubricGrades zawierają:

  • Wartość criterionId odpowiednich kryteriów oceny cząstkowej.
  • points przypisane przez nauczyciela do poszczególnych kryteriów. Może pochodzić z wybranego poziomu, ale nauczyciel mógł to zmienić.
  • Wartość levelId poziomu wybranego dla każdego kryterium. Jeśli nauczyciel nie wybierze poziomu, ale wciąż przypisze do niego punkty, pole tego zabraknie.

Listy te zawierają tylko pozycje zgodne z kryteriami, według których nauczyciel wybrał poziom lub zestaw punktów. Jeśli na przykład nauczyciel zdecyduje się na interakcję tylko z jednym kryterium podczas oceniania, draftRubricGrades i assignedRubricGrades będą miały tylko 1 element, nawet jeśli ocena cząstkowa zawiera wiele kryteriów.

Usuwanie oceny cząstkowej

Ocenę cząstkową można usunąć za pomocą standardowego żądania Delete. Poniższy kod pokazuje przykładową funkcję kompletności, ale ponieważ ocenianie już się rozpoczęło, nie możesz usunąć bieżącej oceny cząstkowej:

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

Eksportowanie i importowanie ocen cząstkowych

Oceny cząstkowe można ręcznie wyeksportować do Arkuszy Google, aby użyć ich ponownie przez nauczycieli.

Oprócz określenia w kodzie kryteriów oceny cząstkowej możesz też tworzyć i aktualizować oceny cząstkowe z wyeksportowanych arkuszy. Aby to zrobić, w treści oceny cząstkowej zamiast criteria możesz użyć właściwości 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

Prześlij opinię

Jeśli zauważysz problemy lub masz jakieś uwagi, podziel się swoją opinią.