Menu
CoddyTech

Kết hợp mọi thứ

Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 50 trên 68.

challenge icon

Thử thách

Dễ

Hoàn thiện hệ thống quản lý hàng tồn kho bằng cách tạo một chương trình chính toàn diện, tích hợp mọi chức năng bạn đã xây dựng trong các bài học trước. Thử thách cuối cùng này kết hợp việc khởi tạo hàng tồn kho, kiểm tra lượng hàng, thêm mặt hàng, cập nhật lượng hàng và tạo báo cáo thành một giao diện dòng lệnh hoàn chỉnh với thao tác điều hướng qua menu.

Bạn sẽ nhận ba đầu vào:

  • Một chuỗi chứa dữ liệu hàng tồn kho ban đầu theo định dạng "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3" (ví dụ: "Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8")
  • Một chuỗi chứa chuỗi thao tác trong menu theo định dạng "operation1,operation2,operation3", trong đó các thao tác có thể là "check", "add", "update", "report" hoặc "exit" (ví dụ: "check,add,update,report,exit")
  • Một chuỗi chứa các tham số thao tác theo định dạng "param1|param2|param3", trong đó mỗi tham số tương ứng với thao tác ở cùng vị trí (ví dụ: "Mouse|Monitor:299.99:10|Laptop:5|full,10")

Nhiệm vụ của bạn là:

  1. Dùng cùng cấu trúc Product như trong các bài học trước, với các trường Price (float64) và Quantity (int)
  2. Phân tích đầu vào thứ nhất và khởi tạo map hàng tồn kho với dữ liệu sản phẩm hiện có
  3. Hiển thị thông báo khởi động hệ thống:
    • "=== INVENTORY MANAGEMENT SYSTEM ==="
    • "System initialized with [number_of_products] products"
    • "Starting interactive session..."
  4. Phân tích đầu vào thứ hai để lấy chuỗi thao tác cần thực hiện
  5. Phân tích đầu vào thứ ba để lấy tham số cho từng thao tác
  6. Với mỗi thao tác theo thứ tự, hiển thị tiêu đề thao tác và thực hiện hành động tương ứng:
    • Với "check": Hiển thị "--- STOCK CHECK ---" và kiểm tra lượng hàng của sản phẩm được chỉ định
    • Với "add": Hiển thị "--- ADD ITEM ---" và thêm sản phẩm được chỉ định
    • Với "update": Hiển thị "--- UPDATE STOCK ---" và cập nhật lượng hàng của sản phẩm được chỉ định
    • Với "report": Hiển thị "--- GENERATE REPORT ---" và tạo báo cáo được chỉ định
    • Với "exit": Hiển thị "--- SYSTEM EXIT ---" và thông tin thoát
  7. Cài đặt hàm checkStock trả về số lượng và lỗi như trong các bài học trước
  8. Cài đặt hàm addNewItem để thêm sản phẩm và trả về lỗi như trong các bài học trước
  9. Cài đặt hàm updateStock để cập nhật số lượng và trả về lỗi như trong các bài học trước
  10. Cài đặt hàm generateReport để in báo cáo được mô tả bên dưới trong thao tác "report"
  11. Với thao tác "check":
    • Dùng tham số làm tên sản phẩm cần kiểm tra
    • Hiển thị: "Checking stock for: [product_name]"
    • Nếu tìm thấy: "Stock level: [quantity] units"
    • Nếu không tìm thấy: "Product not found in inventory"
  12. Với thao tác "add":
    • Phân tích tham số theo định dạng "product_name:price:quantity"
    • Hiển thị: "Adding new product: [product_name]"
    • Nếu thành công: "Product added successfully"
    • Nếu thất bại: "Failed to add product: [error_message]", trong đó lỗi là "product already exists"
  13. Với thao tác "update":
    • Phân tích tham số theo định dạng "product_name:change"
    • Hiển thị: "Updating stock for: [product_name]"
    • Nếu thành công và change bằng không hoặc lớn hơn không: "Added [change] units. New stock: [new_quantity]"
    • Nếu thành công và change nhỏ hơn không: "Removed [absolute_change] units. New stock: [new_quantity]"
    • Nếu thất bại: "Update failed: [error_message]", trong đó lỗi là "product not found" hoặc "insufficient stock" nếu số lượng mới nhỏ hơn 0
  14. Với thao tác "report":
    • Phân tích tham số theo định dạng "report_type,threshold", trong đó report_type là "low" hoặc "full", còn threshold là một số nguyên
    • Hiển thị: "Generating [report_type] report with threshold [threshold]"
    • Sau đó in báo cáo, sắp xếp sản phẩm theo thứ tự bảng chữ cái:
      • Với "low": "=== LOW REPORT ===", sau đó là "Products with stock below [threshold]:", rồi đến "- [name]: [quantity] units (Price: $[price])" cho mỗi sản phẩm có số lượng nhỏ hơn ngưỡng
      • Với "full": "=== FULL REPORT ===", sau đó là "Complete inventory (minimum threshold: [threshold]):", rồi đến "- [name]: [quantity] units @ $[price] each [OK]" cho mọi sản phẩm, dùng [LOW STOCK] thay cho [OK] khi số lượng nhỏ hơn ngưỡng
  15. Với thao tác "exit":
    • Hiển thị thống kê hàng tồn kho cuối cùng:
      • "Final inventory status:"
      • "Total products: [total_products]"
      • "Total items: [total_items]"
      • "Total value: $[total_value]"
    • Hiển thị: "Session completed successfully"
    • Hiển thị: "Thank you for using the Inventory Management System"
  16. Sau mỗi thao tác, ngoại trừ exit, hiển thị: "Operation completed. Continuing to next operation..."

Dùng package strings để tách các chuỗi đầu vào, package strconv để chuyển chuỗi thành số, package errors để xử lý lỗi, package fmt để định dạng đầu ra và package sort để sắp xếp theo thứ tự bảng chữ cái. Định dạng tất cả giá và giá trị với 2 chữ số thập phân. Thử thách này cho thấy cách tạo một hệ thống tương tác hoàn chỉnh, tích hợp nhiều thành phần chức năng thành trải nghiệm liền mạch, đồng thời xử lý lỗi và quản lý trạng thái phù hợp.

Tự làm thử

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

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch Go online