Menu
CoddyTech

Объединяем всё вместе

Часть раздела Логика и управление потоком путешествия по 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. Разобрать первое входное значение и инициализировать карту запасов имеющимися данными о товарах
  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, которая выводит отчёт, описанный ниже для операции "report"
  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]", где ошибка — "product already exists"
  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]", где ошибка — "product not found" или "insufficient stock", если новое количество будет меньше 0
  14. Для операции "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]" для каждого товара; если количество товара меньше порогового значения, вместо [OK] использовать [LOW STOCK]
  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)
}

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

Потренируйтесь самостоятельно: Онлайн-компилятор Go