সংযুক্তি গ্রেড এবং গ্রেড পাসব্যাক

এটি ক্লাসরুম অ্যাড-অন ওয়াকথ্রু সিরিজের ষষ্ঠ পর্ব।

এই ধাপে, আপনি পূর্ববর্তী ধাপের উদাহরণটি পরিবর্তন করে একটি গ্রেডযুক্ত অ্যাক্টিভিটি-টাইপ অ্যাটাচমেন্ট তৈরি করবেন। এছাড়াও, আপনি প্রোগ্রাম্যাটিকভাবে গুগল ক্লাসরুমে একটি গ্রেড পাঠাবেন , যা শিক্ষকের গ্রেডবুকে একটি ড্রাফট গ্রেড হিসেবে প্রদর্শিত হবে।

এই ওয়াকথ্রুটি সিরিজের অন্যগুলোর থেকে কিছুটা আলাদা, কারণ এখানে ক্লাসরুমে গ্রেড ফেরত পাঠানোর দুটি সম্ভাব্য পদ্ধতি রয়েছে। দুটিরই ডেভেলপার এবং ব্যবহারকারীর অভিজ্ঞতার উপর স্বতন্ত্র প্রভাব রয়েছে; আপনার ক্লাসরুম অ্যাড-অন ডিজাইন করার সময় উভয় পদ্ধতিই বিবেচনা করুন। বাস্তবায়নের বিকল্পগুলো সম্পর্কে আরও আলোচনার জন্য আমাদের ‘অ্যাটাচমেন্টের সাথে মিথস্ক্রিয়া’ গাইড পৃষ্ঠাটি পড়ুন।

উল্লেখ্য যে, এপিআই-এর গ্রেডিং বৈশিষ্ট্যগুলো ঐচ্ছিক । এগুলো যেকোনো অ্যাক্টিভিটি-টাইপ অ্যাটাচমেন্টের সাথে ব্যবহার করা যায়।

এই নির্দেশিকাটি অনুসরণ করার সময়, আপনাকে নিম্নলিখিত কাজগুলো সম্পন্ন করতে হবে:

  • ক্লাসরুম এপিআই-তে পূর্ববর্তী অ্যাটাচমেন্ট তৈরির অনুরোধগুলো সংশোধন করে অ্যাটাচমেন্টের গ্রেড ডিনোমিনেটরও সেট করুন।
  • প্রোগ্রামের মাধ্যমে শিক্ষার্থীর জমা দেওয়া কাজের মূল্যায়ন করুন এবং সংযুক্তিটির গ্রেডের লব নির্ধারণ করুন।
  • সাইন-ইন করা বা অফলাইন শিক্ষকের পরিচয়পত্র ব্যবহার করে ক্লাসরুমে জমা দেওয়া বিষয়ের গ্রেড পাঠানোর জন্য দুটি পদ্ধতি বাস্তবায়ন করুন।

কাজ শেষ হলে, পাসব্যাক আচরণটি সক্রিয় হওয়ার পর গ্রেডগুলো ক্লাসরুম গ্রেডবুকে দেখা যায়। ঠিক কখন এটি ঘটবে তা বাস্তবায়ন পদ্ধতির উপর নির্ভর করে।

এই উদাহরণের জন্য, পূর্ববর্তী ওয়াকথ্রু থেকে কার্যকলাপটি পুনরায় ব্যবহার করুন, যেখানে একজন শিক্ষার্থীকে একটি বিখ্যাত ল্যান্ডমার্কের ছবি দেখানো হয় এবং এর নাম লিখতে বলা হয়। শিক্ষার্থী সঠিক নাম লিখলে সংযুক্তির জন্য পূর্ণ নম্বর দিন, অন্যথায় শূন্য।

ক্লাসরুম অ্যাড-অন এপিআই-এর গ্রেডিং বৈশিষ্ট্যটি বুঝুন

আপনার অ্যাড-অন একটি অ্যাটাচমেন্টের জন্য গ্রেডের লব এবং হর উভয়ই নির্ধারণ করতে পারে। এপিআই-তে থাকা pointsEarned এবং maxPoints ভ্যালু ব্যবহার করে এগুলি যথাক্রমে সেট করা হয়। যখন maxPoints ভ্যালুটি সেট করা হয়ে যায়, তখন ক্লাসরুম ইউআই-তে থাকা একটি অ্যাটাচমেন্ট কার্ডে তা দেখানো হয়।

