rubric الگویی است که معلمان میتوانند هنگام نمرهدهی به مطالب ارسالی دانشآموزان از آن استفاده کنند. رابط برنامهنویسی کاربردی (API) کلاس درس به شما امکان میدهد تا از طرف معلم، این روبریکها را مدیریت کنید و همچنین نمرات روبریک مطالب ارسالی دانشآموزان را بخوانید.
شکل ۱. نمایی از یک نمونه روبریک در یک تکلیف کلاسی.
این راهنما مفاهیم اولیه و عملکرد API روبریکس را توضیح میدهد. برای آشنایی با ساختار کلی روبریک و نحوهی نمرهدهی روبریک در رابط کاربری کلاس درس، به این مقالات مرکز راهنما مراجعه کنید.
پیشنیازها
این راهنما فرض میکند که شما موارد زیر را دارید:
- پایتون ۳.۸.۶ یا بالاتر
- ابزار مدیریت بسته pip
- یک پروژه ابری گوگل .
- یک حساب کاربری Google Workspace for Education که Google Classroom در آن فعال باشد و مجوز Google Workspace for Education Plus به آن اختصاص داده شده باشد. در صورت نداشتن حساب کاربری، میتوانید درخواست ارتقاء حساب آزمایشی توسعهدهنده را بدهید.
- یک کلاس آزمایشی با حداقل یک حساب کاربری دانشجوی آزمایشی. اگر کلاس Classroom ندارید که بتوانید برای آزمایش از آن استفاده کنید، یکی در رابط کاربری ایجاد کنید و یک دانشجوی آزمایشی اضافه کنید .
اعتبارنامهها را برای یک برنامه دسکتاپ تأیید کنید
برای احراز هویت به عنوان کاربر نهایی و دسترسی به دادههای کاربر در برنامه خود، باید یک یا چند شناسه کلاینت OAuth 2.0 ایجاد کنید. شناسه کلاینت برای شناسایی یک برنامه واحد به سرورهای OAuth گوگل استفاده میشود. اگر برنامه شما روی چندین پلتفرم اجرا میشود، باید برای هر پلتفرم یک شناسه کلاینت جداگانه ایجاد کنید.
- به صفحه اعتبارنامههای گوگل کلود در کنسول گوگل کلود بروید.
- روی ایجاد اعتبارنامهها > شناسه کلاینت OAuth کلیک کنید.
- روی نوع برنامه > برنامه دسکتاپ کلیک کنید.
- در فیلد نام ، یک نام برای اعتبارنامه تایپ کنید. این نام فقط در کنسول Google Cloud نمایش داده میشود. برای مثال، "Rubrics client".
- روی ایجاد کلیک کنید. صفحه ایجاد کلاینت OAuth ظاهر میشود و شناسه کلاینت و رمز کلاینت جدید شما را نشان میدهد.
- روی دانلود JSON و سپس تأیید کلیک کنید. اعتبارنامه تازه ایجاد شده در زیر شناسههای کلاینت OAuth 2.0 ظاهر میشود.
- فایل JSON دانلود شده را با نام
credentials.jsonذخیره کنید و آن را به دایرکتوری کاری خود منتقل کنید. - روی ایجاد اعتبارنامهها > کلید API کلیک کنید و کلید API را یادداشت کنید.
برای کسب اطلاعات بیشتر به ایجاد اعتبارنامههای دسترسی مراجعه کنید.
پیکربندی محدودههای OAuth
بسته به محدودههای OAuth موجود در پروژه شما، ممکن است نیاز به پیکربندی محدودههای اضافی داشته باشید.
- به صفحه رضایت OAuth بروید.
- برای رسیدن به صفحه Scopes، روی Edit App > Save and Continue کلیک کنید.
- روی افزودن یا حذف محدودهها کلیک کنید.
- اگر scope های زیر را ندارید، آنها را اضافه کنید:
-
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 Scopes for Google APIs مشاهده کنید.
نمونه را پیکربندی کنید
در دایرکتوری کاری خود، کتابخانه کلاینت گوگل برای پایتون را نصب کنید:
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
فایلی به نام main.py ایجاد کنید که کتابخانه کلاینت را میسازد و کاربر را احراز هویت میکند، و به جای YOUR_API_KEY از کلید API شما استفاده میکند:
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 موافقت کنید.
ایجاد یک تکلیف
یک روبریک (Rubric) با یک تکلیف یا 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 ذخیره کنید. این موارد برای همه عملیات CRUD روبریکها مورد نیاز هستند.
اکنون باید یک نمونه CourseWork در کلاس درس داشته باشید.
شکل ۲. نمایی از یک نمونه تکلیف در کلاس درس.
بررسی صلاحیت کاربر
ایجاد و بهروزرسانی روبریکها مستلزم آن است که هم به کاربر درخواستدهنده و هم به مالک دوره مربوطه، مجوز Google Workspace for Education Plus اختصاص داده شده باشد. Classroom از یک نقطه پایانی واجد شرایط بودن کاربر پشتیبانی میکند تا توسعهدهندگان بتوانند قابلیتهایی را که کاربر به آنها دسترسی دارد، تعیین کنند.
برای تأیید اینکه حساب آزمایشی شما به قابلیت rubrics دسترسی دارد 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() که شامل شیء روبریک کامل است، ایجاد شود، که در آن ویژگیهای ID برای معیارها و سطوح حذف میشوند (اینها در هنگام ایجاد ایجاد میشوند).
تابع زیر را به 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))
چند نکته در مورد نمایش روبریک:
- ترتیب معیار و سطح در رابط کاربری کلاس درس منعکس شده است.
- سطوح امتیازدهی شده (آنهایی که دارای ویژگی
pointsهستند) باید بر اساس امتیاز به ترتیب صعودی یا نزولی مرتب شوند (نمیتوان آنها را به صورت تصادفی مرتب کرد). - معلمان میتوانند معیارها و سطوح امتیازدهیشده (اما نه سطوح بدون امتیاز) را در رابط کاربری دوباره مرتب کنند و این باعث تغییر ترتیب آنها در دادهها میشود.
برای نکات بیشتر در مورد ساختار روبریکها، به محدودیتها مراجعه کنید.
به رابط کاربری برگردید، باید عنوان تکلیف را ببینید.
شکل ۳. نمایی از یک نمونه روبریک در یک تکلیف کلاسی.
یک روبریک بخوانید
روبریکها را میتوان با متدهای استاندارد 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
این پیادهسازی در صورت عدم وجود روبریک، خطای ۴۰۴ را برمیگرداند.
بهروزرسانی یک روبریک
بهروزرسانیهای یک روبریک با فراخوانیهای patch() انجام میشوند. با توجه به ساختار پیچیدهی یک روبریک، بهروزرسانیها باید با الگوی خواندن-تغییر-نوشتن انجام شوند، که در آن کل ویژگی criteria جایگزین میشود.
قوانین بهروزرسانی به شرح زیر است:
- معیارها یا سطوحی که بدون شناسه اضافه میشوند، اضافه محسوب میشوند.
- معیارها یا سطوحی که از قبل وجود ندارند ، حذفشده محسوب میشوند.
- معیارها یا سطوحی که شناسه (ID) آنها موجود است اما دادههایشان تغییر یافته ، ویرایش محسوب میشوند. ویژگیهای اصلاح نشده به همان صورت باقی میمانند.
- معیارها یا سطوح ارائه شده با شناسههای جدید یا ناشناخته، خطا محسوب میشوند.
- ترتیب معیارها و سطوح جدید، ترتیب جدید رابط کاربری (با محدودیتهای ذکر شده) در نظر گرفته میشود.
یک تابع برای بهروزرسانی یک روبریک اضافه کنید:
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))
اکنون تغییرات باید برای معلم در کلاس درس منعکس شود.
شکل ۴. نمایی از روبریک بهروزرسانیشده.
مشاهده مقالات رتبهبندیشده بر اساس موضوع
در حال حاضر، API نمیتواند به مطالب ارسالی دانشآموزان با روبریک نمره بدهد، اما میتوانید نمرات روبریک مطالب ارسالی که با روبریک نمره داده شدهاند را در رابط کاربری Classroom بخوانید.
به عنوان یک دانشآموز در رابط کاربری کلاس درس، نمونه تکلیف خود را تکمیل و تحویل دهید . سپس به عنوان معلم، با استفاده از روبریک، به صورت دستی به تکلیف نمره دهید .
شکل ۵. نمای معلم از روبریک در حین نمرهدهی.
StudentSubmissions که با یک روبریک نمرهدهی شدهاند، دو ویژگی جدید دارند: draftRubricGrades و assignedRubricGrades که به ترتیب نشاندهنده امتیازها و سطوح انتخاب شده توسط معلم در طول حالتهای نمرهدهی draft و assigned هستند.
شما میتوانید از متدهای 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 Spreadsheets صادر کرد .
علاوه بر مشخص کردن معیارهای روبریک در کد، میتوان روبریکها را از این برگههای صادر شده با مشخص کردن 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