Bắt đầu sử dụng tiêu chí chấm điểm

rubric là một mẫu mà giáo viên có thể sử dụng khi chấm điểm bài tập mà học viên nộp. API Lớp học cho phép bạn hành động thay mặt giáo viên để quản lý các tiêu chí chấm điểm này.

Chế độ xem tiêu chí chấm điểm trong giao diện người dùng Lớp học Hình 1. Xem tiêu chí chấm điểm mẫu cho một bài tập trong Lớp học.

Hướng dẫn này giải thích các khái niệm và chức năng cơ bản của Rubrics API. Hãy xem các bài viết này trong Trung tâm trợ giúp để tìm hiểu về cấu trúc chung của tiêu chí chấm điểm và cách chấm điểm trong giao diện người dùng Lớp học.

Điều kiện tiên quyết

Hướng dẫn này giả định rằng bạn có:

Cấp phép thông tin xác thực cho ứng dụng dành cho máy tính

Để xác thực với tư cách người dùng cuối và truy cập vào dữ liệu người dùng trong ứng dụng, bạn cần tạo một hoặc nhiều Mã ứng dụng khách OAuth 2.0. Mã ứng dụng khách được dùng để xác định một ứng dụng cho các máy chủ OAuth của Google. Nếu ứng dụng của bạn chạy trên nhiều nền tảng, bạn phải tạo một mã ứng dụng khách riêng cho từng nền tảng.

  1. Chuyển đến trang Thông tin xác thực của GCP trong bảng điều khiển Google Cloud.
  2. Nhấp vào Tạo thông tin xác thực > Mã ứng dụng khách OAuth.
  3. Nhấp vào Loại ứng dụng > Ứng dụng dành cho máy tính.
  4. Trong trường Tên, hãy nhập tên cho thông tin xác thực. Tên này chỉ xuất hiện trong bảng điều khiển Google Cloud. Ví dụ: "Ứng dụng xem trước tiêu chí chấm điểm".
  5. Nhấp vào Tạo. Màn hình tạo ứng dụng OAuth sẽ xuất hiện, hiển thị Mã ứng dụng khách và Mật khẩu ứng dụng mới của bạn.
  6. Nhấp vào Tải JSON xuống, sau đó nhấp vào OK. Thông tin xác thực mới tạo sẽ xuất hiện trong Mã ứng dụng khách OAuth 2.0.
  7. Lưu tệp JSON đã tải xuống dưới dạng credentials.json rồi di chuyển tệp này vào thư mục đang làm việc.
  8. Nhấp vào Tạo thông tin xác thực > Khoá API và ghi lại khoá API.

Hãy xem bài viết Tạo thông tin xác thực quyền truy cập để tìm hiểu thêm.

Định cấu hình phạm vi OAuth

Tuỳ thuộc vào các phạm vi OAuth hiện có của dự án, bạn có thể cần phải định cấu hình các phạm vi bổ sung.

  1. Chuyển đến màn hình xin phép bằng OAuth.
  2. Nhấp vào Chỉnh sửa ứng dụng > Lưu và tiếp tục để chuyển đến màn hình Phạm vi.
  3. Nhấp vào Thêm hoặc xoá phạm vi.
  4. Thêm các phạm vi sau nếu bạn chưa có:
    • https://www.googleapis.com/auth/classroom.coursework.students
    • https://www.googleapis.com/auth/classroom.courses
  5. Sau đó, Nhấp vào Cập nhật > Lưu và tiếp tục > Lưu và tiếp tục > Quay lại Trang tổng quan.

Xem bài viết Định cấu hình màn hình xin phép bằng OAuth để tìm hiểu thêm.

Phạm vi classroom.coursework.students cho phép đọc và ghi vào tiêu chí chấm điểm (cùng với quyền truy cập vào CourseWork), còn phạm vi classroom.courses cho phép đọc và ghi các khoá học.

Phạm vi cần thiết cho một phương thức nhất định được liệt kê trong tài liệu tham khảo về phương thức đó. Xem ví dụ về phạm vi uỷ quyền courses.courseWork.rubrics.create. Bạn có thể xem tất cả các phạm vi Lớp học trong mục Phạm vi OAuth 2.0 cho API Google. Tiêu chí chấm điểm không được đề cập ở đây vì API vẫn đang trong giai đoạn xem trước.

Định cấu hình mẫu

Trong thư mục đang làm việc, hãy cài đặt thư viện ứng dụng Google cho Python:

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

Tạo một tệp có tên là main.py để xây dựng thư viện ứng dụng và uỷ quyền cho người dùng, bằng cách sử dụng khoá API của bạn thay cho 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)