একটি অ্যাসাইনমেন্টে সর্বোচ্চ পয়েন্ট সহ একাধিক সংযুক্তি যুক্ত করার উদাহরণ

চিত্র ১. অ্যাসাইনমেন্ট তৈরির UI, যেখানে তিনটি অতিরিক্ত সংযুক্তি কার্ড রয়েছে এবং সেগুলোতে maxPoints নির্ধারণ করা আছে।

ক্লাসরুম অ্যাড-অনস এপিআই আপনাকে অ্যাটাচমেন্ট গ্রেডের জন্য সেটিংস কনফিগার করতে এবং অর্জিত স্কোর নির্ধারণ করতে দেয়। এগুলো অ্যাসাইনমেন্ট গ্রেডের মতো নয়। তবে, অ্যাসাইনমেন্ট গ্রেডের সেটিংস সেই অ্যাটাচমেন্টের গ্রেড সেটিংস অনুসরণ করে, যার অ্যাটাচমেন্ট কার্ডে ‘গ্রেড সিঙ্ক’ লেবেল থাকে। যখন ‘গ্রেড সিঙ্ক’ অ্যাটাচমেন্ট কোনো শিক্ষার্থীর সাবমিশনের জন্য pointsEarned ’ নির্ধারণ করে, তখন এটি অ্যাসাইনমেন্টটির জন্য শিক্ষার্থীর ড্রাফট গ্রেডও নির্ধারণ করে দেয়।

সাধারণত, অ্যাসাইনমেন্টে যোগ করা প্রথম অ্যাটাচমেন্ট, যা maxPoints নির্ধারণ করে, সেটিই "গ্রেড সিঙ্ক" (Grade sync) লেবেল পায়। "গ্রেড সিঙ্ক" লেবেলের একটি উদাহরণের জন্য চিত্র ১-এ দেখানো অ্যাসাইনমেন্ট তৈরির UI উদাহরণটি দেখুন। লক্ষ্য করুন যে "অ্যাটাচমেন্ট ১" কার্ডটিতে "গ্রেড সিঙ্ক" লেবেল রয়েছে এবং লাল বক্সের অ্যাসাইনমেন্ট গ্রেডটি ৫০ পয়েন্টে আপডেট করা হয়েছে। আরও লক্ষ্য করুন যে, যদিও চিত্র ১-এ তিনটি অ্যাটাচমেন্ট কার্ড দেখানো হয়েছে, শুধুমাত্র একটি কার্ডেই "গ্রেড সিঙ্ক" লেবেল রয়েছে। এটি বর্তমান বাস্তবায়নের একটি প্রধান সীমাবদ্ধতা: শুধুমাত্র একটি অ্যাটাচমেন্টেই "গ্রেড সিঙ্ক" লেবেল থাকতে পারে

যদি একাধিক অ্যাটাচমেন্টে maxPoints সেট করা থাকে, তাহলে 'গ্রেড সিঙ্ক' (Grade sync) সহ অ্যাটাচমেন্টটি সরিয়ে ফেললেও বাকি অ্যাটাচমেন্টগুলোর কোনোটিতেই 'গ্রেড সিঙ্ক' চালু হয় নাmaxPoints সেট করে এমন আরেকটি অ্যাটাচমেন্ট যোগ করলে নতুন অ্যাটাচমেন্টটিতে গ্রেড সিঙ্ক চালু হয়ে যায় এবং অ্যাসাইনমেন্টের সর্বোচ্চ গ্রেডও সেই অনুযায়ী পরিবর্তিত হয়। কোন অ্যাটাচমেন্টে 'গ্রেড সিঙ্ক' লেবেল আছে, অথবা কোনো নির্দিষ্ট অ্যাসাইনমেন্টে কতগুলো অ্যাটাচমেন্ট আছে, তা প্রোগ্রামিংয়ের মাধ্যমে দেখার কোনো ব্যবস্থা নেই।

একটি সংযুক্তির সর্বোচ্চ গ্রেড নির্ধারণ করুন

