첨부파일 성적 및 성적 패스백

클래스룸 부가기능의 여섯 번째 둘러보기입니다. 오신 것을 환영합니다

이 둘러보기에서는 이전 둘러보기 단계의 예를 수정합니다. 채점된 활동 유형 첨부파일을 생성합니다. 또한 성적을 돌려받을 수 있습니다. Google 클래스룸에 전송합니다. 이는 교사의 성적에 표시됩니다. 임시 성적으로 제출할 수 있습니다.

이 둘러보기는 시리즈의 다른 부분과 약간 다릅니다. 다음 두 가지 방법을 통해 클래스룸. 둘 다 개발자와 사용자에게 뚜렷한 영향을 미칩니다. 경험 클래스룸 부가기능을 설계할 때 두 가지를 모두 고려하세요 다음 항목에 대한 자세한 내용은 첨부파일과 상호작용 가이드 페이지를 참조하세요. 구현 옵션을 살펴보겠습니다.

API의 평가 기능은 선택사항입니다. 이러한 포드는 모든 활동 유형 첨부파일.

이 둘러보기 과정에서 다음을 완료합니다.

  • 이전 첨부파일 생성 요청을 Classroom API를 사용하여 첨부파일의 성적 분모도 설정할 수 있습니다.
  • 프로그래매틱 방식으로 학생의 제출물에 점수를 매기고 첨부파일의 학년 분자.
  • 두 가지 접근 방식을 구현하여 제출물의 성적을 로그인 또는 오프라인 교사 사용자 인증 정보를 사용하는 클래스룸

완료되면 패스백 동작이 트리거됩니다 이 상황이 발생하는 정확한 시점은 구현 방법을 살펴보겠습니다

이 예에서는 이전 둘러보기는 학생에게 유명한 명소의 이미지를 보여주고 이름을 입력하라는 메시지가 표시됩니다. 학생이 올바른 이름을 입력합니다. 그렇지 않으면 0을 입력합니다.

클래스룸 부가기능 API 평가 기능 이해하기

부가기능은 첨부 파일 이는 각각 pointsEarnedmaxPoints를 사용하여 설정됩니다. 값을 제공합니다. 클래스룸 UI의 첨부파일 카드에 설정된 경우 maxPoints 값입니다.

maxPoints가 하나인 여러 첨부파일의 예
할당

그림 1. 과제 만들기 UI에는 maxPoints가 설정되어 있어야 합니다.

클래스룸 부가기능 API를 사용하면 클래스룸 부가기능 API에 대한 설정을 첨부파일 성적으로 받은 점수 이것들은 과제 성적을 거두는 방법을 알아봅니다. 하지만 과제 성적 설정은 성적 동기화 라벨이 설정된 첨부파일의 첨부파일 성적 설정 첨부 파일 카드를 선택합니다. '성적 동기화' 다음의 첨부파일 세트 pointsEarned개가 이는 과제에 대한 학생의 임시 성적도 설정합니다.

일반적으로 maxPoints에서 '성적 동기화'를 수신함 라벨을 지정합니다. 과제 만들기 UI 보기 '성적 동기화'의 예에 대한 그림 1의 예 라벨을 지정합니다. 참고: '첨부파일 1' 카드에 '성적 동기화'가 있음 과제 성적이 가 50포인트로 업데이트되었습니다. 그림 1에서는 첨부파일 카드 3개가 표시되며 카드 1개에만 '성적 동기화'가 표시됨 라벨을 지정합니다. 이것은 현재 구현의 주요 제한사항: 하나의 첨부파일만 '성적 동기화' 라벨과 함께 사용할 수 있습니다.

maxPoints가 설정된 첨부파일이 여러 개인 경우 '성적 동기화'가 포함된 첨부파일 '성적 동기화'를 사용 설정하지 않음 다음 중 아무거나 나머지 첨부파일은 확인할 수 없습니다 maxPoints를 설정하는 다른 첨부파일을 추가하면 사용 설정됩니다. 새 첨부파일에서 성적이 동기화되고 최대 과제 성적이 조정됨 일치해야 합니다. 어떤 첨부파일이 포함되었는지 프로그래매틱 방식으로 확인할 수 있는 메커니즘은 "성적 동기화" 특정 과제에 몇 개의 첨부파일이 있는지 확인할 수 없습니다.

첨부파일의 최대 성적 설정하기

