Menu
Coddy logo textTech

하나로 합치기

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. 이전 레슨과 동일하게 Price (float64) 및 Quantity (int) 필드를 가진 Product 구조체를 사용합니다.
  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 함수를 구현합니다.
  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. 각 작업(종료 제외) 후에 다음을 표시합니다: "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)
}

로직 & 흐름의 모든 레슨