এই বিভাগে একটি অ্যাটাচমেন্ট গ্রেডের জন্য ডিনোমিনেটর (হর ) নির্ধারণ করার পদ্ধতি বর্ণনা করা হয়েছে; অর্থাৎ, সকল শিক্ষার্থী তাদের জমা দেওয়া কাজের জন্য সর্বোচ্চ যে স্কোরটি পেতে পারে। এটি করার জন্য, অ্যাটাচমেন্টটির maxPoints ভ্যালুটি সেট করুন।

গ্রেডিং বৈশিষ্ট্যগুলো চালু করার জন্য আমাদের বিদ্যমান বাস্তবায়নে শুধুমাত্র একটি সামান্য পরিবর্তন প্রয়োজন। একটি অ্যাটাচমেন্ট তৈরি করার সময়, সেই একই AddOnAttachment অবজেক্টে maxPoints মানটি যোগ করুন, যেটিতে studentWorkReviewUri , teacherViewUri এবং অন্যান্য অ্যাটাচমেন্ট ফিল্ডগুলো রয়েছে।

মনে রাখবেন যে, একটি নতুন অ্যাসাইনমেন্টের জন্য ডিফল্ট সর্বোচ্চ স্কোর হলো ১০০। আমরা পরামর্শ দিচ্ছি যে, maxPoints ১০০ ছাড়া অন্য কোনো মানে সেট করুন, যাতে আপনি যাচাই করতে পারেন যে গ্রেডগুলো সঠিকভাবে সেট হচ্ছে কিনা। উদাহরণস্বরূপ, maxPoints কে ৫০-এ সেট করুন:

পাইথন

courses.courseWork.addOnAttachments এন্ডপয়েন্টে একটি CREATE রিকোয়েস্ট পাঠানোর ঠিক আগে, attachment অবজেক্টটি তৈরি করার সময় maxPoints ফিল্ডটি যোগ করুন। আমাদের দেওয়া উদাহরণটি অনুসরণ করলে, আপনি এটি 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 কল করার প্রয়োজন হয় না। তবে মনে রাখবেন, শিক্ষকরা আপনার অ্যাড-অন থেকে স্বাধীনভাবে অ্যাসাইনমেন্ট গ্রেড সেটিংস পরিবর্তন করতে পারেন। অ্যাসাইনমেন্ট-লেভেলের maxPoints ভ্যালুটি দেখতে courses.courseWork এন্ডপয়েন্টে একটি GET রিকোয়েস্ট পাঠান। এটি করার সময়, CourseWork.id ফিল্ডে itemId পাস করুন।

এখন আপনার ডাটাবেস মডেলটি আপডেট করুন যাতে এটি অ্যাটাচমেন্টের maxPoints মানটিও ধারণ করে। আমরা CREATE রেসপন্স থেকে maxPoints মানটি ব্যবহার করার পরামর্শ দিই:

পাইথন

প্রথমে, 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 scope প্রয়োজন । আপনার student ব্যবহারকারীদের teacher scope দেওয়া উচিত নয়; এর ফলে শিক্ষার্থীরা যখন আপনার অ্যাড-অনটি ব্যবহার করবে, তখন অপ্রত্যাশিত আচরণ দেখা দিতে পারে, যেমন Student View iframe-এর পরিবর্তে Teacher View iframe লোড হয়ে যাওয়া। সুতরাং, pointsEarned সেট করার জন্য আপনার কাছে দুটি উপায় আছে:

  • লগ-ইন করা শিক্ষকের পরিচয়পত্র ব্যবহার করে।
  • সংরক্ষিত (অফলাইন) শিক্ষকের পরিচয়পত্র ব্যবহার করা।

নিম্নলিখিত বিভাগগুলিতে প্রতিটি বাস্তবায়ন দেখানোর আগে প্রতিটি পদ্ধতির সুবিধা-অসুবিধা নিয়ে আলোচনা করা হয়েছে। উল্লেখ্য যে, আমাদের প্রদত্ত উদাহরণগুলি Classroom-এ একটি গ্রেড পাঠানোর উভয় পদ্ধতিই প্রদর্শন করে; প্রদত্ত উদাহরণগুলি চালানোর সময় কীভাবে একটি পদ্ধতি নির্বাচন করতে হয় তা জানতে নীচের ভাষা-নির্দিষ্ট নির্দেশাবলী দেখুন:

পাইথন

