تجميع كل الأجزاء معاً
جزء من قسم المنطق وتدفق التنفيذ في رحلة GO على Coddy. الدرس 50 من 68.
التحدي
سهلأكمل نظام إدارة المخزون بإنشاء برنامج رئيسي شامل يدمج جميع الوظائف التي بنيتها في الدروس السابقة. يجمع هذا التحدي النهائي بين تهيئة المخزون والتحقق من الكميات وإضافة العناصر وتحديث المخزون وإنشاء التقارير في واجهة سطر أوامر متكاملة ذات تنقّل موجّه بالقائمة.
ستتلقى ثلاثة مدخلات:
- سلسلة نصية تحتوي على بيانات المخزون الأولية بالتنسيق
"product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3"(مثلًا،"Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8") - سلسلة نصية تحتوي على تسلسل عمليات القائمة بالتنسيق
"operation1,operation2,operation3"، حيث يمكن أن تكون العمليات"check"أو"add"أو"update"أو"report"أو"exit"(مثلًا،"check,add,update,report,exit") - سلسلة نصية تحتوي على معلمات العمليات بالتنسيق
"param1|param2|param3"، حيث تقابل كل معلمة العملية الموجودة في الموضع نفسه (مثلًا،"Mouse|Monitor:299.99:10|Laptop:5|full,10")
مهمتك هي:
- استخدم بنية
Productنفسها من الدروس السابقة، التي تحتوي على الحقلينPrice(float64) وQuantity(int) - حلّل المدخل الأول وهيّئ خريطة المخزون ببيانات المنتجات الموجودة
- اعرض رسالة بدء تشغيل النظام:
"=== INVENTORY MANAGEMENT SYSTEM ===""System initialized with [number_of_products] products""Starting interactive session..."
- حلّل المدخل الثاني للحصول على تسلسل العمليات المطلوب تنفيذها
- حلّل المدخل الثالث للحصول على معلمات كل عملية
- لكل عملية في التسلسل، اعرض عنوان العملية ونفّذ الإجراء المقابل:
- للعملية
"check": اعرض"--- STOCK CHECK ---"</code وتحقق من مخزون المنتج المحدد</li> <li>للعملية <code>"add": اعرض"--- ADD ITEM ---"</code وأضف المنتج المحدد</li> <li>للعملية <code>"update": اعرض"--- UPDATE STOCK ---"</code وحدّث مخزون المنتج المحدد</li> <li>للعملية <code>"report": اعرض"--- GENERATE REPORT ---"</code وأنشئ التقرير المحدد</li> <li>للعملية <code>"exit": اعرض"--- SYSTEM EXIT ---"</code واعرض معلومات الخروج</li> </ul> </li> <li>نفّذ الدالة <code>checkStockالتي تعيد الكمية والخطأ كما في الدروس السابقة - نفّذ الدالة
addNewItemالتي تضيف المنتجات وتعيد خطأً كما في الدروس السابقة - نفّذ الدالة
updateStockالتي تحدّث الكميات وتعيد خطأً كما في الدروس السابقة - نفّذ الدالة
generateReportالتي تطبع التقرير الموضّح أدناه في عملية"report" - لعملية
"check":- استخدم المعلمة باعتبارها اسم المنتج المطلوب التحقق منه
- اعرض:
"Checking stock for: [product_name]" - إذا عُثر عليه:
"Stock level: [quantity] units" - إذا لم يُعثر عليه:
"Product not found in inventory"
- لعملية
"add":- حلّل المعلمة بالتنسيق
"product_name:price:quantity" - اعرض:
"Adding new product: [product_name]" - إذا نجحت العملية:
"Product added successfully" - إذا فشلت:
"Failed to add product: [error_message]"، حيث يكون الخطأ"product already exists"
- حلّل المعلمة بالتنسيق
- لعملية
"update":- حلّل المعلمة بالتنسيق
"product_name:change" - اعرض:
"Updating stock for: [product_name]" - إذا نجحت العملية وكان التغيير صفرًا أو موجبًا:
"Added [change] units. New stock: [new_quantity]" - إذا نجحت العملية وكان التغيير سالبًا:
"Removed [absolute_change] units. New stock: [new_quantity]" - إذا فشلت:
"Update failed: [error_message]"، حيث يكون الخطأ"product not found"، أو"insufficient stock"عندما تصبح الكمية الجديدة أقل من 0
- حلّل المعلمة بالتنسيق
- لعملية
"report":- حلّل المعلمة بالتنسيق
"report_type,threshold"، حيث يكون report_type إما"low"أو"full"، وتكون threshold عددًا صحيحًا - اعرض:
"Generating [report_type] report with threshold [threshold]" - ثم اطبع التقرير، مع ترتيب المنتجات أبجديًا:
- لـ
"low":"=== LOW REPORT ==="، ثم"Products with stock below [threshold]:"، ثم"- [name]: [quantity] units (Price: $[price])"لكل منتج تقل كميته عن الحد - لـ
"full":"=== FULL REPORT ==="، ثم"Complete inventory (minimum threshold: [threshold]):"، ثم"- [name]: [quantity] units @ $[price] each [OK]"لكل منتج، مع استخدام[LOW STOCK]بدلًا من[OK]عندما تقل الكمية عن الحد
- لـ
- حلّل المعلمة بالتنسيق
- لعملية
"exit":- اعرض إحصاءات المخزون النهائية:
"Final inventory status:""Total products: [total_products]""Total items: [total_items]""Total value: $[total_value]"
- اعرض:
"Session completed successfully" - اعرض:
"Thank you for using the Inventory Management System"
- اعرض إحصاءات المخزون النهائية:
- بعد كل عملية (باستثناء exit)، اعرض:
"Operation completed. Continuing to next operation..."
- للعملية
استخدم الحزمة strings لتقسيم سلاسل الإدخال، والحزمة strconv لتحويل السلاسل إلى أرقام، والحزمة errors لمعالجة الأخطاء، والحزمة fmt للإخراج المنسق، والحزمة sort للترتيب الأبجدي. نسّق جميع الأسعار والقيم إلى منزلتين عشريتين. يوضّح هذا التحدي كيفية إنشاء نظام تفاعلي متكامل يدمج عدة مكوّنات وظيفية في تجربة مستخدم مترابطة، مع معالجة سليمة للأخطاء وإدارة الحالة.
جرّب بنفسك
package main
import (
"fmt"
"sort"
"strconv"
"strings"
)
type Product struct {
Price float64
Quantity int
}
func generateReport(inventory map[string]Product, reportType string, threshold float64) {
// Display report header
switch reportType {
case "full":
fmt.Println("=== FULL INVENTORY REPORT ===")
case "low_stock":
fmt.Println("=== LOW STOCK REPORT ===")
case "high_value":
fmt.Println("=== HIGH VALUE REPORT ===")
}
// Calculate general statistics
totalProducts := len(inventory)
totalItems := 0
totalValue := 0.0
for _, product := range inventory {
totalItems += product.Quantity
totalValue += product.Price * float64(product.Quantity)
}
averagePrice := totalValue / float64(totalItems)
// Display general statistics
fmt.Printf("Total Products: %d\n", totalProducts)
fmt.Printf("Total Items in Stock: %d\n", totalItems)
fmt.Printf("Total Inventory Value: $%.2f\n", totalValue)
fmt.Printf("Average Product Price: $%.2f\n", averagePrice)
// Filter products based on report type
var filteredProducts []string
for name, product := range inventory {
switch reportType {
case "full":
filteredProducts = append(filteredProducts, name)
case "low_stock":
if product.Quantity <= int(threshold) {
filteredProducts = append(filteredProducts, name)
}
case "high_value":
productValue := product.Price * float64(product.Quantity)
if productValue >= threshold {
filteredProducts = append(filteredProducts, name)
}
}
}
// Sort filtered products alphabetically
sort.Strings(filteredProducts)
// Display filtered products section header
switch reportType {
case "full":
fmt.Println("All Products:")
case "low_stock":
fmt.Printf("Products with stock ≤ %.0f:\n", threshold)
case "high_value":
fmt.Printf("Products with value ≥ $%.2f:\n", threshold)
}
// Display filtered products
filteredItems := 0
filteredValue := 0.0
for _, name := range filteredProducts {
product := inventory[name]
productValue := product.Price * float64(product.Quantity)
fmt.Printf("- %s: $%.2f × %d = $%.2f\n", name, product.Price, product.Quantity, productValue)
filteredItems += product.Quantity
filteredValue += productValue
}
// Display filtered statistics
fmt.Println("Filtered Results:")
fmt.Printf("Products shown: %d\n", len(filteredProducts))
fmt.Printf("Items in filtered products: %d\n", filteredItems)
fmt.Printf("Value of filtered products: $%.2f\n", filteredValue)
// Find most and least expensive products
var mostExpensiveName, leastExpensiveName string
var mostExpensivePrice, leastExpensivePrice float64
first := true
var sortedNames []string
for name := range inventory {
sortedNames = append(sortedNames, name)
}
sort.Strings(sortedNames)
for _, name := range sortedNames {
product := inventory[name]
if first {
mostExpensiveName = name
mostExpensivePrice = product.Price
leastExpensiveName = name
leastExpensivePrice = product.Price
first = false
} else {
if product.Price > mostExpensivePrice {
mostExpensiveName = name
mostExpensivePrice = product.Price
}
if product.Price < leastExpensivePrice {
leastExpensiveName = name
leastExpensivePrice = product.Price
}
}
}
fmt.Println("Price Analysis:")
fmt.Printf("Most expensive: %s at $%.2f\n", mostExpensiveName, mostExpensivePrice)
fmt.Printf("Least expensive: %s at $%.2f\n", leastExpensiveName, leastExpensivePrice)
// Find highest and lowest stock products
var highestStockName, lowestStockName string
var highestStock, lowestStock int
first = true
for _, name := range sortedNames {
product := inventory[name]
if first {
highestStockName = name
highestStock = product.Quantity
lowestStockName = name
lowestStock = product.Quantity
first = false
} else {
if product.Quantity > highestStock {
highestStockName = name
highestStock = product.Quantity
}
if product.Quantity < lowestStock {
lowestStockName = name
lowestStock = product.Quantity
}
}
}
fmt.Println("Stock Analysis:")
fmt.Printf("Highest stock: %s with %d units\n", highestStockName, highestStock)
fmt.Printf("Lowest stock: %s with %d units\n", lowestStockName, lowestStock)
// Inventory health assessment
lowStockCount := 0
highStockCount := 0
highValueCount := 0
for _, product := range inventory {
if product.Quantity <= 5 {
lowStockCount++
}
if product.Quantity > 20 {
highStockCount++
}
productValue := product.Price * float64(product.Quantity)
if productValue >= 500.0 {
highValueCount++
}
}
fmt.Printf("Low stock items (≤5): %d\n", lowStockCount)
fmt.Printf("High stock items (>20): %d\n", highStockCount)
fmt.Printf("High value items (≥$500): %d\n", highValueCount)
// Report completion
fmt.Println("Report generated successfully")
fmt.Printf("Threshold applied: %.2f\n", threshold)
}
func main() {
var inventoryData string
var reportConfig string
fmt.Scanln(&inventoryData)
fmt.Scanln(&reportConfig)
// Parse inventory data
inventory := make(map[string]Product)
if inventoryData != "" {
products := strings.Split(inventoryData, ",")
for _, productStr := range products {
parts := strings.Split(productStr, ":")
name := parts[0]
price, _ := strconv.ParseFloat(parts[1], 64)
quantity, _ := strconv.Atoi(parts[2])
inventory[name] = Product{Price: price, Quantity: quantity}
}
}
// Parse report configuration
configParts := strings.Split(reportConfig, ",")
reportType := configParts[0]
threshold, _ := strconv.ParseFloat(configParts[1], 64)
// Generate report
generateReport(inventory, reportType, threshold)
}جميع دروس المنطق وتدفق التنفيذ
1تدفق التحكم المتقدم
جملة Switch مع `fallthrough`الخروج من الحلقات المتداخلةالاستمرار في حلقة محددةجملة `goto`ملخص - التحكم المتقدم في الحلقات2الـ Structs والميثودز (Methods)
تعريف الـ Methods على الـ Structsالـ Value Receiversالـ Pointer Receiversاختيار الـ Receiversالـ Methods مقابل الـ Functionsملخص - سلوك الـ Struct5تعمق في الـ Maps
Maps من نوع Structsالـ Pointers كقيم في الـ Mapsالتحقق من الـ Nil Mapsمقارنة الـ Mapsمراجعة - عداد تكرار الكلمات8مشروع: مخزون بسيط
نظرة عامة على المشروعالتحقق من المخزون3الواجهات (الأساسيات)
ما هي الواجهة؟تعريف الواجهةتطبيق الواجهةاستخدام أنواع الواجهاتالواجهة الفارغةتأكيدات النوع (Type Assertions)تبديل النوع (Type Switch)ملخص - الأشكال والسلوكياتتدرّب بنفسك: مترجم Go عبر الإنترنت