이 섹션에서는 첨부파일 성적의 분모 설정에 대해 설명합니다. 저것 모든 학생이 자신의 학습 시간에 달성할 수 있는 있습니다. 이렇게 하려면 첨부파일의 maxPoints 값을 설정합니다.

기존 구현을 약간만 수정하면 기능을 살펴보겠습니다 첨부파일을 만들 때 maxPoints 값을 studentWorkReviewUri가 포함된 동일한 AddOnAttachment 객체 teacherViewUri 및 기타 첨부파일 필드가 있습니다.

새 과제의 기본 최대 점수는 100점입니다. 권장 조치 maxPoints를 100이 아닌 다른 값으로 설정하여 성적이 올바르게 설정되고 있는지 확인합니다. 다음과 같이 maxPoints를 50으로 설정합니다.

Python

attachment 객체를 구성할 때 maxPoints 필드를 추가합니다. 100%를 반환하는 CREATE 요청을 courses.courseWork.addOnAttachments 엔드포인트. 이 내용은 제공된 예를 따르는 경우 webapp/attachment_routes.py 파일

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # Sets the maximum points that a student can earn for this activity.
    # This is the denominator in a fractional representation of a grade.
    "maxPoints": 50,
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

이 데모에서는 maxPoints 값을 다음 위치에도 저장합니다. 로컬 첨부파일 데이터베이스 이렇게 하면 추가 API를 호출할 필요가 없으며 나중에 학생 제출물을 채점할 때 하지만 Ad Manager 360에서 교사는 부가기능과 상관없이 과제 성적 설정을 변경할 수 있습니다. 보내기 courses.courseWork 엔드포인트에 대한 GET 요청을 전송하여 할당 수준 maxPoints 값입니다. 이 때 itemId CourseWork.id 필드

이제 연결의 maxPoints 값도 포함하도록 데이터베이스 모델을 업데이트합니다. CREATE 응답의 maxPoints 값을 사용하는 것이 좋습니다.

Python

먼저 Attachment 테이블에 max_points 필드를 추가합니다. 여기에서 제공된 예에 따르는 경우 webapp/models.py 파일에 포함됩니다.

