Gerenciar atividades e notas

A interface do Google Sala de Aula é compatível com cinco tipos de atividades: Atividades, Atividades com teste, perguntas de resposta curta, perguntas de múltipla escolha e Materiais. Atualmente, a API Classroom é compatível com três desses tipos, que são conhecidos como CourseWorkType na API: Atividades, Resposta curta e de múltipla escolha.

Para acessar essa funcionalidade, use o Recurso do CourseWork, que representa uma tarefa ou pergunta que foi atribuída aos alunos em um curso específico, incluindo quaisquer materiais e detalhes adicionais, como devido ou da pontuação máxima.

Além do recurso CourseWork, você pode gerenciar as tarefas concluídas com o recurso StudentSubmission. As seções a seguir descrevem esses com mais detalhes.

Criar atividades

As atividades podem ser criadas em nome dos professores do curso e tentar criar tarefas em um curso em nome de um aluno resultará em um erro PERMISSION_DENIED 403. Da mesma forma, os administradores de domínio não podem criar atividades de cursos que não ensinam e tentar fazer isso pela API também vai resultar em um erro PERMISSION_DENIED 403.

Ao criar atividades usando o método courses.courseWork.create, você É possível anexar links como materials, conforme mostrado no exemplo de código abaixo:

Java

classroom/snippets/src/main/java/CreateCourseWork.java
CourseWork courseWork = null;
try {
  // Create a link to add as a material on course work.
  Link articleLink =
      new Link()
          .setTitle("SR-71 Blackbird")
          .setUrl("https://www.lockheedmartin.com/en-us/news/features/history/blackbird.html");

  // Create a list of Materials to add to course work.
  List<Material> materials = Arrays.asList(new Material().setLink(articleLink));

  /* Create new CourseWork object with the material attached.
  Set workType to `ASSIGNMENT`. Possible values of workType can be found here:
  https://developers.google.com/classroom/reference/rest/v1/CourseWorkType
  Set state to `PUBLISHED`. Possible values of state can be found here:
  https://developers.google.com/classroom/reference/rest/v1/courses.courseWork#courseworkstate */
  CourseWork content =
      new CourseWork()
          .setTitle("Supersonic aviation")
          .setDescription(
              "Read about how the SR-71 Blackbird, the world’s fastest and "
                  + "highest-flying manned aircraft, was built.")
          .setMaterials(materials)
          .setWorkType("ASSIGNMENT")
          .setState("PUBLISHED");

  courseWork = service.courses().courseWork().create(courseId, content).execute();

  /* Prints the created courseWork. */
  System.out.printf("CourseWork created: %s\n", courseWork.getTitle());
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf("The courseId does not exist: %s.\n", courseId);
  } else {
    throw e;
  }
  throw e;
} catch (Exception e) {
  throw e;
}
return courseWork;

Python

classroom/snippets/classroom_create_coursework.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_create_coursework(course_id):
  """
  Creates the coursework the user has access to.
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """

  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member

  try:
    service = build("classroom", "v1", credentials=creds)
    coursework = {
        "title": "Ant colonies",
        "description": """Read the article about ant colonies
                              and complete the quiz.""",
        "materials": [
            {"link": {"url": "http://example.com/ant-colonies"}},
            {"link": {"url": "http://example.com/ant-quiz"}},
        ],
        "workType": "ASSIGNMENT",
        "state": "PUBLISHED",
    }
    coursework = (
        service.courses()
        .courseWork()
        .create(courseId=course_id, body=coursework)
        .execute()
    )
    print(f"Assignment created with ID {coursework.get('id')}")
    return coursework

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


if __name__ == "__main__":
  # Put the course_id of course whose coursework needs to be created,
  # the user has access to.
  classroom_create_coursework(453686957652)

O resultado inclui um identificador atribuído pelo servidor que pode ser usado para a atribuição em outras solicitações da API.

Para incluir materiais vinculados em uma atividade criada com a API Classroom, usar um recurso Link, especificando o URL de destino. O Google Sala de Aula busca automaticamente o título e a imagem em miniatura. A Classroom API também oferece suporte nativo a materiais do Google Drive e do YouTube, que podem incluídos em um recurso do DriveFile ou Recurso do YouTubeVideo em um formato de um jeito fácil.

Para especificar um prazo, defina os campos dueDate e dueTime como o hora UTC correspondente. A data de conclusão precisa estar no futuro.

Recuperar atividades e perguntas

É possível recuperar atividades e perguntas de estudantes e professores da correspondente ou por um administrador do domínio. Para recuperar um determinado para uma atividade ou pergunta, use courses.courseWork.get. Para recuperar todos atribuições ou perguntas (opcionalmente correspondendo a alguns critérios), use courses.courseWork.list.

