package main
import (
"fmt"
"time"
)
type item struct {
name string
price int
amount int
}
type buyer struct {
point int
cart map[string]int
}
type delivery struct {
status string
products map[string]int
}
func newBuyer() *buyer {
tmp := new(buyer)
tmp.point = 1000000
tmp.cart = make(map[string]int ,0)
return tmp
}
func (b *buyer) buyItems(items []item, limits *int, d chan bool, tmpProd map[string]int) {
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
fmt.Println()
b.buyItems(items, limits, d, tmpProd)
}
}()
module := func (idx int) {
amount := 0
fmt.Print("수량을 입력하시오 : ")
fmt.Scanln(&amount)
fmt.Println()
if amount <= 0 {
panic("올바른 수량을 입력하세요.")
}
if b.point < items[idx].price * amount || items[idx].amount < amount {
panic("주문이 불가능합니다.")
} else {
for {
opt := 0
fmt.Println("1. 바로 주문\n2. 장바구니에 담기")
fmt.Print("실행할 기능을 입력하시오 : ")
fmt.Scanln(&opt)
fmt.Println()
if opt == 1 {
if *limits < 5 {
items[idx].amount -= amount
b.point -= items[idx].price * amount
tmpProd[items[idx].name] = amount
fmt.Println("상품 주문이 접수 되었습니다.")
*limits++
d <- true
break
} else {
fmt.Println("배송 한도를 초과했습니다. 배송이 완료되면 주문하세요.")
break
}
} else if opt == 2 {
already := false
for key := range b.cart {
if key == items[idx].name {
already = true
break
}
}
if already {
tmp := b.cart[items[idx].name] + amount
if tmp > items[idx].amount {
fmt.Println("물품의 잔여 수량을 초과했습니다.")
break
} else {
b.cart[items[idx].name] += amount
}
} else {
b.cart[items[idx].name] = amount
}
fmt.Println("상품이 장바구니에 추가 되었습니다.")
break
} else {
fmt.Println("잘못된 입력입니다. 다시 입력해주세요.\n")
}
}
}
}
for {
choice := 0
checkShop(items)
fmt.Print("구매할 물품을 선택하세요 : ")
fmt.Scanln(&choice)
fmt.Println()
if choice >= 1 && choice <= 5 {
module(choice - 1)
break
} else {
fmt.Println("잘못된 입력입니다. 다시 입력해주세요.\n")
}
}
}
func (b *buyer) checkPoint() {
fmt.Printf("현재 잔여 마일리지는 %d점입니다.\n", b.point)
}
func (b *buyer) checkCart(items []item, limits *int, d chan bool, tmpProd map[string]int) {
pointModule := func () (afford bool) {
cartTotal := 0
for key, val := range b.cart {
for i := 0; i < len(items); i++ {
if items[i].name == key {
cartTotal += items[i].price * val
}
}
}
fmt.Println("필요 마일리지 : ", cartTotal)
fmt.Println("보유 마일리지 : ", b.point)
fmt.Println()
if b.point < cartTotal {
fmt.Printf("마일리지가 %d점 부족합니다.\n", cartTotal - b.point)
fmt.Println()
return false
}
return true
}
amountModule := func() (afford bool) {
for key, val := range b.cart {
for i := 0; i < len(items); i++ {
if items[i].name == key {
if items[i].amount < val {
fmt.Printf("%s, 잔여 수량에서 %d개 초과", items[i].name, val - items[i].amount)
return false
}
}
}
}
return true
}
payModule := func() {
defer func() {
if r:= recover(); r != nil {
fmt.Println(r)
}
}()
if len(b.cart) == 0 {
panic("주문 가능한 목록이 없습니다.")
} else {
if (*limits < 5) {
for key, val := range b.cart {
tmpProd[key] = val
for i := range items {
if items[i].name == key {
items[i].amount -= val
b.point -= items[i].price * val
}
}
}
b.cart = make(map[string]int, 0)
fmt.Println("주문이 접수 되었습니다.")
*limits++
d <- true
} else {
fmt.Println("배송 한도를 초과했습니다. 배송이 완료되면 주문하세요.")
}
}
}
for {
if len(b.cart) == 0 {
fmt.Println("장바구니가 비었습니다.\n")
} else {
for key, val := range b.cart {
fmt.Printf("%s, 수량 : %d\n", key, val)
}
}
opt := 0
fmt.Println("1. 장바구니 상품 주문")
fmt.Println("2. 장바구니 초기화")
fmt.Println("3. 메뉴로 돌아가기")
fmt.Print("실행할 기능을 입력하시오 : ")
fmt.Scanln(&opt)
fmt.Println()
if opt == 1 {
pointAfford := pointModule()
amountAfford := amountModule()
if pointAfford && amountAfford {
payModule()
break
} else {
fmt.Println("구매할 수 없습니다.")
break
}
} else if opt == 2 {
b.cart = make(map[string]int, 0)
fmt.Println("장바구니를 초기화했습니다.")
break
} else if opt == 3 {
break
} else {
fmt.Println("잘못된 입력입니다. 다시 입력해주세요.")
}
}
}
func newDelivery() delivery {
tmp := delivery{}
tmp.products = make(map[string]int, 0)
return tmp
}
func initDelivery(list []delivery) {
for i := range list {
list[i] = newDelivery()
}
}
func initShop(items []item) {
items[0] = item{"텀블러", 10000, 30}
items[1] = item{"롱패딩", 500000, 20}
items[2] = item{"투미 백팩", 400000, 20}
items[3] = item{"나이키 운동화", 150000, 50}
items[4] = item{"빼빼로", 1200, 500}
}
func checkShop(items []item) {
for idx, i := range items {
fmt.Printf("물품 %d : %s, 가격 : %d, 잔여 수량 : %d\n", idx + 1, i.name, i.price, i.amount)
}
fmt.Println()
}
func checkDeliveryStatus(list []delivery) {
total := 0
for i := 0; i < 5; i++ {
total += len(list[i].products)
}
if total == 0 {
fmt.Println("배송 중인 상품이 없습니다.")
} else {
for i := range list {
if len(list[i].products) != 0 {
for key, val := range list[i].products {
fmt.Printf("%s %d개\n", key, val)
}
}
fmt.Printf("배송상황: %s\n", list[i].status)
}
fmt.Println()
}
}
func deliveryStatus(idx int, list []delivery, limits *int, d chan bool, tmpProd *map[string]int) {
for {
if <- d {
for key, val := range *tmpProd {
list[idx].products[key] = val
}
*tmpProd = make(map[string]int, 0)
list[idx].status = "주문접수"
time.Sleep(time.Second * 10)
list[idx].status = "배송 중"
time.Sleep(time.Second * 10)
list[idx].status = "배송 완료"
time.Sleep(time.Second * 10)
list[idx].status = ""
list[idx].products = make(map[string]int, 0)
*limits--
}
}
}
func main() {
jseo := newBuyer()
items := make([]item, 5)
initShop(items)
deliveryList := make([]delivery, 5)
initDelivery(deliveryList)
limits := 0
dch := make(chan bool)
tmpProd := make(map[string]int, 0)
for i := 0; i < 5; i++ {
time.Sleep(time.Millisecond)
go deliveryStatus(i, deliveryList, &limits, dch, &tmpProd)
}
for {
menu := 0
fmt.Println("1. 구매")
fmt.Println("2. 잔여 수량 확인")
fmt.Println("3. 잔여 마일리지 확인")
fmt.Println("4. 배송 상태 확인")
fmt.Println("5. 장바구니 확인")
fmt.Println("6. 프로그램 종료")
fmt.Print("실행할 기능을 입력하시오 : ")
fmt.Scanln(&menu)
fmt.Println()
switch menu {
case 1:
jseo.buyItems(items, &limits, dch, tmpProd)
fmt.Println("엔터를 입력하면 메뉴 화면으로 돌아갑니다.")
fmt.Scanln()
case 2:
checkShop(items)
fmt.Println("엔터를 입력하면 메뉴 화면으로 돌아갑니다.")
fmt.Scanln()
case 3:
jseo.checkPoint()
fmt.Println("엔터를 입력하면 메뉴 화면으로 돌아갑니다.")
fmt.Scanln()
case 4:
checkDeliveryStatus(deliveryList)
fmt.Println("엔터를 입력하면 메뉴 화면으로 돌아갑니다.")
fmt.Scanln()
case 5:
jseo.checkCart(items, &limits, dch, tmpProd)
fmt.Println("엔터를 입력하면 메뉴 화면으로 돌아갑니다.")
fmt.Scanln()
case 6:
fmt.Println("프로그램을 종료합니다.")
return
default:
fmt.Println("잘못된 입력입니다. 다시 입력해주세요.\n")
}
}
}
Go