Chạy tập lệnh bằng python main.py. Bạn sẽ được nhắc đăng nhập và đồng ý sử dụng phạm vi OAuth.

Tạo bài tập

Tiêu chí chấm điểm liên kết với một bài tập (CourseWork) và chỉ có ý nghĩa trong bối cảnh của CourseWork đó. Chỉ có thể tạo tiêu chí chấm điểm bằng dự án Google Cloud đã tạo mục CourseWork mẹ. Để đạt được mục đích của hướng dẫn này, hãy tạo một bài tập CourseWork mới bằng một tập lệnh.

Thêm phần sau vào 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

Bây giờ, hãy cập nhật main.py để truy xuất course_id của lớp kiểm thử bạn vừa tạo, tạo một bài tập mẫu mới và truy xuất coursework_id của bài tập đó:

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.

Lưu course_idcoursework_id. Các tiêu chí này là cần thiết cho tất cả các thao tác CRUD theo tiêu chí chấm điểm.

Bây giờ, bạn sẽ có một CourseWork mẫu trong Lớp học.

Chế độ xem một bài tập trong giao diện người dùng của Lớp học Hình 2. Chế độ xem một bài tập mẫu trong Lớp học.

Tạo tiêu chí chấm điểm

Giờ bạn đã có thể bắt đầu quản lý tiêu chí chấm điểm.

Bạn có thể tạo tiêu chí chấm điểm trên CourseWork bằng lệnh gọi Create chứa đối tượng tiêu chí chấm điểm đầy đủ, trong đó các thuộc tính mã nhận dạng cho tiêu chí và cấp độ bị bỏ qua (các thuộc tính này được tạo khi tạo).

Thêm hàm sau vào 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

Sau đó, hãy cập nhật và chạy main.py để tạo tiêu chí chấm điểm mẫu, sử dụng mã nhận dạng CourseCourseWork ở phần trước:

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

Một số điểm về cách trình bày theo tiêu chí chấm điểm:

  • Thứ tự tiêu chí và cấp độ được phản ánh trong giao diện người dùng của Lớp học.
  • Các cấp được tính điểm (những cấp có thuộc tính points) phải được sắp xếp theo điểm theo thứ tự tăng dần hoặc giảm dần (không thể sắp xếp ngẫu nhiên).
  • Giáo viên có thể sắp xếp lại các tiêu chí và mức điểm (chứ không phải các mức chưa có điểm) trong giao diện người dùng. Đồng thời, giáo viên có thể thay đổi thứ tự của các tiêu chí trong dữ liệu.

Hãy xem phần giới hạn để biết thêm các cảnh báo về cấu trúc tiêu chí chấm điểm.

Quay lại giao diện người dùng, bạn sẽ thấy tiêu chí chấm điểm cho bài tập.

Chế độ xem tiêu chí chấm điểm trong giao diện người dùng Lớp học Hình 3. Xem tiêu chí chấm điểm mẫu cho một bài tập trong Lớp học.

Đọc tiêu chí chấm điểm

Bạn có thể đọc tiêu chí chấm điểm bằng phương thức ListGet chuẩn.

Mỗi bài tập có thể có tối đa một tiêu chí chấm điểm. Vì vậy, List có vẻ không trực quan, nhưng sẽ hữu ích nếu bạn chưa có mã tiêu chí chấm điểm. Nếu không có tiêu chí chấm điểm nào liên kết với CourseWork, thì phản hồi List sẽ trống.

Thêm hàm sau vào 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

Cập nhật và chạy main.py để tìm nạp tiêu chí chấm điểm mà bạn đã thêm:

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.

Hãy lưu ý thuộc tính id trong tiêu chí chấm điểm để biết các bước sau.

Get hoạt động hiệu quả khi bạn có mã tiêu chí chấm điểm. Thay vào đó, việc sử dụng Get trong hàm có thể có dạng như sau:

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

Cách triển khai này sẽ trả về mã lỗi 404 nếu không có tiêu chí chấm điểm.

Cập nhật tiêu chí chấm điểm

Hệ thống thực hiện cập nhật tiêu chí chấm điểm qua các lệnh gọi Patch. Do cấu trúc phức tạp của tiêu chí chấm điểm, nên các cập nhật phải được thực hiện bằng mẫu đọc sửa đổi-ghi, trong đó toàn bộ thuộc tính criteria được thay thế.

