منصة تعليم إلكتروني
جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 105 من 107.
التحدي
سهللنَبْنِ منصة تعلّم إلكتروني تدير الدورات والطلاب وتتتبّع تقدّم التعلّم! ستجمع بين البُنى والواجهات والتركيب وتعدّد الأشكال لإنشاء نظام متماسك يمكن فيه للطلاب التسجيل في الدورات وإكمال Lessons.
ستنظّم شفرتك عبر خمسة ملفات:
lesson.go: عرّف بنيةLessonتمثّل وحدات learning الفردية. لكل lesson قيمةIDوTitleوDuration(بالدقائق). ضمّن مُنشئًا باسمNewLessonيعيد مؤشرًا إلى Lesson.course.go: أنشئ بنيةCourseتحتوي علىIDوTitleوInstructorوشريحة من مؤشرات*Lesson. ضمّن مُنشئًا باسمNewCourseوطريقة باسمAddLesson. طبّق أيضًا طريقةTotalDuration() intالتي تعيد مجموع مدد جميع lessons في course.student.go: عرّف بنيةStudentتحتوي على حقولIDوNameوEmail. ضمّن مُنشئًا باسمNewStudent.enrollment.go: هنا تحدث آلية تتبّع التقدّم. أنشئ بنيةEnrollmentتربط student بـ course وتتتبّع أي lessons أكملها. يجب أن تحتوي على:- مؤشر إلى
Student - مؤشر إلى
Course - خريطة
CompletedLessons(من lesson ID إلى قيمة منطقية)
عرّف واجهة
Progressableتحتوي على طريقةProgress() float64التي تعيد نسبة مئوية (من 0.0 إلى 100.0).طبّق الطرق التالية على Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment: مُنشئ يهيّئ خريطة lessons المكتملة فارغةCompleteLesson(lessonID string) string: يعلّم lesson على أنه مكتمل. يعيدlesson not foundإذا لم يكن lesson موجودًا في course، أوalready completedإذا كان مكتملًا بالفعل، أوcompletedعند النجاحProgress() float64: يعيد نسبة lessons المكتملة (المكتملة/الإجمالية * 100)، أو 0.0 إذا لم يحتوِ course على أي lessons
- مؤشر إلى
main.go: ابنِ منصتك وعالِج عمليات enrollment.اقرأ معرّف course وعنوانه وInstructor الخاص به. ثم اقرأ عدد lessons ومعرّف كل lesson وعنوانه ومدته. اقرأ معرّف student واسمه وEmail الخاص به. أنشئ enrollment يربط student بـ course.
ثم اقرأ عدد العمليات. كل عملية إما
complete [lessonID]أوprogress. بالنسبة إلى عمليات complete، اطبع رسالة النتيجة. وبالنسبة إلى عمليات progress، اطبع التقدّم منسّقًا إلى منزلة عشرية واحدة، متبوعًا بعلامة النسبة المئوية.
سيتم توفير المدخلات التالية:
- معرّف Course وTitle وInstructor (3 أسطر)
- عدد lessons، ثم معرّف كل lesson وTitle وDuration (3 أسطر لكل منها)
- معرّف Student وName وEmail (3 أسطر)
- عدد العمليات، ثم كل عملية (سطر واحد لكل منها)
على سبيل المثال، عند تقديم:
C001
Go Fundamentals
Jane Smith
3
L001
Variables
30
L002
Functions
45
L003
Structs
60
S001
Alice
alice@learn.com
5
progress
complete L001
progress
complete L001
complete L002يجب أن يكون ناتجك:
0.0%
completed
33.3%
already completed
completedوعند تقديم:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressيجب أن يكون ناتجك:
lesson not found
completed
completed
100.0%لاحظ كيف تستخدم بنية Enrollment التركيب لربط students وcourses معًا، بينما تتيح واجهة Progressable لأي نوع الإبلاغ عن حالة الإكمال الخاصة به. يجعل هذا التصميم التوسّع سهلًا. يمكنك إضافة تتبّع التقدّم إلى lessons الفردية أو مسارات التعلّم الكاملة باستخدام الواجهة نفسها!
جرّب بنفسك
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// دالة مساعدة لقراءة سطر
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// قراءة معلومات الدورة
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: أنشئ الدورة باستخدام NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// قراءة عدد الدروس
numLessons, _ := strconv.Atoi(readLine())
// TODO: اقرأ كل درس وأضفه إلى الدورة
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: أنشئ الدرس وأضفه إلى الدورة
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// قراءة معلومات الطالب
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: أنشئ الطالب باستخدام NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: أنشئ التسجيل الذي يربط الطالب بالدورة
// قراءة عدد العمليات
numOps, _ := strconv.Atoi(readLine())
// معالجة كل عملية
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: استدعِ Progress() واطبع بالتنسيق "%.1f%%"
fmt.Println("0.0%") // استبدل بالتقدم الفعلي
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: استدعِ CompleteLesson واطبع النتيجة
_ = lessonID
fmt.Println("") // استبدل بالنتيجة الفعلية
}
}
}
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP في Go
الملفات الخارجيةمساحة العمل والـ Modules في Goالـ Packages والـ Importsالأسماء المصدرة مقابل غير المصدرةمقدمة إلى الـ OOP في Goالـ Structs كـ Classesتعريف الـ Methods في الـ Structsالـ Pointer Receivers مقابل الـ Value Receiversتهيئة الـ Structدوال الـ Constructorمراجعة - آلة حاسبة بسيطة4الواجهات
مقدمة في الواجهاتالتنفيذ الضمنيالواجهة كعقدالواجهة الفارغة (any)تأكيد النوع (Type Assertion)تبديل النوع (Type Switch)تركيب الواجهاتواجهات Stringer و Errorمراجعة - حاسبة الأشكال7التغليف
الحقول المصدرة وغير المصدرةالتغليف على مستوى الحزمةدوال الـ Getter والـ Setterإخفاء المعلومات في Goملخص - سجلات الطلاب10الأنواع العامة (Go 1.18+)
مقدمة في الأنواع العامةمعاملات الأنواعقيود الأنواعالـ Structs العامةحل بديل للـ Methods العامةملخص - المجموعات العامة13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy2تعمق في الأنواع و Structs
الأنواع الأساسية والمركبةتعريفات الأنواع المخصصةStruct TagsStructs مجهولةStructs متداخلةالقيم الصفرية والافتراضيةمراجعة - دفتر العناوين5التركيب بدلاً من الوراثة
لماذا لا تدعم Go الوراثةأساسيات تضمين الـ Structترقية الـ Methodتضمين عدة Structsالتضمين مقابل التجميعحجب الـ Methods المضمنةملخص - الهيكل الهرمي للموظفين8معالجة الأخطاء و OOP
واجهة errorأنواع الأخطاء المخصصةتغليف الأخطاء (fmt.Errorf)أخطاء Sentinelerrors.Is() و errors.As()Panic و Defer و Recoverملخص - File Parser11المكتبة القياسية والبرمجة كائنية التوجه (OOP)
io.Reader و io.Writerواجهة sort.Interfaceواجهة fmt.Stringerencoding/json مع Structsواجهة http.Handlerمراجعة - نماذج REST API14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبMiddleware كنمط مزين3المؤشرات والذاكرة
أساسيات المؤشرات في Goالمؤشرات إلى الـ Structsالتمرير بالقيمة مقابل التمرير بالمرجعدالة ()newGarbage Collection في Goملخص - بناء Linked List6تعدد الأشكال في Go
تعدد الأشكال عبر InterfacesDuck Typing في Goقواعد استيفاء الـ Interfaceمجموعات متعددة الأشكالحقن التبعيةمراجعة - معالج الدفع9التزامن والبرمجة كائنية التوجه (OOP)
أساسيات الـ Goroutinesالقنوات (Channels) والاتصالالقنوات المخزنة (Buffered) مقابل غير المخزنةجملة Selectsync.Mutex و sync.RWMutexsync.WaitGroupتصميم الـ Structs الآمنة للخيوط (Thread-Safe)مراجعة - Worker Poolتدرّب بنفسك: مترجم Go عبر الإنترنت