إنشاء تقرير
جزء من قسم Logic & Flow في رحلة GO على Coddy — الدرس 49 من 68.
التحدي
سهلأكمل نظام إدارة المخزون الخاص بك من خلال تنفيذ وظيفة تقارير شاملة توفر رؤى تفصيلية حول مخزونك الحالي. يبني هذا التحدي على جميع الوظائف السابقة ويضيف القدرة على إنشاء تقارير منسقة مع الإحصائيات والتصنيف والتحليل.
ستتلقى مدخلين:
- سلسلة نصية تحتوي على بيانات المخزون الحالي بالتنسيق
"product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3"(على سبيل المثال،"Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8") - سلسلة نصية تحتوي على تكوين التقرير بالتنسيق
"report_type,threshold_value"حيث يمكن أن يكون report_type هو"full"، أو"low_stock"، أو"high_value"و threshold_value هو رقم (على سبيل المثال،"low_stock,10")
مهمتك هي:
- استخدام نفس هيكل
Productمن الدروس السابقة مع حقولPrice(float64) وQuantity(int) - تحليل المدخل الأول عن طريق التقسيم عند الفواصل للحصول على إدخالات المنتجات الفردية الموجودة
- لكل إدخال منتج موجود، قم بالتقسيم عند النقطتين الرأسيتين للحصول على اسم المنتج وسعره وكميته
- تحويل سلسلة السعر النصية إلى float64 وسلسلة الكمية النصية إلى int
- إنشاء وتعبئة خريطة
inventoryببيانات المنتجات الموجودة - إنشاء وظيفة تسمى
generateReportتأخذ خريطة المخزون ونوع التقرير وقيمة العتبة (threshold) كمعلمات - تحليل المدخل الثاني عن طريق التقسيم عند الفواصل للحصول على نوع التقرير وقيمة العتبة
- تحويل سلسلة قيمة العتبة النصية إلى float64
- عرض رأس التقرير بناءً على نوع التقرير:
- لـ
"full":"=== FULL INVENTORY REPORT ===" - لـ
"low_stock":"=== LOW STOCK REPORT ===" - لـ
"high_value":"=== HIGH VALUE REPORT ==="
- لـ
- عرض إحصائيات المخزون العامة:
"Total Products: [total_number_of_products]""Total Items in Stock: [sum_of_all_quantities]""Total Inventory Value: $[sum_of_price_times_quantity_for_all_products]""Average Product Price: $[total_inventory_value_divided_by_total_items]"
- تصفية وعرض المنتجات بناءً على نوع التقرير:
- لـ
"full": عرض جميع المنتجات - لـ
"low_stock": عرض المنتجات التي تكون كميتها أقل من أو تساوي قيمة العتبة فقط - لـ
"high_value": عرض المنتجات التي تكون قيمتها الإجمالية (السعر × الكمية) أكبر من أو تساوي قيمة العتبة فقط
- لـ
- عرض قسم المنتجات المصفاة:
- لـ
"full":"All Products:" - لـ
"low_stock":"Products with stock ≤ [threshold_value]:" - لـ
"high_value":"Products with value ≥ $[threshold_value]:"
- لـ
- لكل منتج مصفى (بالترتيب الأبجدي حسب اسم المنتج):
"- [product_name]: $[price] × [quantity] = $[total_value]"
- عرض الإحصائيات المصفاة:
"Filtered Results:""Products shown: [number_of_products_in_filtered_results]""Items in filtered products: [sum_of_quantities_for_filtered_products]""Value of filtered products: $[sum_of_values_for_filtered_products]"
- البحث عن وعرض المنتجات الأكثر والأقل سعراً:
"Price Analysis:""Most expensive: [product_name] at $[price]""Least expensive: [product_name] at $[price]"
- البحث عن وعرض المنتجات ذات المخزون الأعلى والأقل:
"Stock Analysis:""Highest stock: [product_name] with [quantity] units""Lowest stock: [product_name] with [quantity] units"
- عرض تقييم حالة المخزون:
- عد المنتجات ذات الكمية ≤ 5:
"Low stock items (≤5): [count]" - عد المنتجات ذات الكمية > 20:
"High stock items (>20): [count]" - عد المنتجات ذات القيمة ≥ $500:
"High value items (≥$500): [count]"
- عد المنتجات ذات الكمية ≤ 5:
- عرض اكتمال التقرير:
"Report generated successfully""Threshold applied: [threshold_value]"
استخدم حزمة strings لتقسيم السلاسل النصية المدخلة، وحزمة strconv لتحويل السلاسل النصية إلى أرقام، وحزمة fmt للإخراج المنسق، وحزمة sort لفرز أسماء المنتجات أبجدياً. قم بتنسيق جميع الأسعار والقيم إلى منزلتين عشريتين. عند البحث عن الأكثر/الأقل سعراً أو المخزون الأعلى/الأقل، إذا كان هناك تعادل، استخدم اسم المنتج الأول أبجدياً. يوضح هذا التحدي كيفية إنشاء أنظمة تقارير شاملة توفر رؤى تجارية قيمة من خلال تحليل البيانات والعرض المنسق.
جرّب بنفسك
package main
import (
"errors"
"fmt"
"sort"
"strconv"
"strings"
)
type Product struct {
Price float64
Quantity int
}
func updateStock(inventory map[string]Product, productName string, change int) error {
product, exists := inventory[productName]
if !exists {
return errors.New("product not found: " + productName)
}
newQuantity := product.Quantity + change
if newQuantity < 0 {
return fmt.Errorf("insufficient stock: cannot reduce %s by %d, only %d available", productName, -change, product.Quantity)
}
product.Quantity = newQuantity
inventory[productName] = product
return nil
}
func main() {
var inventoryData string
var updateRequests string
fmt.Scanln(&inventoryData)
fmt.Scanln(&updateRequests)
// Parse existing inventory
inventory := make(map[string]Product)
inventoryEntries := strings.Split(inventoryData, ",")
for _, entry := range inventoryEntries {
parts := strings.Split(entry, ":")
name := parts[0]
price, _ := strconv.ParseFloat(parts[1], 64)
quantity, _ := strconv.Atoi(parts[2])
inventory[name] = Product{
Price: price,
Quantity: quantity,
}
}
// Parse update requests
updateEntries := strings.Split(updateRequests, ",")
fmt.Println("Processing Stock Updates:")
totalUpdates := len(updateEntries)
successfulUpdates := 0
failedUpdates := 0
var failedProducts []string
for _, update := range updateEntries {
parts := strings.Split(update, ":")
productName := parts[0]
change, _ := strconv.Atoi(parts[1])
err := updateStock(inventory, productName, change)
if err != nil {
fmt.Printf("%s: Update failed - %s\n", productName, err.Error())
failedUpdates++
failedProducts = append(failedProducts, productName)
} else {
newQuantity := inventory[productName].Quantity
if change > 0 {
fmt.Printf("%s: Added %d units - New stock: %d\n", productName, change, newQuantity)
} else if change < 0 {
fmt.Printf("%s: Removed %d units - New stock: %d\n", productName, -change, newQuantity)
} else {
fmt.Printf("%s: No change - Current stock: %d\n", productName, newQuantity)
}
successfulUpdates++
}
}
// Update summary
fmt.Println("Update Summary:")
fmt.Printf("Updates processed: %d\n", totalUpdates)
fmt.Printf("Updates successful: %d\n", successfulUpdates)
fmt.Printf("Updates failed: %d\n", failedUpdates)
// Display updated inventory in alphabetical order
fmt.Println("Updated Inventory:")
var productNames []string
for name := range inventory {
productNames = append(productNames, name)
}
sort.Strings(productNames)
for _, name := range productNames {
product := inventory[name]
fmt.Printf("- %s: $%.2f (Stock: %d)\n", name, product.Price, product.Quantity)
}
// Calculate final statistics
totalProducts := len(inventory)
totalItems := 0
totalValue := 0.0
for _, product := range inventory {
totalItems += product.Quantity
totalValue += product.Price * float64(product.Quantity)
}
fmt.Println("Final Inventory 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)
// List failed updates
if len(failedProducts) > 0 {
fmt.Printf("Failed updates: %s\n", strings.Join(failedProducts, ","))
} else {
fmt.Println("All stock updates were processed successfully")
}
}جميع دروس Logic & Flow
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)ملخص - الأشكال والسلوكيات