Các quy tắc cập nhật như sau:

  1. Tiêu chí hoặc cấp độ được thêm mà không có mã nhận dạng được coi là bổ sung.
  2. Các tiêu chí hoặc cấp bị thiếu trước đó được coi là xoá.
  3. Tiêu chí hoặc cấp độ có mã nhận dạng hiện có nhưng dữ liệu đã sửa đổi được coi là bản chỉnh sửa. Các thuộc tính chưa sửa đổi sẽ giữ nguyên.
  4. Tiêu chí hoặc cấp độ được cung cấp cùng với mã nhận dạng mới hoặc không xác định được coi là lỗi.
  5. Thứ tự của các tiêu chí và cấp mới được coi là thứ tự giao diện người dùng mới (với các giới hạn nêu trên).

Thêm hàm để cập nhật tiêu chí chấm điểm:

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

Trong ví dụ này, trường criteria được chỉ định để sửa đổi bằng updateMask.

Sau đó, hãy sửa đổi main.py để thực hiện thay đổi cho từng quy tắc cập nhật nêu trên:

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

Lúc này, giáo viên sẽ thấy các thay đổi này trong Lớp học.

Xem tiêu chí chấm điểm mới trong giao diện người dùng của Lớp học Hình 4. Xem tiêu chí chấm điểm mới cập nhật.

Xem bài nộp được chấm điểm theo tiêu chí chấm điểm

Hiện tại, API không thể chấm điểm các bài tập học viên nộp theo tiêu chí chấm điểm, nhưng bạn có thể đọc điểm theo tiêu chí chấm điểm cho các bài tập đã được chấm điểm theo tiêu chí chấm điểm trong giao diện người dùng Lớp học.

Là học viên trong giao diện người dùng của Lớp học, hãy hoàn thành và gửi bài tập mẫu. Sau đó, với tư cách là giáo viên, hãy chấm điểm bài tập theo cách thủ công theo tiêu chí chấm điểm.

Xem điểm theo tiêu chí chấm điểm trong giao diện người dùng Lớp học Hình 5. Chế độ xem của giáo viên đối với tiêu chí chấm điểm.

Bài nộp của học viên được chấm điểm theo tiêu chí chấm điểm sẽ có hai thuộc tính mới: draftRubricGradesassignedRubricGrades, thể hiện điểm và cấp độ do giáo viên chọn trong bản nháp và trạng thái chấm điểm được chỉ định tương ứng.

Ngoài ra, các bài tập mà học viên nộp có tiêu chí chấm điểm liên quan sẽ có trường rubricId, ngay cả trước khi chấm điểm. Đây là tiêu chí chấm điểm mới nhất liên kết với CourseWork và giá trị này có thể thay đổi nếu giáo viên xoá và tạo lại tiêu chí chấm điểm.

Bạn có thể sử dụng phương thức studentSubmissions.GetstudentSubmissions.List hiện có để xem bài tập đã chấm điểm.

Thêm hàm sau vào main.py để liệt kê bài làm của học viên:

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

Sau đó, hãy cập nhật và chạy main.py để xem điểm của bài nộp.

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 chứa:

  • criterionId của tiêu chí chấm điểm tương ứng.
  • points mà giáo viên đã chỉ định cho từng tiêu chí. Thao tác này có thể thuộc cấp độ đã chọn, nhưng giáo viên cũng có thể đã ghi đè cấp độ này.
  • levelId của cấp đã chọn cho từng tiêu chí. Nếu giáo viên không chọn cấp nhưng vẫn chỉ định điểm cho tiêu chí, thì trường này sẽ không xuất hiện.

Các danh sách này chỉ chứa mục nhập cho các tiêu chí mà giáo viên đã chọn một cấp hoặc đặt điểm. Ví dụ: nếu giáo viên chọn chỉ tương tác với một tiêu chí trong quá trình chấm điểm, thì draftRubricGradesassignedRubricGrades sẽ chỉ có một mục, ngay cả khi tiêu chí chấm điểm có nhiều tiêu chí.

Xoá tiêu chí chấm điểm

Bạn có thể xoá tiêu chí chấm điểm bằng một yêu cầu Delete tiêu chuẩn. Mã sau đây cho thấy một hàm mẫu để xác định mức độ hoàn thành. Tuy nhiên, vì quá trình chấm điểm đã bắt đầu, nên bạn không thể xoá tiêu chí chấm điểm hiện tại:

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

Xuất và nhập tiêu chí chấm điểm

Bạn có thể xuất tiêu chí chấm điểm theo cách thủ công sang Google Bảng tính để giáo viên sử dụng lại.

Ngoài việc chỉ định tiêu chí chấm điểm trong mã, bạn còn có thể tạo và cập nhật tiêu chí chấm điểm trên các trang tính đã xuất này bằng cách chỉ định sourceSpreadsheetId trong nội dung tiêu chí chấm điểm thay vì 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

Ý kiến phản hồi

Nếu bạn phát hiện vấn đề hoặc có ý kiến, hãy chia sẻ ý kiến phản hồi của bạn.