webapp/attachment_routes.py ফাইলের শীর্ষে SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS ডিক্লারেশনটি খুঁজুন। সাইন-ইন করা শিক্ষকের ক্রেডেনশিয়াল ব্যবহার করে গ্রেড ফেরত পাঠাতে এই মানটি True সেট করুন। শিক্ষার্থী যখন অ্যাক্টিভিটি জমা দেবে, তখন সংরক্ষিত ক্রেডেনশিয়াল ব্যবহার করে গ্রেড ফেরত পাঠাতে এই মানটি False সেট করুন।

সাইন-ইন করা শিক্ষকের পরিচয়পত্র ব্যবহার করে গ্রেড নির্ধারণ করুন।

pointsEarned সেট করার অনুরোধ জানাতে সাইন-ইন করা ব্যবহারকারীর ক্রেডেনশিয়াল ব্যবহার করুন। এটি বেশ স্বজ্ঞাত মনে হওয়া উচিত, কারণ এটি এখন পর্যন্ত বাকি বাস্তবায়নেরই প্রতিচ্ছবি এবং এটি কার্যকর করতে সামান্যই প্রচেষ্টার প্রয়োজন।

তবে, মনে রাখবেন যে শিক্ষক শুধুমাত্র 'Student Work Review' আইফ্রেমের মধ্যেই শিক্ষার্থীর জমা দেওয়া কাজের সাথে মিথস্ক্রিয়া করেন। এর কিছু গুরুত্বপূর্ণ প্রভাব রয়েছে:

  • শিক্ষক ক্লাসরুম UI-তে কোনো পদক্ষেপ না নেওয়া পর্যন্ত ক্লাসরুমে কোনো গ্রেড প্রদর্শিত হয় না।
  • সকল শিক্ষার্থীর গ্রেড যুক্ত করার জন্য একজন শিক্ষককে তাদের প্রত্যেকের জমা দেওয়া প্রতিটি নথি খুলতে হতে পারে।
  • ক্লাসরুমে গ্রেড জমা হওয়ার পর তা ক্লাসরুম ইউআই-তে প্রদর্শিত হতে সামান্য বিলম্ব হয়। এই বিলম্ব সাধারণত পাঁচ থেকে দশ সেকেন্ড হয়, তবে তা ৩০ সেকেন্ড পর্যন্তও হতে পারে।

এই কারণগুলোর সম্মিলিত প্রভাবে, একটি ক্লাসের গ্রেড সম্পূর্ণরূপে পূরণ করার জন্য শিক্ষকদের যথেষ্ট পরিমাণে সময়সাপেক্ষ হস্তকর্ম করতে হতে পারে।

এই পদ্ধতিটি বাস্তবায়ন করতে, আপনার বিদ্যমান স্টুডেন্ট ওয়ার্ক রিভিউ রুটে একটি অতিরিক্ত এপিআই কল যোগ করুন।

শিক্ষার্থীর জমা দেওয়া তথ্য এবং সংযুক্তি রেকর্ডগুলি সংগ্রহ করার পর, শিক্ষার্থীর জমা দেওয়া তথ্য মূল্যায়ন করুন এবং প্রাপ্ত গ্রেডটি সংরক্ষণ করুন। একটি AddOnAttachmentStudentSubmission অবজেক্টের pointsEarned ফিল্ডে গ্রেডটি সেট করুন। সবশেষে, রিকোয়েস্ট বডিতে AddOnAttachmentStudentSubmission ইনস্ট্যান্সটি সহ courses.courseWork.addOnAttachments.studentSubmissions এন্ডপয়েন্টে একটি PATCH রিকোয়েস্ট পাঠান। উল্লেখ্য যে, আমাদের PATCH রিকোয়েস্টের updateMaskpointsEarned ও উল্লেখ করতে হবে:

পাইথন

# 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. শিক্ষক আইডি সংরক্ষণ করার জন্য অ্যাটাচমেন্ট ডেটাবেসের রেকর্ডগুলো পরিবর্তন করুন।
  3. শিক্ষকের পরিচয়পত্র সংগ্রহ করুন এবং (ঐচ্ছিকভাবে) একটি নতুন Classroom পরিষেবা ইনস্ট্যান্স তৈরি করুন।
  4. জমা দেওয়া লেখার গ্রেড নির্ধারণ করুন।

এই প্রদর্শনের উদ্দেশ্যে, শিক্ষার্থী যখন কাজটি সম্পন্ন করবে, অর্থাৎ 'স্টুডেন্ট ভিউ' রুটে ফর্মটি জমা দেবে, তখন গ্রেড নির্ধারণ করুন।

