Começar a usar rubricas

O rubric é um modelo que os professores podem usar ao dar notas para os estudantes envios. A API Classroom permite que você aja em nome das professor gerenciar essas rubricas.

Visualização de uma rubrica na interface do Google Sala de Aula Figura 1. Visualização de um exemplo de rubrica em uma atividade do Google Sala de Aula.

Este guia explica os conceitos básicos e a funcionalidade da API Rubrics. Consulte estes artigos da Central de Ajuda para conhecer as informações gerais estrutura de uma rubrica e como a rubrica a avaliação é feita na interface do Google Sala de Aula.

Pré-requisitos

Para seguir este guia, você precisa ter:

Autorizar credenciais para um aplicativo de computador

Para fazer a autenticação como usuário final e acessar os dados do usuário no app, crie um ou mais IDs do cliente OAuth 2.0. Um ID do cliente é usado para identificar um único app nos servidores OAuth do Google. Caso seu app seja executado em várias plataformas, crie um ID do cliente separado para cada plataforma.

  1. Acesse a página Credenciais do Google Cloud na console do Google Cloud.
  2. Clique em Criar credenciais > ID do cliente OAuth.
  3. Clique em Tipo de aplicativo > App para computador.
  4. No campo Nome, digite um nome para a credencial. Esse nome só é mostrados no console do Google Cloud. Por exemplo, "Cliente de visualização de rubricas".
  5. Clique em Criar. A tela criada pelo cliente OAuth é exibida, mostrando o novo ID e chave secreta do cliente.
  6. Clique em Fazer o download do JSON e depois em OK. A credencial recém-criada aparece em "IDs do cliente OAuth 2.0".
  7. Salve o arquivo JSON salvo como credentials.json e mova-o para seu diretório de trabalho.
  8. Clique em Criar credenciais > Chave de API e anote a chave de API.

Consulte Criar credenciais de acesso para saber mais.

Configurar escopos do OAuth

Dependendo dos escopos do OAuth do seu projeto, talvez seja necessário configurar escopos de adição.

  1. Acesse a tela de permissão OAuth.
  2. Clique em Editar aplicativo > Clique em Salvar e continuar para acessar a tela "Escopos".
  3. Clique em Adicionar ou remover escopos.
  4. Adicione os seguintes escopos se ainda não os tiver:
    • https://www.googleapis.com/auth/classroom.coursework.students
    • https://www.googleapis.com/auth/classroom.courses
  5. Em seguida, clique em Atualizar > Salvar e continuar > Salvar e continuar > Voltar para o painel.

Consulte Configurar a tela de permissão OAuth para saber mais.

O escopo classroom.coursework.students dá acesso de leitura e gravação rubricas (com acesso a CourseWork) e o escopo classroom.courses permite cursos de leitura e escrita.

Os escopos necessários para um determinado método estão listados na documentação de referência. para o método. Consulte courses.courseWork.rubrics.create escopos de autorização como exemplo. Você pode conferir todos os escopos do Google Sala de Aula em Escopos do OAuth 2.0 para o Google APIs do Google. As rubricas não são mencionadas aqui porque a API ainda está em pré-lançamento.

Configurar a amostra

No seu diretório de trabalho, instale a biblioteca de cliente do Google para Python:

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

Crie um arquivo chamado main.py, que cria a biblioteca de cliente e autoriza a usuário, usando sua chave de API no lugar de 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)

Execute o script usando python main.py. Será solicitado que você faça login e consentir com os escopos OAuth.

Criar uma atividade

Uma rubrica está associada a uma atividade, ou CourseWork, e só pode ser usada significativo no contexto dessa CourseWork. As rubricas só podem ser criadas por o projeto do Google Cloud que criou o item CourseWork pai. Para os objetivos deste guia, crie uma nova atividade CourseWork com um script.

Adicione o seguinte a 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

Agora, atualize main.py para extrair o course_id da classe de teste que você acabou de criar uma nova atividade de amostra e recuperar o 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.

Salve o course_id e o coursework_id. Eles são necessários para todas as rubricas CRUD as operações.

Agora você tem um exemplo de CourseWork no Google Sala de Aula.

Visualização de uma atividade na interface do Google Sala de Aula Figura 2. Visualização de um exemplo de atividade no Google Sala de Aula.

Criar uma rubrica

Agora você já pode começar a gerenciar rubricas.

Uma rubrica pode ser criada em uma CourseWork com uma chamada Create contendo as seguintes informações: objeto de rubrica completa, em que as propriedades do ID para critérios e níveis são omitidas (são gerados na criação).

Adicione a seguinte função a 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

Em seguida, atualize e execute main.py para criar a rubrica de exemplo usando Course. e CourseWork de antes:

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

Alguns pontos sobre a representação da rubrica:

  • A ordem dos critérios e dos níveis é refletida na interface do Google Sala de Aula.
  • Os níveis pontuados (aqueles com a propriedade points) precisam ser classificados por pontos. em ordem crescente ou decrescente (eles não podem ser ordenados aleatoriamente).
  • Os professores podem reordenar os critérios e os níveis pontuados (mas não sem pontuação níveis) na interface, o que muda a ordem dos dados.