# Database model to represent an attachment.
class Attachment(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The image filename to store.
    image_filename = db.Column(db.String(120))

    # The image caption to store.
    image_caption = db.Column(db.String(120))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

courses.courseWork.addOnAttachments CREATE 요청으로 돌아갑니다. 스토어 응답에서 반환된 maxPoints 값입니다.

new_attachment = Attachment(
    # The new attachment's unique ID, returned in the CREATE response.
    attachment_id=resp.get("id"),
    image_filename=key,
    image_caption=value,
    # Store the maxPoints value returned in the response.
    max_points=int(resp.get("maxPoints")))
db.session.add(new_attachment)
db.session.commit()

이제 첨부파일에 최대 등급이 지정되었습니다. 이 동작을 테스트할 수 있어야 합니다. 이제 새 과제에 첨부파일을 추가하고 첨부파일 카드가 '성적 동기화'가 표시됩니다. 라벨 및 과제의 '점수' 값이 변경됩니다.

클래스룸에서 학생 제출 성적 설정하기

이 섹션에서는 첨부파일 성적의 분자 설정에 대해 설명합니다. 즉, 개별 학생의 첨부파일 점수 이렇게 하려면 학생을 제출의 pointsEarned 값입니다.

이제 부가기능을 어떻게 해결해야 하는지에 대한 중요한 결정을 내릴 수 있습니다. pointsEarned 설정을 요청할까요?

문제는 pointsEarned 설정 시 teacher OAuth 범위가 필요하다는 점입니다. 학생 사용자에게 teacher 범위를 부여하면 안 됩니다. 이로 인해 학생이 부가기능과 상호작용할 때 학생 보기 iframe 대신 교사 보기 iframe. 따라서 pointsEarned 설정 방법은 다음과 같습니다.

  • 로그인한 교사의 사용자 인증 정보 사용
  • 저장된 (오프라인) 교사 사용자 인증 정보를 사용합니다.

다음 섹션에서는 각 접근 방식의 장단점을 각 구현을 시연할 수 있습니다. 제공된 예제는 클래스룸에 성적을 전달하는 두 가지 접근 방식을 모두 모두 알고 있어야 합니다. 자세한 내용은 언어별 지침을 참조하세요. 다음 명령어를 실행합니다.

Python

상단에서 SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS 선언 찾기 파일 webapp/attachment_routes.py개 이 값을 True로 설정하여 뒤로 전달합니다. 성적을 매깁니다. 이 값을 False로 설정합니다. 저장된 사용자 인증 정보를 사용하여 성적을 돌려줄 수 있습니다. 있습니다.

로그인한 교사의 사용자 인증 정보를 사용하여 성적 설정하기

로그인한 사용자의 사용자 인증 정보를 사용하여 pointsEarned 설정 요청을 실행합니다. 나머지 구현 내용을 반영하므로 매우 직관적으로 보입니다. 실현하는 데 큰 노력이 필요하지 않습니다

하지만 교사가 학생의 학생과 상호작용한다고 생각해 보세요. 학생 과제물 검토 iframe에 제출하세요. 여기에는 몇 가지 중요한 의미:

  • 교사가 다음 채점을 완료할 때까지 클래스룸에 성적이 입력되지 않음 클래스룸 UI에서 수행할 수 있습니다.
  • 교사는 학생 과제물을 모두 채우기 위해 모든 학생 제출물을 열어야 할 수도 있습니다. 학생 성적
  • 클래스룸에서 성적을 받기까지 약간의 지연이 있습니다. 클래스룸 UI에서 어떻게 표시되는지 살펴보겠습니다. 지연 시간: 일반적으로 5~10초이지만 최대 30초까지 걸릴 수 있습니다

이러한 요인이 복합적으로 작용해 교사는 학급의 성적을 모두 채우는 데 상당한 시간과 시간이 드는 수동 작업을 해야 했습니다.

이 방법을 구현하려면 기존 학생에 API 호출을 하나 더 추가하세요. 작업 검토 라우트

학생 제출물 및 첨부파일 기록을 가져온 후 저장하고 결과 성적을 저장합니다. 성적을 설정하려면 AddOnAttachmentStudentSubmission 객체pointsEarned 필드 마지막으로, PATCH 요청을 courses.courseWork.addOnAttachments.studentSubmissions 엔드포인트를 요청 본문에 AddOnAttachmentStudentSubmission 인스턴스를 추가합니다. 참고: 또한 PATCH 요청의 updateMask에서 pointsEarned를 지정해야 합니다.

Python

# Look up the student's submission in our database.
student_submission = Submission.query.get(flask.session["submissionId"])

# Look up the attachment in the database.
attachment = Attachment.query.get(student_submission.attachment_id)

grade = 0

# See if the student response matches the stored name.
if student_submission.student_response.lower(
) == attachment.image_caption.lower():
    grade = attachment.max_points

# Create an instance of the Classroom service.
classroom_service = ch._credential_handler.get_classroom_service()

# Build an AddOnAttachmentStudentSubmission instance.
add_on_attachment_student_submission = {
    # Specifies the student's score for this attachment.
    "pointsEarned": grade,
}

# Issue a PATCH request to set the grade numerator for this attachment.
patch_grade_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

오프라인 교사 사용자 인증 정보를 사용하여 성적 설정하기

성적을 설정하는 두 번째 접근 방식은 저장된 사용자 인증 정보를 사용해야 합니다. 첨부파일을 만든 교사에게 문의하세요. 이 구현을 위해서는 이전에 승인된 교사의 새로고침 및 액세스 토큰을 생성한 다음 이 사용자 인증 정보를 사용하여 pointsEarned를 설정합니다.

이 접근 방식의 중요한 장점은 입력하지 않고도 성적을 입력할 수 있다는 점입니다. 클래스룸 UI에서 교사의 조치로 문제 방지 위에서 언급했습니다. 그 결과 최종 사용자가 평가 환경을 인식하고 원활하고 효율적입니다 또한 이 방법을 사용하면 성적을 돌려주는 순간입니다. 예를 들어 비동기식으로 작동합니다

이 접근 방식을 구현하려면 다음 작업을 완료하세요.

  1. 사용자 데이터베이스 레코드를 수정하여 액세스 토큰을 저장합니다.
  2. 교사 ID를 저장하도록 첨부파일 데이터베이스 레코드를 수정합니다.
  3. 교사의 사용자 인증 정보를 가져오고 필요한 경우 새 클래스룸 서비스 인스턴스입니다.
  4. 제출물의 성적을 설정합니다.

이 데모에서는 학생이 완료한 과제의 성적을 설정합니다. 활동 즉, 학생이 학생 뷰 창에서 양식을 제출하면 있습니다.

사용자 데이터베이스 레코드를 수정하여 액세스 토큰 저장

API를 호출하려면 두 가지 고유 토큰(갱신 토큰액세스 토큰에 대해 자세히 알아보세요. 지금까지 둘러보기 시리즈를 따라해 보셨다면 User 테이블 스키마가 이미 갱신 토큰을 저장해야 합니다. 새로고침 저장 토큰으로는 로그인한 사용자에 의해서만 API를 호출할 수 있습니다. 인증 흐름의 일부로 액세스 토큰을 받게 됩니다.

하지만 이제 로그인한 사용자가 아닌 다른 사람으로 전화를 걸어야 합니다. 인증 흐름을 사용할 수 없습니다 따라서 다음과 같이 액세스 토큰을 새로고침할 수 있습니다 User 테이블 스키마를 다음으로 업데이트합니다. 액세스 토큰을 포함할 수 있습니다.

Python

제공된 예에서는 webapp/models.py 파일에 있습니다.

# Database model to represent a user.
class User(db.Model):
    # The user's identifying information:
    id = db.Column(db.String(120), primary_key=True)
    display_name = db.Column(db.String(80))
    email = db.Column(db.String(120), unique=True)
    portrait_url = db.Column(db.Text())

    # The user's refresh token, which will be used to obtain an access token.
    # Note that refresh tokens will become invalid if:
    # - The refresh token has not been used for six months.
    # - The user revokes your app's access permissions.
    # - The user changes passwords.
    # - The user belongs to a Google Cloud organization
    #   that has session control policies in effect.
    refresh_token = db.Column(db.Text())

    # An access token for this user.
    access_token = db.Column(db.Text())

그런 다음 User 레코드를 만들거나 업데이트하는 코드를 업데이트하여 액세스 토큰:

Python

제공된 예에서는 webapp/credential_handler.py 파일에 있습니다.

def save_credentials_to_storage(self, credentials):
    # Issue a request for the user's profile details.
    user_info_service = googleapiclient.discovery.build(
        serviceName="oauth2", version="v2", credentials=credentials)
    user_info = user_info_service.userinfo().get().execute()
    flask.session["username"] = user_info.get("name")
    flask.session["login_hint"] = user_info.get("id")

    # See if we have any stored credentials for this user. If they have used
    # the add-on before, we should have received login_hint in the query
    # parameters.
    existing_user = self.get_credentials_from_storage(user_info.get("id"))

    # If we do have stored credentials, update the database.
    if existing_user:
        if user_info:
            existing_user.id = user_info.get("id")
            existing_user.display_name = user_info.get("name")
            existing_user.email = user_info.get("email")
            existing_user.portrait_url = user_info.get("picture")

        if credentials and credentials.refresh_token is not None:
            existing_user.refresh_token = credentials.refresh_token
            # Update the access token.
            existing_user.access_token = credentials.token

    # If not, this must be a new user, so add a new entry to the database.
    else:
        new_user = User(
            id=user_info.get("id"),
            display_name=user_info.get("name"),
            email=user_info.get("email"),
            portrait_url=user_info.get("picture"),
            refresh_token=credentials.refresh_token,
            # Store the access token as well.
            access_token=credentials.token)

        db.session.add(new_user)

    db.session.commit()

교사 ID를 저장하도록 첨부파일 데이터베이스 레코드 수정

활동의 성적을 설정하려면 pointsEarned를 담당하고 있습니다. 다음과 같은 여러 가지 방법이 있습니다.

  • 교사 사용자 인증 정보의 로컬 매핑을 강의 ID에 저장합니다. 하지만 같은 교사가 특정 과정과 연결되지 않을 수도 있습니다.
  • Classroom API courses 엔드포인트에 대한 GET 요청을 실행하여 다음을 수행합니다. 현재 교사를 가져옵니다. 그런 다음 로컬 사용자 레코드를 쿼리하여 일치하는 교사의 인증 정보를 찾습니다.
  • 부가기능 첨부파일을 만들 때 교사 ID를 로컬 첨부 파일 데이터베이스를 생성할 수 있습니다 그런 다음 attachmentId가 학생 뷰 iframe으로 전달되었습니다.

이 예는 학생이 활동 첨부파일을 완료합니다.

데이터베이스의 Attachment 테이블에 교사 ID 필드를 추가합니다.

Python

제공된 예에서는 webapp/models.py 파일에 있습니다.

# Database model to represent an attachment.
class Attachment(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The image filename to store.
    image_filename = db.Column(db.String(120))

    # The image caption to store.
    image_caption = db.Column(db.String(120))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

    # The ID of the teacher that created the attachment.
    teacher_id = db.Column(db.String(120))

그런 다음 Attachment 레코드를 만들거나 업데이트하는 코드를 크리에이터 ID 저장:

Python

제공된 예에서는 다음 URL의 create_attachments 메서드에 있습니다. webapp/attachment_routes.py 파일.

# Store the attachment by id.
new_attachment = Attachment(
    # The new attachment's unique ID, returned in the CREATE response.
    attachment_id=resp.get("id"),
    image_filename=key,
    image_caption=value,
    max_points=int(resp.get("maxPoints")),
    teacher_id=flask.session["login_hint"])
db.session.add(new_attachment)
db.session.commit()

교사의 사용자 인증 정보 가져오기

학생 보기 iframe을 게재하는 경로를 찾습니다. 저장 직후 로컬 데이터베이스에서 학생의 응답을 검색하고 교사의 사용자 인증 정보를 가져옵니다. 이는 준비에 대해 알아봤습니다 또한 이를 사용하여 새로운 클래스룸 서비스의 인스턴스:

Python

제공된 예에서는 load_activity_attachment 메서드에 있습니다. webapp/attachment_routes.py 파일

# Create an instance of the Classroom service using the tokens for the
# teacher that created the attachment.

# We're assuming that there are already credentials in the session, which
# should be true given that we are adding this within the Student View
# route; we must have had valid credentials for the student to reach this
# point. The student credentials will be valid to construct a Classroom
# service for another user except for the tokens.
if not flask.session.get("credentials"):
    raise ValueError(
        "No credentials found in session for the requested user.")

# Make a copy of the student credentials so we don't modify the original.
teacher_credentials_dict = deepcopy(flask.session.get("credentials"))

# Retrieve the requested user's stored record.
teacher_record = User.query.get(attachment.teacher_id)

# Apply the user's tokens to the copied credentials.
teacher_credentials_dict["refresh_token"] = teacher_record.refresh_token
teacher_credentials_dict["token"] = teacher_record.access_token

# Construct a temporary credentials object.
teacher_credentials = google.oauth2.credentials.Credentials(
    **teacher_credentials_dict)

# Refresh the credentials if necessary; we don't know when this teacher last
# made a call.
if teacher_credentials.expired:
    teacher_credentials.refresh(Request())

# Request the Classroom service for the specified user.
teacher_classroom_service = googleapiclient.discovery.build(
    serviceName=CLASSROOM_API_SERVICE_NAME,
    version=CLASSROOM_API_VERSION,
    credentials=teacher_credentials)

제출물 성적 설정하기

이 과정은 로그인한 교사의 사용자 인증 정보를 제공합니다. 하지만 선생님과 통화해야 합니다. 사용자 인증 정보:

Python

# Issue a PATCH request as the teacher to set the grade numerator for this
# attachment.
patch_grade_response = teacher_classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

부가기능 테스트

이전 둘러보기와 마찬가지로 활동 유형으로 할당 만들기 첨부파일을 선생님으로 제출하고 학생으로 답변을 제출한 다음 학생 과제물 검토 iframe에 제출하세요. 이제 다음과 같이 구현 방식에 따라 다른 시점에 표시됩니다.

  • 학생이 활동을 완료했을 때 성적을 돌려주도록 선택하면 임시 성적을 확인할 수 있습니다. 학생 과제물 검토 iframe. 다음 경우에 학생 목록에서도 확인할 수 있습니다. '성적' 탭에서 학생 제출물 옆의 체크박스 iframe을 검토합니다.
  • 교사가 학생 과제물을 열 때 성적을 돌려주는 경우 iframe을 검토합니다. 성적이 '성적'에 표시됩니다. 상자에 iframe이 로드됩니다. 위에서 언급한 것처럼 최대 30초가 걸릴 수 있습니다. 그러면 특정 학생의 성적도 기타 클래스룸 성적 기록 보기

학생에게 올바른 점수가 표시되는지 확인합니다.

축하합니다. 이제 다음 단계(첨부파일 만들기)를 진행할 준비가 되었습니다. 학습할 수 있습니다.