O escopo necessário depende do papel que o usuário solicitante tem na neste curso. Se o usuário for um aluno, use um dos seguintes escopos:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

Se o usuário for um professor ou administrador de domínio, use uma das seguintes opções escopos:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

Ter permissão para recuperar uma atividade ou pergunta não implica permissões para acessar materiais ou metadados do material. Na prática, isso significa que um administrador pode não ver o título de um arquivo do Google Drive anexado que não são membros do curso. Se você quiser permitir que os administradores acessem os recursos consulte a documentação em todo o domínio delegação guia.

Gerenciar as respostas dos estudantes

Uma StudentSubmission recurso representa o trabalho realizado e a nota de um estudante para uma tarefa ou pergunta. Uma StudentSubmission é criado implicitamente para cada aluno quando uma nova pergunta ou atribuição é criada.

As seções a seguir explicam ações comuns que gerenciam as respostas dos estudantes.

Recuperar respostas dos estudantes

Os estudantes podem recuperar os próprios envios, os professores podem recuperar os arquivos enviados para todos os alunos em seus cursos, e os administradores de domínio podem recuperar todos envios para todos os alunos no domínio. O envio de cada estudante é recebeu um identificador; Se você souber o identificador, use courses.courseWork.studentSubmissions.get para recuperá-la.

Use o método courses.courseWork.studentSubmissions.list para receber StudentSubmission recursos que correspondem a alguns critérios, conforme mostrado nas exemplo a seguir:

Java

classroom/snippets/src/main/java/ListSubmissions.java
List<StudentSubmission> studentSubmissions = new ArrayList<>();
String pageToken = null;

try {
  do {
    ListStudentSubmissionsResponse response =
        service
            .courses()
            .courseWork()
            .studentSubmissions()
            .list(courseId, courseWorkId)
            .setPageToken(pageToken)
            .execute();

    /* Ensure that the response is not null before retrieving data from it to avoid errors. */
    if (response.getStudentSubmissions() != null) {
      studentSubmissions.addAll(response.getStudentSubmissions());
      pageToken = response.getNextPageToken();
    }
  } while (pageToken != null);

  if (studentSubmissions.isEmpty()) {
    System.out.println("No student submission found.");
  } else {
    for (StudentSubmission submission : studentSubmissions) {
      System.out.printf(
          "Student id (%s), student submission id (%s)\n",
          submission.getUserId(), submission.getId());
    }
  }
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s) or courseWorkId (%s) does not exist.\n", courseId, courseWorkId);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmissions;

Python

classroom/snippets/classroom_list_submissions.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_list_submissions(course_id, coursework_id):
  """
  Creates the courses the user has access to.
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """

  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member
  submissions = []
  page_token = None

  try:
    service = build("classroom", "v1", credentials=creds)
    while True:
      coursework = service.courses().courseWork()
      response = (
          coursework.studentSubmissions()
          .list(
              pageToken=page_token,
              courseId=course_id,
              courseWorkId=coursework_id,
              pageSize=10,
          )
          .execute()
      )
      submissions.extend(response.get("studentSubmissions", []))
      page_token = response.get("nextPageToken", None)
      if not page_token:
        break

    if not submissions:
      print("No student submissions found.")

    print("Student Submissions:")
    for submission in submissions:
      print(
          "Submitted at:"
          f"{(submission.get('id'), submission.get('creationTime'))}"
      )

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


if __name__ == "__main__":
  # Put the course_id and coursework_id of course whose list needs to be
  # submitted.
  classroom_list_submissions(453686957652, 466086979658)

Para recuperar os recursos do StudentSubmission que pertencem a um estudante específico, faça o seguinte: especificando o parâmetro userId, conforme mostrado no exemplo a seguir:

Java

classroom/snippets/src/main/java/ListStudentSubmissions.java
List<StudentSubmission> studentSubmissions = new ArrayList<>();
String pageToken = null;

