Menu
Coddy logo textTech

Объединение всех частей

Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 50 из 68.

challenge icon

Задание

Легко

Завершите создание вашей системы управления запасами, разработав комплексную основную программу, которая объединяет все функциональные возможности, созданные в предыдущих уроках. Это финальное испытание объединяет инициализацию инвентаря, проверку остатков, добавление товаров, обновление запасов и генерацию отчетов в полноценный интерфейс командной строки с навигацией через меню.

Вы получите три входных параметра:

  • Строку, содержащую начальные данные инвентаря в формате "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")

Ваша задача:

  1. Использовать ту же структуру Product из предыдущих уроков с полями Price (float64) и Quantity (int)
  2. Разобрать первый входной параметр и инициализировать карту (map) инвентаря существующими данными о продуктах
  3. Вывести сообщение о запуске системы:
    • "=== INVENTORY MANAGEMENT SYSTEM ==="
    • "System initialized with [number_of_products] products"
    • "Starting interactive session..."
  4. Разобрать второй входной параметр, чтобы получить последовательность выполняемых операций
  5. Разобрать третий входной параметр, чтобы получить параметры для каждой операции
  6. Для каждой операции в последовательности вывести заголовок операции и выполнить соответствующее действие:
    • Для "check": Вывести "--- STOCK CHECK ---" и проверить наличие указанного продукта
    • Для "add": Вывести "--- ADD ITEM ---" и добавить указанный продукт
    • Для "update": Вывести "--- UPDATE STOCK ---" и обновить запас указанного продукта
    • Для "report": Вывести "--- GENERATE REPORT ---" и сгенерировать указанный отчет
    • Для "exit": Вывести "--- SYSTEM EXIT ---" и показать информацию о выходе
  7. Реализовать функцию checkStock, которая возвращает количество и ошибку, как в предыдущих уроках
  8. Реализовать функцию addNewItem, которая добавляет продукты и возвращает ошибку, как в предыдущих уроках
  9. Реализовать функцию updateStock, которая обновляет количество и возвращает ошибку, как в предыдущих уроках
  10. Реализовать функцию generateReport, которая создает отчеты, как в предыдущих уроках
  11. Для операции "check":
    • Использовать параметр как название продукта для проверки
    • Вывести: "Checking stock for: [product_name]"
    • Если найден: "Stock level: [quantity] units"
    • Если не найден: "Product not found in inventory"
  12. Для операции "add":
    • Разобрать параметр в формате "product_name:price:quantity"
    • Вывести: "Adding new product: [product_name]"
    • В случае успеха: "Product added successfully"
    • В случае ошибки: "Failed to add product: [error_message]"
  13. Для операции "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]"
  14. Для операции "report":
    • Разобрать параметр в формате "report_type,threshold"
    • Вывести: "Generating [report_type] report with threshold [threshold]"
    • Сгенерировать и вывести полный отчет, как в предыдущих уроках
  15. Для операции "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"
  16. После каждой операции (кроме exit) выводить: "Operation completed. Continuing to next operation..."

Используйте пакет strings для разделения входных строк, пакет strconv для преобразования строк в числа, пакет errors для обработки ошибок, пакет fmt для форматированного вывода и пакет sort для алфавитной сортировки. Форматируйте все цены и значения до 2 знаков после запятой. Это испытание демонстрирует, как создать полноценную интерактивную систему, объединяющую несколько функциональных компонентов в единый пользовательский интерфейс с правильной обработкой ошибок и управлением состоянием.

Попробуйте сами

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

Все уроки раздела Логика и управление потоком