অ্যাক্সেস টোকেন সংরক্ষণ করতে ব্যবহারকারী ডেটাবেস রেকর্ড পরিবর্তন করুন

এপিআই কল করার জন্য দুটি স্বতন্ত্র টোকেন প্রয়োজন: রিফ্রেশ টোকেন এবং অ্যাক্সেস টোকেন । আপনি যদি এখন পর্যন্ত এই ওয়াকথ্রু সিরিজটি অনুসরণ করে থাকেন, তাহলে আপনার User টেবিল স্কিমাতে ইতিমধ্যেই একটি রিফ্রেশ টোকেন সংরক্ষিত থাকার কথা। শুধুমাত্র সাইন-ইন করা ব্যবহারকারী দিয়ে এপিআই কল করার ক্ষেত্রে রিফ্রেশ টোকেন সংরক্ষণ করাই যথেষ্ট, কারণ অথেনটিকেশন প্রক্রিয়ার অংশ হিসেবেই আপনি একটি অ্যাক্সেস টোকেন পেয়ে থাকেন।

তবে, এখন আপনাকে সাইন-ইন করা ব্যবহারকারী ছাড়া অন্য কেউ হিসেবে কল করতে হবে, যার অর্থ হলো অথেনটিকেশন ফ্লোটি উপলব্ধ নেই। তাই, আপনাকে রিফ্রেশ টোকেনের পাশাপাশি অ্যাক্সেস টোকেনটিও সংরক্ষণ করতে হবে। একটি অ্যাক্সেস টোকেন অন্তর্ভুক্ত করার জন্য আপনার User টেবিলের স্কিমা আপডেট করুন:

পাইথন

আমাদের দেওয়া উদাহরণে, এটি 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 রেকর্ড তৈরি বা আপডেট করে এমন যেকোনো কোড আপডেট করুন, যাতে সেটি অ্যাক্সেস টোকেনও সংরক্ষণ করে:

পাইথন

আমাদের দেওয়া উদাহরণে, এটি 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()

শিক্ষক আইডি সংরক্ষণ করার জন্য অ্যাটাচমেন্ট ডেটাবেসের রেকর্ডগুলো পরিবর্তন করুন।

কোনো অ্যাক্টিভিটির জন্য গ্রেড নির্ধারণ করতে, কোর্সে শিক্ষক হিসেবে pointsEarned সেট করার জন্য কল করুন। এটি সম্পন্ন করার কয়েকটি উপায় রয়েছে:

  • শিক্ষকের পরিচয়পত্রের সাথে কোর্স আইডিগুলোর একটি স্থানীয় ম্যাপিং সংরক্ষণ করুন। তবে মনে রাখবেন, একই শিক্ষক সবসময় একটি নির্দিষ্ট কোর্সের সাথে যুক্ত নাও থাকতে পারেন।
  • বর্তমান শিক্ষক(দের) পেতে Classroom API-এর courses এন্ডপয়েন্টে GET রিকোয়েস্ট পাঠান। এরপর, মিলে যাওয়া শিক্ষকের ক্রেডেনশিয়াল খুঁজে বের করতে স্থানীয় ব্যবহারকারীর রেকর্ড কোয়েরি করুন।
  • অ্যাড-অন অ্যাটাচমেন্ট তৈরি করার সময়, স্থানীয় অ্যাটাচমেন্ট ডেটাবেসে একটি শিক্ষক আইডি সংরক্ষণ করুন। তারপর, স্টুডেন্ট ভিউ আইফ্রেমে পাঠানো attachmentId থেকে শিক্ষকের ক্রেডেনশিয়ালস সংগ্রহ করুন।

এই উদাহরণটি শেষ বিকল্পটি প্রদর্শন করে, কারণ এখানে শিক্ষার্থী কোনো অ্যাক্টিভিটি অ্যাটাচমেন্ট সম্পন্ন করলে গ্রেড নির্ধারণ করা হচ্ছে।

আপনার ডাটাবেসের Attachment টেবিলে একটি টিচার আইডি ফিল্ড যোগ করুন:

পাইথন