try {
  do {
    // Set the userId as a query parameter on the request.
    ListStudentSubmissionsResponse response =
        service
            .courses()
            .courseWork()
            .studentSubmissions()
            .list(courseId, courseWorkId)
            .setPageToken(pageToken)
            .set("userId", userId)
            .execute();

    /* Ensure that the response is not null before retrieving data from it to avoid errors. */
    if (response.getStudentSubmissions() != null) {
      studentSubmissions.addAll(response.getStudentSubmissions());
      pageToken = response.getNextPageToken();
    }
  } while (pageToken != null);

  if (studentSubmissions.isEmpty()) {
    System.out.println("No student submission found.");
  } else {
    for (StudentSubmission submission : studentSubmissions) {
      System.out.printf("Student submission: %s.\n", submission.getId());
    }
  }

Python

classroom/snippets/classroom_list_student_submissions.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_list_student_submissions(course_id, coursework_id, user_id):
  """
  Creates the courses the user has access to.
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """

  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member
  submissions = []
  page_token = None

  try:
    service = build("classroom", "v1", credentials=creds)
    while True:
      coursework = service.courses().courseWork()
      response = (
          coursework.studentSubmissions()
          .list(
              pageToken=page_token,
              courseId=course_id,
              courseWorkId=coursework_id,
              userId=user_id,
          )
          .execute()
      )
      submissions.extend(response.get("studentSubmissions", []))
      page_token = response.get("nextPageToken", None)
      if not page_token:
        break

    if not submissions:
      print("No student submissions found.")

    print("Student Submissions:")
    for submission in submissions:
      print(
          "Submitted at:"
          f"{(submission.get('id'), submission.get('creationTime'))}"
      )

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


if __name__ == "__main__":
  # Put the course_id, coursework_id and user_id of course whose list needs
  # to be submitted.
  classroom_list_student_submissions(453686957652, 466086979658, "me")

Os estudantes são identificados pelo ID exclusivo ou endereço de e-mail do usuário, conforme retornados pelo SDK Admin do Google. O usuário atual também pode consultar as próprias usando a abreviação "me".

Também é possível receber os envios dos alunos para todas as tarefas de uma neste curso. Para fazer isso, use o "-" literal como courseWorkId, conforme mostrado nas exemplo a seguir:

Java

service.courses().courseWork().studentSubmissions()
    .list(courseId, "-")
    .set("userId", userId)
    .execute();

Python

service.courses().courseWork().studentSubmissions().list(
    courseId=<course ID or alias>,
    courseWorkId='-',
    userId=<user ID>).execute()

O escopo necessário depende do papel que o usuário solicitante tem na neste curso. Use o escopo a seguir se o usuário for um professor ou um domínio administrador:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

Use o escopo a seguir se o usuário for um estudante:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

Ter permissão para recuperar o arquivo enviado por um estudante não significa permissões para acessar anexos ou metadados de anexos. Na prática, significa que um administrador pode não ver o título de um arquivo do Google Drive anexado se não fazem parte do curso. Se você quiser permitir que os administradores acessem aos arquivos do usuário, consulte a delegação em todo o domínio.

Adicionar anexos à resposta do estudante

Você pode anexar links para o envio de um estudante anexando Link, DriveFile ou YouTubeVideo. Isso é feito com courses.courseWork.studentSubmissions.modifyAttachments, conforme mostrado no exemplo a seguir:

Java

classroom/snippets/src/main/java/ModifyAttachmentsStudentSubmission.java
StudentSubmission studentSubmission = null;
try {
  // Create ModifyAttachmentRequest object that includes a new attachment with a link.
  Link link = new Link().setUrl("https://en.wikipedia.org/wiki/Irrational_number");
  Attachment attachment = new Attachment().setLink(link);
  ModifyAttachmentsRequest modifyAttachmentsRequest =
      new ModifyAttachmentsRequest().setAddAttachments(Arrays.asList(attachment));

  // The modified studentSubmission object is returned with the new attachment added to it.
  studentSubmission =
      service
          .courses()
          .courseWork()
          .studentSubmissions()
          .modifyAttachments(courseId, courseWorkId, id, modifyAttachmentsRequest)
          .execute();

  /* Prints the modified student submission. */
  System.out.printf(
      "Modified student submission attachments: '%s'.\n",
      studentSubmission.getAssignmentSubmission().getAttachments());
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
            + "not exist.\n",
        courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmission;

Python

classroom/snippets/classroom_add_attachment.py
def classroom_add_attachment(course_id, coursework_id, submission_id):
  """
  Adds attachment to existing course with specific course_id.
  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """
  creds, _ = google.auth.default()
  # pylint: disable=maybe-no-member
  request = {
      "addAttachments": [
          {"link": {"url": "http://example.com/quiz-results"}},
          {"link": {"url": "http://example.com/quiz-reading"}},
      ]
  }

  try:
    service = build("classroom", "v1", credentials=creds)
    while True:
      coursework = service.courses().courseWork()
      coursework.studentSubmissions().modifyAttachments(
          courseId=course_id,
          courseWorkId=coursework_id,
          id=submission_id,
          body=request,
      ).execute()

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


if __name__ == "__main__":
  # Put the course_id, coursework_id and submission_id of course in which
  # attachment needs to be added.
  classroom_add_attachment("course_id", "coursework_id", "me")

Um anexo de link é definido pelo URL de destino. o Google Sala de Aula vai usar buscar o título e a imagem da miniatura. Saiba mais sobre os outros materiais em as respectivas páginas de referência.

O StudentSubmission só pode ser modificado por um professor do curso ou por ao aluno proprietário. Você só pode anexar Materials se o CourseWorkType do envio do estudante é ASSIGNMENT.

O escopo necessário depende do papel que o usuário solicitante tem na neste curso. Use o escopo a seguir se o usuário for um professor:

  • https://www.googleapis.com/auth/classroom.coursework.students

Use o escopo a seguir se o usuário for um estudante:

  • https://www.googleapis.com/auth/classroom.coursework.me

Gerenciar o estado da resposta do estudante

É possível que o envio, a entrega ou a devolução de uma resposta do estudante seja cancelada. O campo de estado em StudentSubmission indica o estado atual. Para mudar o estado, chame um dos seguintes métodos:

Todos esses métodos precisam de um corpo vazio. Exemplo:

Java

classroom/snippets/src/main/java/ReturnStudentSubmission.java
try {
  service
      .courses()
      .courseWork()
      .studentSubmissions()
      .classroomReturn(courseId, courseWorkId, id, null)
      .execute();
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
            + "not exist.\n",
        courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}

Python

service.courses().courseWork().studentSubmission().turnIn(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    body={}).execute()

Somente o aluno proprietário de uma StudentSubmission pode entregá-la ou recuperá-la. Somente uma atividade entregue pode ser reivindicada. Os professores do curso só podem devolver StudentSubmission que está no estado entregue.

Atribuir nota às respostas dos estudantes

O recurso StudentSubmission tem dois campos para armazenar notas: assignedGrade, que é a nota informada aos estudantes, e draftGrade, que é uma nota provisória visível apenas para os professores. Esses campos são atualizados usando courses.courseWork.studentSubmissions.patch com uma máscara de campo contendo os campos apropriados, conforme mostrado no exemplo a seguir.

Java

classroom/snippets/src/main/java/PatchStudentSubmission.java
StudentSubmission studentSubmission = null;
try {
  // Updating the draftGrade and assignedGrade fields for the specific student submission.
  StudentSubmission content =
      service
          .courses()
          .courseWork()
          .studentSubmissions()
          .get(courseId, courseWorkId, id)
          .execute();
  content.setAssignedGrade(90.00);
  content.setDraftGrade(80.00);

  // The updated studentSubmission object is returned with the new draftGrade and assignedGrade.
  studentSubmission =
      service
          .courses()
          .courseWork()
          .studentSubmissions()
          .patch(courseId, courseWorkId, id, content)
          .set("updateMask", "draftGrade,assignedGrade")
          .execute();

  /* Prints the updated student submission. */
  System.out.printf(
      "Updated student submission draft grade (%s) and assigned grade (%s).\n",
      studentSubmission.getDraftGrade(), studentSubmission.getAssignedGrade());
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
            + "not exist.\n",
        courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmission;

Python

studentSubmission = {
  'assignedGrade': 99,
  'draftGrade': 80
}
service.courses().courseWork().studentSubmissions().patch(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    updateMask='assignedGrade,draftGrade',
    body=studentSubmission).execute()

Na interface do Google Sala de Aula, os professores só podem atribuir uma nota quando salvam uma nota temporária. A nota atribuída pode ser devolvida para um aluno. Os aplicativos precisam emular esse comportamento. Seu aplicativo pode avaliar a tarefa de um estudante de duas formas:

  • Atribua apenas o draftGrade. Isso é útil, por exemplo, para permitir que o professor revisar manualmente as notas antes de finalizá-las. Os alunos não podem ver as notas temporárias.

  • Atribua draftGrade e assignedGrade para avaliar totalmente uma atividade.

.

Listar notas atribuídas

É possível listar todas as notas de um item específico do curso explorando a Objeto de resposta do método courses.courseWork.studentSubmissions.list:

Java

classroom/snippets/src/main/java/ListStudentSubmissions.java
  ListStudentSubmissionsResponse response =
      service
          .courses()
          .courseWork()
          .studentSubmissions()
          .list(courseId, courseWorkId)
          .setPageToken(pageToken)
          .execute();

  /* Ensure that the response is not null before retrieving data from it to avoid errors. */
  if (response.getStudentSubmissions() != null) {
    studentSubmissions.addAll(response.getStudentSubmissions());
    pageToken = response.getNextPageToken();
  }
} while (pageToken != null);

if (studentSubmissions.isEmpty()) {
  System.out.println("No student submissions found.");
} else {
  for (StudentSubmission submission : studentSubmissions) {
    System.out.printf(
        "User ID %s, Assigned grade: %s\n",
        submission.getUserId(), submission.getAssignedGrade());
  }
}

Python

response = coursework.studentSubmissions().list(
    courseId=course_id,
    courseWorkId=coursework_id,
    pageSize=10).execute()
submissions.extend(response.get('studentSubmissions', []))

if not submissions:
    print('No student submissions found.')

print('Student Submissions:')
for submission in submissions:
    print(f"Submitted at:"
          f"{(submission.get('userId'), submission.get('assignedGrade'))}")