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 ocenami cząstkowymi w imieniu nauczyciela.

Wygląd oceny cząstkowej w interfejsie Classroom Rysunek 1. Przykład oceny cząstkowej w projekcie w Classroom

W tym przewodniku opisano podstawowe pojęcia i funkcje interfejsu Rubrics API. Zapoznaj się z tymi artykułami w Centrum pomocy, aby dowiedzieć się więcej o ogólnej strukturze karty oceny i o tym, jak ocenić kartę w interfejsie Classroom.

Wymagania wstępne

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

Autoryzowanie danych logowania do aplikacji na komputer

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 służy do identyfikowania pojedynczej aplikacji na serwerach OAuth Google. Jeśli Twoja aplikacja działa na wielu platformach, musisz utworzyć oddzielny identyfikator klienta dla każdej z nich.

  1. W konsoli Google Cloud otwórz stronę Dane logowania.
  2. Kliknij Utwórz dane logowania > Identyfikator klienta OAuth.
  3. Kliknij Typ aplikacji > Aplikacja na komputer.
  4. W polu Nazwa wpisz nazwę danych logowania. Ta nazwa jest widoczna tylko w konsoli Google Cloud. Na przykład „Klient podglądu ocen cząstkowych”.
  5. Kliknij Utwórz. Pojawi się ekran tworzenia klienta OAuth z nowym identyfikatorem klienta i tajnym kluczem klienta.
  6. Kliknij Pobierz plik JSON, a następnie OK. Nowo utworzone dane logowania pojawią się 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 klucz interfejsu API.

Więcej informacji znajdziesz w artykule Tworzenie danych logowania.

Konfigurowanie zakresów OAuth

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

  1. Przejdź do ekranu zgody OAuth.
  2. Aby otworzyć ekran Zakresy, kliknij Edytuj aplikację > Zapisz i kontynuuj.
  3. Kliknij Dodaj lub usuń zakresy.
  4. Jeśli nie masz tych uprawnień, dodaj je:
    • 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 umożliwia odczyt i zapis kryteriów oceny (oraz dostęp do CourseWork), a zakres classroom.courses umożliwia odczyt i zapis kursów.

Zakresy wymagane w przypadku danej metody są wymienione w jej dokumentacji. Przykładem są courses.courseWork.rubrics.createzakresy autoryzacji. Wszystkie zakresy Classroom znajdziesz w sekcji Zakresy OAuth 2.0 dla interfejsów API Google. Nie jest tu wymieniona, ponieważ interfejs API jest nadal w wersji wstępnej.

Konfigurowanie próbki

W katalogu roboczym zainstaluj bibliotekę klienta Google dla Pythona:

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

Utwórz plik o nazwie main.py, który tworzy bibliotekę klienta i uwierzytelnia użytkownika, używając klucza 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ą python main.py. Powinna pojawić się prośba o zalogowanie się i zgodę na używanie zakresów protokołu OAuth.

Utwórz zadanie

Rubryka jest powiązana z projektem lub CourseWork i ma znaczenie tylko w kontekście tego CourseWork. Kryteria może tworzyć tylko projekt Google Cloud, który utworzył element nadrzędny CourseWork. W ramach tego przewodnika utwórz nowe przypisanie o rodzaju CourseWork za pomocą skryptu.

Dodaj do pliku main.py te informacje:

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 klasy testu, którą właśnie utworzyłeś, 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 do wszystkich operacji CRUD dotyczących kryteriów.

W Classroom powinien teraz pojawić się przykładowy CourseWork.

Wygląd projektu w interfejsie Classroom Rysunek 2. Widok przykładowego projektu w Classroom

Tworzenie oceny cząstkowej

Teraz możesz zacząć zarządzać schematami oceniania.

Oceny cząstkowej można utworzyć w usługach CourseWork za pomocą wywołania Create zawierającego pełny obiekt oceny cząstkowej, w którym pominięto właściwości identyfikatora dla kryteriów i poziomów (są one generowane podczas tworzenia).

Dodaj do main.py tę funkcję:

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 polecenie 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 informacji o reprezentowaniu kryteriów:

  • Kolejność kryteriów i poziomów jest odzwierciedlona w interfejsie Classroom.
  • Ocenione poziomy (za pomocą właściwości points) muszą być sortowane według punktów w kolejności rosnącej lub malejącej (nie mogą być posortowane losowo).
  • Nauczyciele mogą ponownie sortować kryteria i poziomy z punktacją (ale nie bezpunktowe poziomy) w interfejsie, co zmienia ich kolejność w danych.

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

W interfejsie powinna się wyświetlić karta oceny projektu.

Wygląd oceny cząstkowej w interfejsie Classroom Rysunek 3. Przykład oceny cząstkowej w projekcie w Classroom

