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
، وانقل الملف إلى دليل العمل. - انقر على إنشاء بيانات اعتماد > مفتاح API واحتفظ بمفتاح API.
لمزيد من المعلومات، يُرجى الاطّلاع على إنشاء بيانات اعتماد الوصول.
ضبط نطاقات OAuth
بناءً على نطاقات OAuth الحالية في مشروعك، قد تحتاج إلى ضبط نطاقات إضافية.
- انتقِل إلى شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth.
- انقر على تعديل التطبيق > حفظ ومتابعة للانتقال إلى شاشة "نطاقات الوصول".
- انقر على إضافة نطاقات أو إزالتها.
- أضِف النطاقات التالية إذا لم تكن لديك:
https://www.googleapis.com/auth/classroom.coursework.students
https://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