Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نظام الاستعارة

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 100 من 107.

challenge icon

التحدي

سهل

لنقم ببناء نظام الاستعارة لمشروع إدارة المكتبة الخاص بنا! ستقوم بإنشاء هيكل Library يدير مجموعات الكتب والمستخدمين، مع طرق (methods) للتعامل مع عمليات الاستعارة والإرجاع — مكتملة مع التحقق المناسب من الصحة.

ستقوم بتنظيم الكود الخاص بك عبر أربعة ملفات:

  • book.go: هيكل Book الخاص بك من الدرس السابق مع حقول ID و Title و Author و ISBN و Available. قم بتضمين منشئ NewBook الذي يقوم بتهيئة الكتب كـ "متاحة".
  • user.go: هيكل User الخاص بك مع حقول ID و Name و Email و BorrowedBooks (شريحة من معرفات الكتب). قم بتضمين منشئ NewUser الذي يقوم بتهيئة المستخدمين بقائمة استعارة فارغة.
  • library.go: قم بإنشاء هيكل Library يقوم بتخزين الكتب والمستخدمين في خرائط (maps) (مفتاحها هو معرفاتهم). قم ببناء هذه المكونات:
    • منشئ NewLibrary يقوم بتهيئة خرائط فارغة للكتب والمستخدمين
    • طريقة AddBook تضيف كتاباً إلى المكتبة
    • طريقة AddUser تضيف مستخدماً إلى المكتبة
    • طريقة Borrow تأخذ معرف المستخدم ومعرف الكتاب، وتتحقق من صحة العملية، وتجعل الكتاب غير متاح، وتضيف معرف الكتاب إلى قائمة استعارة المستخدم، وتعيد خطأً إذا حدث خطأ ما
    • طريقة Return تعكس عملية الاستعارة — تجعل الكتاب متاحاً وتزيله من قائمة استعارة المستخدم

    يجب أن تعيد طريقة Borrow هذه الأخطاء:

    • user not found إذا كان معرف المستخدم غير موجود
    • book not found إذا كان معرف الكتاب غير موجود
    • book not available إذا كان الكتاب مستعاراً بالفعل

    يجب أن تعيد طريقة Return هذه الأخطاء:

    • user not found إذا كان معرف المستخدم غير موجود
    • book not found إذا كان معرف الكتاب غير موجود
    • book not borrowed إذا كان الكتاب متاحاً بالفعل
  • main.go: اجمع كل شيء معاً عن طريق إنشاء مكتبة، وإضافة كتب ومستخدمين، ثم معالجة عمليات الاستعارة/الإرجاع.

    اقرأ عدد الكتب، ثم لكل كتاب اقرأ معرفه، وعنوانه، ومؤلفه، و ISBN الخاص به. بعد ذلك، اقرأ عدد المستخدمين، ولكل مستخدم اقرأ معرفه، واسمه، وبريده الإلكتروني. ثم اقرأ عدد العمليات، حيث تكون كل عملية إما borrow [userID] [bookID] أو return [userID] [bookID].

    لكل عملية، اطبع إما OK إذا كانت ناجحة، أو Error: [message] إذا فشلت.

سيتم توفير المدخلات التالية:

  • عدد الكتب، ثم معرف كل كتاب، وعنوانه، ومؤلفه، و ISBN (كل منها في سطر منفصل)
  • عدد المستخدمين، ثم معرف كل مستخدم، واسمه، وبريده الإلكتروني (كل منها في سطر منفصل)
  • عدد العمليات، ثم كل عملية في سطر منفصل

على سبيل المثال، إذا كان المدخل:

2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com
4
borrow U001 B001
borrow U001 B001
return U001 B001
borrow U002 B001

يجب أن يكون مخرجك:

OK
Error: book not available
OK
Error: user not found

وإذا كان المدخل:

1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.com
3
borrow U001 B100
borrow U002 B100
return U001 B100

يجب أن يكون مخرجك:

OK
Error: book not available
OK

وإذا كان المدخل:

1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999

يجب أن يكون مخرجك:

Error: book not borrowed
Error: book not found

لاحظ كيف تعمل المكتبة (Library) كمنسق مركزي — فهي تتحقق من صحة جميع العمليات قبل تعديل الحالة، مما يضمن بقاء الكتب والمستخدمين متزامنين. استخدام مستقبلات المؤشر (pointer receivers) يسمح لطرقك بتعديل البيانات الفعلية المخزنة في الخرائط!

جرّب بنفسك

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// قراءة عدد الكتب
	var numBooks int
	fmt.Scanln(&numBooks)

	// TODO: إنشاء مكتبة جديدة

	// TODO: قراءة تفاصيل كل كتاب (ID، وTitle، وAuthor، وISBN في أسطر منفصلة)
	// وإضافتها إلى المكتبة
	for i := 0; i < numBooks; i++ {
		id, _ := reader.ReadString('\n')
		id = strings.TrimSpace(id)
		title, _ := reader.ReadString('\n')
		title = strings.TrimSpace(title)
		author, _ := reader.ReadString('\n')
		author = strings.TrimSpace(author)
		isbn, _ := reader.ReadString('\n')
		isbn = strings.TrimSpace(isbn)

		// TODO: إنشاء كتاب وإضافته إلى المكتبة
	}

	// قراءة عدد المستخدمين
	var numUsers int
	fmt.Scanln(&numUsers)

	// TODO: قراءة تفاصيل كل مستخدم (ID، وName، وEmail في أسطر منفصلة)
	// وإضافتها إلى المكتبة
	for i := 0; i < numUsers; i++ {
		id, _ := reader.ReadString('\n')
		id = strings.TrimSpace(id)
		name, _ := reader.ReadString('\n')
		name = strings.TrimSpace(name)
		email, _ := reader.ReadString('\n')
		email = strings.TrimSpace(email)

		// TODO: إنشاء مستخدم وإضافته إلى المكتبة
	}

	// قراءة عدد العمليات
	var numOps int
	fmt.Scanln(&numOps)

	// TODO: معالجة كل عملية
	// التنسيق: "borrow [userID] [bookID]" أو "return [userID] [bookID]"
	for i := 0; i < numOps; i++ {
		line, _ := reader.ReadString('\n')
		line = strings.TrimSpace(line)
		parts := strings.Split(line, " ")

		// TODO: تحليل العملية واستدعاء الطريقة المناسبة
		// طباعة "OK" عند النجاح أو "Error: [message]" عند الفشل
	}
}

جميع دروس Object Oriented Programming