Czytanie oceny cząstkowej

Oceny cząstkowe można odczytać za pomocą standardowych metod List i Get.

W zadaniu może być maksymalnie jedna karta, więc List może wydawać się nieintuicyjna, ale jest przydatna, jeśli nie masz jeszcze identyfikatora karty. Jeśli nie ma kryteriów powiązanych z CourseWork, odpowiedź List będzie pusta.

Dodaj do pliku main.py tę funkcję:

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

Zapisz w swoim kryterium usługę id, aby wykorzystać ją w kolejnych krokach.

Get działa dobrze, gdy masz identyfikator kryteriów. 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

Ta implementacja zwraca kod 404, jeśli nie ma żadnej rubryki.

Aktualizowanie oceny cząstkowej

Aktualizowanie oceny cząstkowej odbywa się za pomocą wywołań Patch. Ze względu na złożoną strukturę kryteriów aktualizacje muszą być wykonywane w schemacie odczyt-modyfikacja-zapis, w którym zastępowana jest cała właściwość criteria.

Oto reguły aktualizacji:

  1. Kryteria lub poziomy dodane bez identyfikatora są uważane za dodatki.
  2. Kryteria lub poziomy, których brak w poprzedniej wersji, są uważane za usunięte.
  3. Kryteria lub poziomy z istniejącym identyfikatorem, ale ze zmienionymi danymi są uznawane za modyfikacje. Niezmienione właściwości pozostają bez zmian.
  4. Kryteria lub poziomy podane 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 wymienionymi wyżej ograniczeniami).

Dodaj funkcję aktualizowania kryteriów:

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 oznaczone do modyfikacji za pomocą parametru updateMask.

Następnie zmień main.py, aby wprowadzić zmianę w przypadku każdego z wymienionych wyżej 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ć już widoczne u nauczyciela w Classroom.

Wyświetlanie zaktualizowanej oceny cząstkowej w interfejsie Classroom Rysunek 4. Widok zaktualizowanej tabeli

Wyświetlanie zadań ocenionych za pomocą kryteriów

Obecnie interfejs API nie umożliwia oceniania zadań uczniów za pomocą ocen cząstkowych, ale możesz odczytać oceny cząstkowe zadań, które zostały ocenione za pomocą oceny cząstkowej w interfejsie Classroom.

Jako uczeń w interfejsie Classroom ukończ i oddaj przykładowy projekt. Następnie jako nauczyciel możesz ręcznie ocenić projekt za pomocą oceny cząstkowej.

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

Zadania uczniów, które zostały ocenione za pomocą oceny cząstkowej, mają 2 nowe właściwości: draftRubricGrades i assignedRubricGrades. Określają one odpowiednio punkty i poziomy wybrane przez nauczyciela podczas wersji roboczej oraz przypisane stany oceniania.

Dodatkowo zadania uczniów z powiązaną kartą zawierały pole rubricId, nawet przed ocenieniem. Ta wartość reprezentuje najnowszą kartę oceniania powiązaną z CourseWork. Może się ona zmienić, jeśli nauczyciele usuną i ponownie utworzą kartę oceniania.

Aby wyświetlić ocenione zadania, możesz użyć istniejących metod studentSubmissions.Get i studentSubmissions.List.

Dodaj do 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 przesłanych danych.

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 zawierają:

  • criterionId odpowiadających kryteriów oceny cząstkowej.
  • points przypisany przez nauczyciela do każdego kryterium. Może ona pochodzić z wybranego poziomu, ale nauczyciel mógł to też zastąpić.
  • levelId poziomu wybranego dla każdego kryterium. Jeśli nauczyciel nie wybrał poziomu, ale mimo to przypisywał punkty do kryterium, to pole nie jest dostępne.

Te listy zawierają tylko wpisy dotyczące kryteriów, w których nauczyciel wybrał poziom lub ustawił punkty. Jeśli na przykład podczas oceniania nauczyciel zdecyduje się na interakcję tylko z jednym kryterium, elementy draftRubricGrades i assignedRubricGrades będą zawierać tylko 1 element, nawet jeśli ocena cząstkowa ma wiele kryteriów.

Usuwanie oceny cząstkowej

Kryteria można usunąć za pomocą standardowego żądania Delete. Poniższy kod pokazuje przykładową funkcję, ale ponieważ ocena już się rozpoczęła, 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 eksportować do Arkuszy Google, aby nauczyciele mogli ich używać ponownie.

Poza określeniem w kodzie kryteriów oceny cząstkowej możesz też tworzyć i aktualizować oceny cząstkowe z tych wyeksportowanych arkuszy. Aby to zrobić, zamiast criteria podaj w treści elementu 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 jakieś problemy lub masz uwagi, prześlij opinię.