Confira as limitações para saber mais sobre a estrutura das rubricas.

Na interface, você vai encontrar a rubrica na atividade.

Visualização de uma rubrica na interface do Google Sala de Aula Figura 3. Visualização de um exemplo de rubrica em uma atividade do Google Sala de Aula.

Ler uma rubrica

As rubricas podem ser lidas com os métodos padrão List e Get.

Pode haver no máximo uma rubrica em uma atividade, então List pode parecer não intuitiva, mas será útil se você ainda não tiver o ID da rubrica. Se houver não há uma rubrica associada a CourseWork, a resposta de List está vazia.

Adicione a seguinte função a 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

Atualize e execute main.py para buscar a rubrica que você adicionou:

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.

Observe a propriedade id na rubrica para as próximas etapas.

Get funciona bem quando você tem o ID da rubrica. Como usar Get na função em vez disso, pode ser semelhante a:

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

Essa implementação retornará um erro 404 se não houver rubrica.

Atualizar uma rubrica

As atualizações em uma rubrica são feitas nas chamadas do Patch. Devido à complexidade da estrutura de uma rubrica, as atualizações devem ser feitas com um padrão leitura-modificação-gravação, em que o toda a propriedade criteria será substituída.

As regras de atualização são as seguintes:

  1. Os critérios ou níveis adicionados sem um ID são considerados adições.
  2. Os critérios ou níveis ausentes anteriores são considerados exclusões.
  3. Os critérios ou níveis com um ID existente, mas com dados modificados, são considerados edições. As propriedades não modificadas são deixadas como estão.
  4. Os critérios ou níveis fornecidos com IDs novos ou desconhecidos são considerados erros.
  5. A ordem dos novos critérios e níveis será considerada a nova ordem da interface. (com as limitações mencionadas acima).

Adicionar uma função para atualizar uma rubrica:

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

Neste exemplo, o campo criteria é especificado para modificação com uma updateMask.

Em seguida, modifique main.py para fazer uma mudança em cada uma das atualizações mencionadas acima. regras:

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

As alterações serão aplicadas ao professor no Google Sala de Aula.

Visualização de uma rubrica atualizada na interface do Google Sala de Aula Figura 4. Visualização da rubrica atualizada.

Conferir os envios avaliados por rubrica

Por enquanto, os envios dos alunos não podem ser avaliados com uma rubrica pela API, mas você podem ler as notas dos envios que foram avaliados com uma rubrica em a interface do Google Sala de Aula.

Como estudante na interface do Google Sala de Aula, conclua e entregue seu exemplo de atividade. Em seguida, como professor, corrija a tarefa manualmente usando a rubrica.

Visualização da nota de uma rubrica na interface do Google Sala de Aula Figura 5. Visualização da rubrica para o professor durante a avaliação.

Os envios dos alunos que foram avaliados com uma rubrica têm dois novos propriedades: draftRubricGrades e assignedRubricGrades, representando as pontos e níveis escolhidos pelo professor durante a avaliação preliminar e na avaliação atribuída estados, respectivamente.

Além disso, os envios dos estudantes com uma rubrica associada contêm um rubricId mesmo antes da avaliação. Representa a rubrica mais recente associada ao a CourseWork, e esse valor pode mudar se os professores excluírem e recriarem uma da tarefa.

É possível usar as APIs studentSubmissions.Get e studentSubmissions.List para ver os envios que valem nota.

Adicione a seguinte função a main.py para listar os envios dos estudantes:

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

Em seguida, atualize e execute main.py para conferir as notas do envio.

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

A draftRubricGrades e a assignedRubricGrades contêm:

  • O criterionId dos critérios da rubrica correspondentes.
  • A points que o professor atribuiu a cada critério. Isso pode ser do nível selecionado, mas o professor também pode ter substituído isso.
  • O levelId do nível escolhido para cada critério. Se o professor não escolher um nível, mas ainda atribuir pontos para o critério, esse campo não estiver presente.

Essas listas contêm apenas entradas para os critérios em que um professor selecionar um nível ou definir pontos. Por exemplo, se um professor escolher interagirem com um critério durante a avaliação, os draftRubricGrades e assignedRubricGrades só teria um item, mesmo que a rubrica tenha muitos critérios.

Excluir uma rubrica

Uma rubrica pode ser excluída com uma solicitação padrão do Delete. O código a seguir mostra um exemplo de função para integridade, mas como a avaliação já iniciado, não será possível excluir a rubrica atual:

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

Exportar e importar rubricas

As rubricas podem ser exportadas manualmente para o Google Planilhas para reutilização pelos professores.

Além de especificar os critérios da rubrica no código, é possível criar e atualizar rubricas dessas planilhas exportadas especificando o sourceSpreadsheetId no corpo da rubrica em vez de 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

Feedback

Se você encontrar algum problema ou tiver sugestões, compartilhe seu feedback.