আমাদের দেওয়া উদাহরণে, এটি 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 রেকর্ড তৈরি বা আপডেট করে এমন যেকোনো কোড আপডেট করুন, যাতে এটি নির্মাতার আইডি-ও সংরক্ষণ করে:

পাইথন

আমাদের দেওয়া উদাহরণে, এটি webapp/attachment_routes.py ফাইলের create_attachments মেথডে রয়েছে।

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

শিক্ষকের পরিচয়পত্র সংগ্রহ করুন।

যে রুটটি স্টুডেন্ট ভিউ আইফ্রেমটি সরবরাহ করে, সেটি খুঁজুন। আপনার লোকাল ডেটাবেসে শিক্ষার্থীর প্রতিক্রিয়া সংরক্ষণ করার ঠিক পরেই, আপনার লোকাল স্টোরেজ থেকে শিক্ষকের ক্রেডেনশিয়ালগুলো পুনরুদ্ধার করুন। আগের দুটি ধাপের প্রস্তুতির কারণে এটি বেশ সহজ হওয়ার কথা। আপনি এগুলো ব্যবহার করে শিক্ষক ব্যবহারকারীর জন্য ক্লাসরুম সার্ভিসের একটি নতুন ইনস্ট্যান্সও তৈরি করতে পারেন:

পাইথন

আমাদের দেওয়া উদাহরণে, এটি webapp/attachment_routes.py ফাইলের load_activity_attachment মেথডে রয়েছে।

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

জমা দেওয়া লেখার গ্রেড নির্ধারণ করুন

এরপরের পদ্ধতিটি সাইন-ইন করা শিক্ষকের ক্রেডেনশিয়াল ব্যবহার করার পদ্ধতির মতোই। তবে, মনে রাখবেন যে আপনাকে আগের ধাপে পাওয়া শিক্ষকের ক্রেডেনশিয়াল ব্যবহার করেই কলটি করতে হবে:

পাইথন

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

অ্যাড-অনটি পরীক্ষা করুন

আগের ওয়াকথ্রু-এর মতোই, একজন শিক্ষক হিসেবে অ্যাক্টিভিটি-টাইপ অ্যাটাচমেন্ট সহ একটি অ্যাসাইনমেন্ট তৈরি করুন, একজন শিক্ষার্থী হিসেবে একটি প্রতিক্রিয়া জমা দিন, তারপর স্টুডেন্ট ওয়ার্ক রিভিউ আইফ্রেম-এ তাদের জমা দেওয়া কাজটি খুলুন। আপনার বাস্তবায়ন পদ্ধতির উপর নির্ভর করে গ্রেডটি বিভিন্ন সময়ে প্রদর্শিত হতে দেখা যাবে:

  • শিক্ষার্থী কাজটি সম্পন্ন করার পর যদি আপনি গ্রেড ফেরত দেওয়ার বিকল্পটি বেছে নেন, তাহলে 'Student Work Review' আইফ্রেমটি খোলার আগেই আপনি UI-তে তাদের খসড়া গ্রেড দেখতে পাবেন। এছাড়াও, অ্যাসাইনমেন্টটি খোলার সময় শিক্ষার্থীর তালিকায় এবং 'Student Work Review' আইফ্রেমের পাশের 'Grade' বক্সেও আপনি এটি দেখতে পাবেন।
  • শিক্ষক যখন 'শিক্ষার্থীর কাজ পর্যালোচনা' আইফ্রেমটি খুলবেন, তখন যদি আপনি গ্রেড ফেরত পাঠানোর বিকল্পটি বেছে নেন, তাহলে আইফ্রেমটি লোড হওয়ার পরপরই গ্রেডটি 'গ্রেড' বক্সে দেখা যাবে। উপরে যেমন উল্লেখ করা হয়েছে , এতে ৩০ সেকেন্ড পর্যন্ত সময় লাগতে পারে। এরপরে, নির্দিষ্ট শিক্ষার্থীর গ্রেডটি ক্লাসরুমের অন্যান্য গ্রেডবুক ভিউতেও দেখা যাবে।

শিক্ষার্থীর জন্য সঠিক স্কোর প্রদর্শিত হচ্ছে কিনা তা নিশ্চিত করুন।

অভিনন্দন! আপনি এখন পরবর্তী ধাপে যাওয়ার জন্য প্রস্তুত: গুগল ক্লাসরুমের বাইরে অ্যাটাচমেন্ট তৈরি করা