rubric هو نموذج يمكن للمعلّمين استخدامه عند وضع الدرجات للواجبات التي يرسلها الطلاب. تتيح لك Classroom API التصرف نيابةً عن المعلّم لإدارة نماذج التقييم هذه، بالإضافة إلى قراءة درجات نماذج التقييم في المهام التي يرسلها الطلاب.
الشكل 1. لقطة شاشة لقواعد تقييم نموذجية في مهمة على Classroom
يشرح هذا الدليل المفاهيم الأساسية ووظائف واجهة برمجة التطبيقات Rubrics API. راجِع مقالات مركز المساعدة هذه للتعرّف على البنية العامة لقاعدة التقييم وكيفية التقييم باستخدام قاعدة التقييم في واجهة مستخدم Classroom.
المتطلبات الأساسية
يفترض هذا الدليل أنّك تستوفي الشروط التالية:
- الإصدار 3.8.6 أو الإصدارات الأحدث من Python
- أداة إدارة الحِزم pip
- مشروع على السحابة الإلكترونية من Google Cloud
حساب تعليمي في Google Workspace for Education مع تفعيل Google Classroom وترخيص Google Workspace for Education Plus معيّن له. يمكنك طلب حساب تجريبي محدَّث للمطوِّرين إذا لم يكن لديك حساب.
صف تجريبي يتضمّن حساب طالب تجريبي واحد على الأقل إذا لم يكن لديك صف في Classroom يمكنك استخدامه للاختبار، أنشئ صفًا في واجهة المستخدم وأضِف طالبًا تجريبيًا.
تفويض بيانات اعتماد لتطبيق على الكمبيوتر
لإجراء المصادقة كمستخدم نهائي والوصول إلى بيانات المستخدمين في تطبيقك، عليك إنشاء معرّف عميل واحد أو أكثر من معرّفات عملاء OAuth 2.0. يُستخدم معرّف العميل لتعريف تطبيق واحد على خوادم OAuth من Google. إذا كان تطبيقك يعمل على منصات متعددة، عليك إنشاء معرّف عميل منفصل لكل منصة.
- انتقِل إلى صفحة "بيانات الاعتماد" في Google Cloud ضمن وحدة تحكّم Google Cloud.
- انقر على إنشاء بيانات اعتماد > معرِّف عميل OAuth.
- انقر على نوع التطبيق > تطبيق على الكمبيوتر.
- في حقل الاسم، اكتب اسمًا لبيانات الاعتماد. ولا يظهر هذا الاسم إلا في Google Cloud Console. على سبيل المثال، "عميل Rubrics".
- انقر على إنشاء. تظهر شاشة إنشاء عميل OAuth، تعرض معرّف العميل الجديد وسر العميل.
- انقر على تنزيل JSON، ثم على حسنًا. تظهر بيانات الاعتماد التي تم إنشاؤها حديثًا ضمن "معرّفات عميل OAuth 2.0".
- احفظ ملف JSON الذي تم تنزيله باسم
credentials.json، وانقِل الملف إلى دليل العمل. - انقر على إنشاء بيانات الاعتماد > مفتاح واجهة برمجة التطبيقات واحتفظ بمفتاح واجهة برمجة التطبيقات.
لمزيد من المعلومات، يُرجى الاطّلاع على إنشاء بيانات اعتماد الوصول.
ضبط نطاقات OAuth
بناءً على نطاقات OAuth الحالية في مشروعك، قد تحتاج إلى ضبط نطاقات إضافية.
- انتقِل إلى شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth.
- انقر على تعديل التطبيق > حفظ ومتابعة للانتقال إلى شاشة "نطاقات الوصول".
- انقر على إضافة نطاقات أو إزالتها.
- أضِف النطاقات التالية إذا لم تكن لديك:
https://www.googleapis.com/auth/classroom.coursework.studentshttps://www.googleapis.com/auth/classroom.courses
- بعد ذلك، انقر على "تعديل" > حفظ ومتابعة > حفظ ومتابعة > الرجوع إلى لوحة البيانات.
لمزيد من المعلومات، يُرجى الاطّلاع على مقالة ضبط شاشة طلب موافقة OAuth.
يتيح نطاق classroom.coursework.students إذن القراءة والكتابة في نماذج التقييم (بالإضافة إلى إذن الوصول إلى CourseWork)، ويتيح نطاق classroom.courses إذن القراءة والكتابة في الدورات التدريبية.
يتم إدراج النطاقات المطلوبة لطريقة معيّنة في المستندات المرجعية الخاصة بهذه الطريقة. يمكنك الاطّلاع على نطاقات أذونات courses.courseWork.rubrics.create كمثال. يمكنك الاطّلاع على جميع نطاقات Classroom في نطاقات OAuth 2.0 في Google APIs.
ضبط العيّنة
في دليل العمل، ثبِّت مكتبة عميل Google للغة Python:
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
أنشئ ملفًا باسم main.py ينشئ مكتبة برامج العميل ويمنح المستخدم الإذن باستخدام مفتاح واجهة برمجة التطبيقات بدلاً من 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)
شغِّل النص البرمجي باستخدام python main.py. سيُطلب منك تسجيل الدخول والموافقة على نطاقات OAuth.
إنشاء مهمة
ترتبط قواعد التقييم بمهمة أو CourseWork، ولا تكون ذات صلة إلا في سياق CourseWork. لا يمكن إنشاء نماذج التقييم إلا من خلال مشروع Google Cloud الذي أنشأ CourseWork العنصر الرئيسي. لأغراض هذا الدليل، أنشئ CourseWork مهمة جديدة باستخدام نص برمجي.
أضِف ما يلي إلى 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
الآن، عدِّل main.py لاسترداد course_id لفئة الاختبار التي أنشأتها للتو، وأنشئ مهمة نموذجية جديدة، واستردّ 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.
احفظ course_id وcoursework_id. وهي مطلوبة لجميع عمليات إنشاء وقراءة وتعديل وحذف معايير التقييم.
من المفترض أن تتوفّر لديك الآن عيّنة CourseWork في Classroom.
الشكل 2. عرض لمهمة نموذجية في Classroom
التحقّق من أهلية المستخدم
يتطلّب إنشاء نماذج التقييم وتعديلها أن يكون لدى كل من المستخدم الذي يقدّم الطلب ومالك الدورة التدريبية المعني ترخيص Google Workspace for Education Plus. يتيح Classroom نقطة نهاية للأهلية كي يتمكّن المطوّرون من تحديد الميزات التي يمكن للمستخدم الوصول إليها.
عدِّل main.py ونفِّذه للتأكّد من أنّ حسابك التجريبي لديه إذن الوصول إلى ميزة
نماذج التقييم:
if __name__ == '__main__':
service = build_authenticated_service(YOUR_API_KEY)
capability = service.userProfiles().checkUserCapability(
userId='me',
# Specify the preview version. checkUserCapability is
# supported in V1_20240930_PREVIEW and later.
previewVersion="V1_20240930_PREVIEW",
capability="CREATE_RUBRIC").execute()
if not capability.get('allowed'):
print('User ineligible for rubrics creation.')
# TODO(developer): in a production app, this signal could be used to
# proactively hide any rubrics related features from users or encourage
# them to upgrade to the appropriate license.
else:
print('User eligible for rubrics creation.')
إنشاء قواعد تقييم
أنت الآن جاهز لبدء إدارة نماذج التقييم.
يمكن إنشاء قواعد تقييم في CourseWork باستخدام طلب create() يتضمّن عنصر قواعد التقييم الكامل، حيث يتم حذف سمات المعرّف الخاصة بالمعايير والمستويات (يتم إنشاء هذه السمات عند الإنشاء).
أضِف الدالة التالية إلى 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
).execute()
print(f"Rubric created with ID {rubric.get('id')}")
return rubric
except HttpError as error:
print(f"An error occurred: {error}")
return error
بعد ذلك، عدِّل main.py وشغِّله لإنشاء نموذج لقواعد التقييم باستخدام معرّفَي Course وCourseWork من الخطوات السابقة:
if __name__ == '__main__':
service = build_authenticated_service(YOUR_API_KEY)
capability = service.userProfiles().checkUserCapability(
userId='me',
# Specify the preview version. checkUserCapability is
# supported in V1_20240930_PREVIEW and later.
previewVersion="V1_20240930_PREVIEW",
capability="CREATE_RUBRIC").execute()
if not capability.get('allowed'):
print('User ineligible for rubrics creation.')
# TODO(developer): in a production app, this signal could be used to
# proactively hide any rubrics related features from users or encourage
# them to upgrade to the appropriate license.
else:
rubric = create_rubric(service, YOUR_COURSE_ID, YOUR_COURSEWORK_ID)
print(json.dumps(rubric, indent=4))
في ما يلي بعض النقاط حول طريقة عرض قواعد التقييم:
- يظهر ترتيب المعايير والمستويات في واجهة مستخدم Classroom.
- يجب ترتيب المستويات التي تم تسجيل نقاط فيها (تلك التي تتضمّن السمة
points) حسب النقاط بترتيب تصاعدي أو تنازلي (لا يمكن ترتيبها بشكل عشوائي). - يمكن للمعلّمين إعادة ترتيب المعايير والمستويات التي تم تسجيلها (ولكن ليس المستويات التي لم يتم تسجيلها) في واجهة المستخدم، ويؤدي ذلك إلى تغيير ترتيبها في البيانات.
اطّلِع على القيود لمعرفة المزيد من التحذيرات بشأن بنية نماذج التقييم.
في واجهة المستخدم، من المفترض أن يظهر نموذج التقييم في المهمة.
الشكل 3. عرض نموذج لقواعد التقييم في مهمة على Classroom
قراءة قواعد التقييم
يمكن قراءة نماذج التقييم باستخدام الطريقتَين العاديتَين list() وget().
يمكن أن تتضمّن المهمة قواعد تقييم واحدة على الأكثر، لذا قد يبدو استخدام list() غير منطقي، ولكنّه مفيد إذا لم يكن لديك رقم تعريف قواعد التقييم. إذا لم تكن هناك قاعدة تقييم مرتبطة بـ CourseWork، سيكون الردّ list() فارغًا.
أضِف الدالة التالية إلى 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
).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
عدِّل main.py وشغِّله لجلب قواعد التقييم التي أضفتها:
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.
دوِّن السمة id في قواعد التقييم للخطوات اللاحقة.
تعمل ميزة Get() بشكل جيد عندما يكون لديك معرّف نموذج التقييم. قد يبدو استخدام get() في الدالة
بدلاً من ذلك على النحو التالي:
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
).execute()
return rubric
except HttpError as error:
print(f"An error occurred: {error}")
return error
تعرض هذه العملية رمز الحالة 404 إذا لم تكن هناك قاعدة تقييم.
تعديل قواعد تقييم
يتم إجراء التعديلات على قواعد التقييم باستخدام طلبات patch(). بسبب البنية المعقّدة لنموذج التقييم، يجب إجراء التعديلات باستخدام نمط القراءة والتعديل والكتابة، حيث يتم استبدال السمة criteria بأكملها.
في ما يلي قواعد التعديل:
- تُعتبر المعايير أو المستويات التي تتم إضافتها بدون رقم تعريف إضافات.
- تُعتبر المعايير أو المستويات التي لم تعُد متوفّرة عمليات حذف.
- تُعتبر المعايير أو المستويات التي تتضمّن معرّفًا حاليًا ولكن بيانات معدَّلة تعديلات. تبقى المواقع التي لم يتم تعديلها كما هي.
- تُعد المعايير أو المستويات التي يتم تقديمها مع معرّفات جديدة أو غير معروفة أخطاء.
- يُعدّ ترتيب المعايير والمستويات الجديدة هو ترتيب واجهة المستخدم الجديدة (مع القيود المذكورة أعلاه).
أضِف دالة لتعديل قواعد التقييم:
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'
).execute()
return rubric
except HttpError as error:
print(f"An error occurred: {error}")
return error
في هذا المثال، تم تحديد الحقل criteria للتعديل باستخدام
updateMask.
بعد ذلك، عدِّل main.py لإجراء تغيير لكل قاعدة من قواعد التعديل المذكورة أعلاه:
if __name__ == '__main__':
service = build_authenticated_service(YOUR_API_KEY)
capability = service.userProfiles().checkUserCapability(
userId='me',
# Specify the preview version. checkUserCapability is
# supported in V1_20240930_PREVIEW and later.
previewVersion="V1_20240930_PREVIEW",
capability="CREATE_RUBRIC").execute()
if not capability.get('allowed'):
print('User ineligible for rubrics creation.')
# TODO(developer): in a production app, this signal could be used to
# proactively hide any rubrics related features from users or encourage
# them to upgrade to the appropriate license.
else:
# 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))
من المفترض أن تظهر التغييرات الآن للمعلّم في Classroom.
الشكل 4. عرض قاعدة التقييم المعدَّلة
عرض المهام التي تم منحها درجات باستخدام قواعد التقييم
في الوقت الحالي، لا يمكن منح درجات لإرسالات الطلاب باستخدام قواعد التقييم من خلال واجهة برمجة التطبيقات، ولكن يمكنك الاطّلاع على درجات قواعد التقييم للإرسالات التي تم منحها درجات باستخدام قواعد التقييم في واجهة مستخدم Classroom.
بصفتك طالبًا في واجهة مستخدم Classroom، أكمل الواجب النموذجي وسلِّمه. بعد ذلك، بصفتك المعلّم، يمكنك وضع درجة للواجب يدويًا باستخدام قواعد التقييم.
الشكل 5. عرض المعلّم لقواعد التقييم أثناء وضع الدرجات
StudentSubmissions التي تم وضع درجات لها باستخدام نموذج تقييم تتضمّن سمتَين جديدتَين: draftRubricGrades وassignedRubricGrades، وهما تمثّلان النقاط والمستويات التي اختارها المعلّم أثناء حالات وضع الدرجات في المسودة والواجب، على التوالي.
يمكنك استخدام الطريقتَين studentSubmissions.get() وstudentSubmissions.list() الحالتَين لعرض المهام التي تم تقييمها.
أضِف الدالة التالية إلى main.py لإدراج المهام التي سلّمها الطلاب:
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
).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
بعد ذلك، عدِّل main.py ونفِّذه للاطّلاع على درجات المهام التي تم إرسالها.
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))
يتضمّن draftRubricGrades وassignedRubricGrades ما يلي:
- تمثّل هذه السمة
criterionIdمعايير قواعد التقييم المقابلة. pointsالتي حدّدها المعلّم لكل معيار قد يكون ذلك من المستوى المحدّد، ولكن قد يكون المعلّم قد ألغى هذا المستوى.levelIdالمستوى الذي تم اختياره لكل معيار إذا لم يحدّد المعلّم مستوى، لكنّه خصّص نقاطًا للمعيار، لن يظهر هذا الحقل.
لا تحتوي هذه القوائم إلا على إدخالات للمعايير التي اختار فيها المعلّم مستوى أو ضبط نقاط. على سبيل المثال، إذا اختار المعلّم التفاعل مع معيار واحد فقط أثناء وضع الدرجات، سيحتوي draftRubricGrades وassignedRubricGrades على عنصر واحد فقط، حتى إذا كانت قواعد التقييم تتضمّن العديد من المعايير.
حذف قواعد تقييم
يمكن حذف نموذج التقييم باستخدام طلب delete() عادي. يعرض الرمز التالي مثالاً على دالة اكتمال، ولكن بما أنّ عملية وضع الدرجات قد بدأت، لا يمكنك حذف قواعد التقييم الحالية:
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
).execute()
except HttpError as error:
print(f"An error occurred: {error}")
return error
تصدير قواعد التقييم واستيرادها
يمكن تصدير نماذج التقييم يدويًا إلى "جداول بيانات Google" ليتمكن المعلّمون من إعادة استخدامها.
بالإضافة إلى تحديد معايير قواعد التقييم في الرمز، يمكن إنشاء قواعد التقييم وتعديلها من جداول البيانات التي تم تصديرها من خلال تحديد sourceSpreadsheetId في نص قاعدة التقييم بدلاً من 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
).execute()
print(f"Rubric created with ID {rubric.get('id')}")
return rubric
except HttpError as error:
print(f"An error occurred: {error}")
return error