Menu
CoddyTech

하나로 합치기

Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨. 68개 중 50번째.

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. 아래의 "report" 작업에서 설명하는 보고서를 출력하는 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]"를 표시합니다. 오류는 "product already exists"입니다.
  13. "update" 작업의 경우:
    • 매개변수를 "product_name:change" 형식으로 구문 분석합니다.
    • "Updating stock for: [product_name]"을 표시합니다.
    • 성공했고 change가 0 이상이면 "Added [change] units. New stock: [new_quantity]"를 표시합니다.
    • 성공했고 change가 음수이면 "Removed [absolute_change] units. New stock: [new_quantity]"를 표시합니다.
    • 실패하면 "Update failed: [error_message]"를 표시합니다. 오류는 "product not found"이거나 새 수량이 0 미만이 되는 경우 "insufficient stock"입니다.
  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]:"를 출력하고, 수량이 threshold 미만인 각 제품에 대해 "- [name]: [quantity] units (Price: $[price])"를 출력합니다.
      • "full"의 경우: 먼저 "=== FULL REPORT ==="를 출력한 다음 "Complete inventory (minimum threshold: [threshold]):"를 출력하고, 모든 제품에 대해 "- [name]: [quantity] units @ $[price] each [OK]"를 출력합니다. 수량이 threshold 미만이면 [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 컴파일러