251222 TIL - C++ 11일차

2025. 12. 22. 21:55언리얼 7기 본캠프

오늘은 추가적으로 배운건 없고 대신 과제를 마무리하는데 급급함... 4번과제의 도전 내용이 생각보다 어려웠지만 꼭 시도해보고싶어서 하루종일 잡고있었음

3번 과제와 4번 과제의 코드를 미리 공유함

 

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

class Item {
protected :
	string name_;
	int price_ = 0;
public :
	Item() : name_(""), price_(0) {} // 임시 생성자
	Item(string name, int price) { //입력받아서만 만드는 클래스기에 해당 생성자 내부에선 유효성 검사를 하지 않음
		name_ = name;
		price_ = price;
	}
	~Item() {}

	string getName() const {
		return name_;
	}
	int getPrice() const {
		return price_;
	}
	virtual void PrintInfo() const {
		cout << "[이름: " << name_ << ", 가격: " << price_ << "G]" << endl;
	}
};

bool compareItemsByPrice(const Item& a, const Item& b) {
	return a.getPrice() < b.getPrice();
}

template <typename T>
class Inventory {
private :
	T* pItems_;
	int capacity_ = 0;
	int size_ = 0;
public:
	Inventory(int capacity = 10) {
		if (capacity < 1) { // cap 최소값 1
			capacity_ = 1;
		}
		else capacity_ = capacity;
		pItems_ = new T[capacity_];
	}
	Inventory(const Inventory<T>& other) {
		capacity_ = other.capacity_;
		size_ = other.size_;
		pItems_ = new T[capacity_];
		for (int i = 0; i < size_; ++i) {
			pItems_[i] = other.pItems_[i];
		}
		cout << "인벤토리 복사 완료" << endl;
	}
	~Inventory() {
		delete[] pItems_;
		pItems_ = nullptr;
	}
	void addItem(const T& item) {
		if (size_ < capacity_) {
			pItems_[size_] = item;
			cout << "아이템 " << item.getName() << "이(가) 인벤토리에 추가되었습니다." << endl;
			size_++;
		}
		else { // 가득 찼을 시 2배 확장하고 추가
			int tCap = capacity_ * 2;
			T* temp = new T[tCap]; // 2배 증가한 임시배열 생성
			for (int i = 0; i < capacity_; i++) { // 복사
				temp[i] = pItems_[i];
			}
			delete[] pItems_; // 기존 배열 제거
			pItems_ = temp; // pItems_ 포인터를 새로만든 배열에 가리키기
			capacity_ *= 2;
			pItems_[size_] = item;
			cout << "인벤토리가 가득 찼습니다. 자동으로 인벤토리 크기를 2배(" << capacity_ << ")로 확장하였고, 아이템 " << item.getName() << "이(가) 인벤토리에 추가되었습니다." << endl;
			size_++;
		}
	}
	void removeLastItem() {
		if (size_ > 0) {
			cout << "아이템 " << pItems_[size_ - 1].getName() << " 이(가) 인벤토리에서 제거되었습니다." << endl;
			size_--;
		}
		else cout << "인벤토리가 비어있습니다." << endl;
	}
	int getSize() const {
		return size_;
	}
	int getCapacity() const {
		return capacity_;
	}
	void printAllItems() const {
		if (size_ <= 0) {
			cout << "=== 인벤토리 내용물 ===" << endl;
			cout << "(비어있음)" << endl;
			cout << "======================" << endl;
		}
		else {
			cout << "=== 인벤토리 내용물 ===" << endl;
			for (int i = 0; i < size_; i++)	pItems_[i].PrintInfo();
			cout << "======================" << endl;
		}
	}
	void assign(const Inventory<T>& other) {
		if (this == &other) return; // 셀프 붙여넣기 방지
		if (pItems_ != nullptr) { // 메모리 삭제
			delete[] pItems_;
		}
		capacity_ = other.capacity_;
		size_ = other.size_;
		pItems_ = new T[capacity_]; // 복사 대상 크기에 맞춰 인벤토리 재생성
		for (int i = 0; i < other.getSize(); i++) { // 아이템 붙여넣기
			pItems_[i] = other.pItems_[i];
		}
		cout << "인벤토리 붙여넣기 완료" << endl;
	}
	void resize(int newCapacity) {
		if (newCapacity < size_) { // 유효성 검사 : 입력한 수가 size보다 적을 경우
			cout << "현재 인벤토리에 있는 아이템 수(" << size_ << ")보다 작게 수정할 수 없습니다!" << endl;
			return;
		}
		if (newCapacity == capacity_) { // 유효성 검사 : 입력한 수가 현재 capacity와 동일할 경우(불필요한 연산 미처리)
			cout << "변경하려는 인벤토리 크기가 현재 인벤토리 크기와 동일합니다." << endl;
			return;
		}
		capacity_ = newCapacity;
		T* temp = new T[capacity_]; // newCapacity 크기만큼의 배열을 다시 만들어서 복사하는 과정
		for (int i = 0; i < size_; i++) {
			temp[i] = pItems_[i];
		}
		delete[] pItems_;
		pItems_ = temp;
		cout << "인벤토리의 크기가 " << capacity_ << "로 변경되었습니다." << endl;
	}
	void SortItems() {
		if (size_ <= 1) { // 유효성 검사 : 아이템이 1개 이하일때(정렬할 필요 없음)
			cout << "정렬을 수행하기에는 아이템 수가 너무 적습니다." << endl;
			return;
		}
		sort(pItems_, pItems_ + size_, compareItemsByPrice);
		cout << "인벤토리의 아이템들이 가격 오름차순으로 정렬되었습니다." << endl;
	}
};



int main() {
	cout << "25칸 인벤토리를 생성합니다." << endl;
	Inventory<Item>* inventory = new Inventory<Item>(25);
	for (int i = 1; i <= 10; i++) { // 기본 아이템 10개 생성 시도
		inventory->addItem(Item::Item("아이템" + to_string(i), i * 100));
	}
	inventory->printAllItems(); // 아이템 전체 출력
	inventory->removeLastItem(); // 마지막 아이템 2개 제거
	inventory->removeLastItem();
	inventory->addItem(Item::Item("왕비싼아이템", 100000)); // 임의 아이템 추가
	inventory->printAllItems();
	cout << "현재 아이템 갯수: " << inventory->getSize() << endl; // 아이템 갯수와 인벤토리 크기 체크
	cout << "현재 인벤토리 크기: " << inventory->getCapacity() << endl;
	for (int i = inventory->getSize(), j = 1; i < inventory->getCapacity(); i++, j++) { // 인벤토리를 가득 채울때까지 완전싼아이템 추가
		inventory->addItem(Item::Item("완전싼아이템" + to_string(j), j * 10));
	}
	cout << "현재 아이템 갯수: " << inventory->getSize() << endl;
	cout << "현재 인벤토리 크기: " << inventory->getCapacity() << endl;
	inventory->printAllItems();
	inventory->addItem(Item::Item("초왕비싼아이템", 1000000)); // 이 시점에서 인벤토리가 가득 차있기때문에 2배 자동확장 체크
	cout << "현재 아이템 갯수: " << inventory->getSize() << endl;
	cout << "현재 인벤토리 크기: " << inventory->getCapacity() << endl;
	inventory->printAllItems();
	inventory->resize(1); // 현재 아이템 갯수보다 적은 수를 넣으면 경고문을 반환 체크
	inventory->resize(26); // 26/26으로 변환
	cout << "현재 아이템 갯수: " << inventory->getSize() << endl;
	cout << "현재 인벤토리 크기: " << inventory->getCapacity() << endl;
	inventory->SortItems(); // 가격 오름차순 정렬
	inventory->printAllItems(); // 정렬 확인
	Inventory<Item>* inventory2 = new Inventory<Item>(*inventory); // 인벤2로 인벤1 복사
	inventory2->printAllItems(); //인벤2 내용물 체크
	for (int i = inventory->getSize(); i > 0; i--) { // 인벤1 내용물 전부 제거
		inventory->removeLastItem();
	}
	inventory->printAllItems(); // 1은 텅텅 2는 가득
	inventory2->printAllItems();
	inventory->assign(*inventory2); // 2를 1로 붙여넣기
	inventory->printAllItems(); // 1 인벤토리 확인
	return 0;
}

 

 

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>

// PotionRecipe 클래스: 재료 목록을 vector<string>으로 변경
class PotionRecipe {
public:
    std::string potionName;
    std::vector<std::string> ingredients; // 단일 재료에서 재료 '목록'으로 변경

    // 생성자: 재료 목록을 받아 초기화하도록 수정
    PotionRecipe(const std::string& name, const std::vector<std::string>& ingredients)
        : potionName(name), ingredients(ingredients) {
    }
    PotionRecipe() : potionName(""), ingredients() {}
};

class RecipeManager {
private:
    std::vector<PotionRecipe> recipes;
public:
    // addRecipe 메서드: 재료 목록(vector)을 매개변수로 받도록 수정
    PotionRecipe* addRecipe(const std::string& name, const std::vector<std::string>& ingredients) {
        std::vector<std::string> sortedIngre = ingredients;
        std::sort(sortedIngre.begin(), sortedIngre.end());

        for (auto& recipe : recipes) {
            std::vector<std::string> sortedExistIngre = recipe.ingredients;
            std::sort(sortedExistIngre.begin(), sortedExistIngre.end());
            if (sortedIngre == sortedExistIngre) { // 재료가 들어간 순서가 달라도 구성이 완전히 동일하면 만들 수 없게 판정
                std::cout << "재료 구성이 완전히 동일한 포션은 만들 수 없습니다." << std::endl;
                return nullptr;
            }
        }
        recipes.push_back(PotionRecipe(name, ingredients));
        return &recipes.back();
    }

    PotionRecipe* searchRecipeByName(const std::string& name) {
        for (auto& recipe : recipes) {
            if (recipe.potionName == name) {
                return &recipe;
            }
        }
        return nullptr;
    }

    std::vector<PotionRecipe> searchRecipeByIngredient(const std::string& ingredient) {
        std::vector<PotionRecipe> result;
        for (const auto& recipe : recipes) {
            for (const auto& listedIngred : recipe.ingredients) {
                if (listedIngred == ingredient) {
                    result.push_back(recipe);
                    break;
                }
            }
        }
        return result;
    }

    const std::vector<PotionRecipe>& getAllRecipes() const {
        return recipes;
    }
};
class StockManager {
private:
    static constexpr int MAX_STOCK = 3;
    std::map<std::string, int> potionStock;
public:
    void initializeStock(const std::string& potionName) {
        potionStock[potionName] = 3;
    }

    bool dispensePotion(const std::string& potionName) {
        auto it = potionStock.find(potionName);
        if (it == potionStock.end()) {
            std::cout << "경고: 존재하지 않는 포션명입니다. 포션을 배포할 수 없습니다." << std::endl;
            return false;
        }
        if (it != potionStock.end() && it->second > 0) {
            it->second -= 1;
            std::cout << "포션 " << potionName << "을(를) 1개 배포하였습니다." << std::endl;
            return true;
        }
        else if (it != potionStock.end() && it->second <= 0) {
            std::cout << "경고: 포션 " << potionName << "의 재고가 부족합니다. 포션을 배포할 수 없습니다." << std::endl;
            return false;
        }
    }

    void returnPotion(const std::string& potionName) {
        auto it = potionStock.find(potionName);
        if (it == potionStock.end()) {
            std::cout << "경고: 존재하지 않는 포션명입니다. 포션을 반납할 수 없습니다." << std::endl;
            return;
        }
        if (it != potionStock.end() && it->second < MAX_STOCK) {
            it->second += 1;
            std::cout << potionName << "을(를) 1개 반납했습니다." << std::endl;
        }
        else if (it != potionStock.end() && it->second >= MAX_STOCK) {
            std::cout << "경고: 포션의 재고는 " << MAX_STOCK << "개를 넘을 수 없습니다. " << potionName << "을(를) 반납할 수 없습니다." << std::endl;
        }
    }

    int getStock(const std::string& potionName) const {
        auto it = potionStock.find(potionName);
        if (it == potionStock.end()) {
            return 0;
        }
        if (it != potionStock.end()) {
            return it->second;
        }
    }
};

// AlchemyWorkshop 클래스: 레시피 목록을 관리
class AlchemyWorkshop {
private:
    RecipeManager recipeManager_;
    StockManager stockManager_;
public:
    // addRecipe 메서드: 재료 목록(vector)을 매개변수로 받도록 수정
    void addRecipe(const std::string& name, const std::vector<std::string>& ingredients) {
        PotionRecipe* nameDupeCheck = recipeManager_.searchRecipeByName(name);
        if (nameDupeCheck != nullptr) {
            std::cout << "중복된 이름의 포션은 만들 수 없습니다." << std::endl;
            return;
        }
        PotionRecipe* ingreDupeCheck = recipeManager_.addRecipe(name, ingredients);
        if (ingreDupeCheck == nullptr) {
            return;
        }
        stockManager_.initializeStock(name);
        std::cout << ">> 새로운 레시피 '" << name << "'이(가) 추가되었고, " << name << "의 재고 3개가 추가되었습니다." << std::endl;
    }

    // 모든 레시피 출력 메서드
    void displayAllRecipes() const {
        if (recipeManager_.getAllRecipes().empty()) {
            std::cout << "아직 등록된 레시피가 없습니다." << std::endl;
            return;
        }

        std::cout << "\n--- [ 전체 레시피 목록 ] ---" << std::endl;
        for (size_t i = 0; i < recipeManager_.getAllRecipes().size(); ++i) {
            std::cout << "- 물약 이름: " << recipeManager_.getAllRecipes()[i].potionName << std::endl;
            std::cout << "  > 필요 재료: ";

            // 재료 목록을 순회하며 출력
            for (size_t j = 0; j < recipeManager_.getAllRecipes()[i].ingredients.size(); ++j) {
                std::cout << recipeManager_.getAllRecipes()[i].ingredients[j];
                // 마지막 재료가 아니면 쉼표로 구분
                if (j < recipeManager_.getAllRecipes()[i].ingredients.size() - 1) {
                    std::cout << ", ";
                }
            }
            std::cout << std::endl;
            std::cout << "  > 남은 재고: " << stockManager_.getStock(recipeManager_.getAllRecipes()[i].potionName) << "개" << std::endl;
        }
        std::cout << "---------------------------\n";
    }

    PotionRecipe* searchRecipeByName(const std::string& name) {
        PotionRecipe* result = recipeManager_.searchRecipeByName(name);
        return result;
    }

    std::vector<PotionRecipe> searchRecipeByIngredient(const std::string& ingredient) {
        std::vector<PotionRecipe> result = recipeManager_.searchRecipeByIngredient(ingredient);
        return result;
    }
    
    int getStockByName(const std::string& potionName) const {
        return stockManager_.getStock(potionName);
    }

    bool dispensePotionByName(const std::string& potionName) {
        return stockManager_.dispensePotion(potionName);
    }

    std::vector<std::string> dispensePotionByIngredient(const std::string& ingredient) {
        std::vector<PotionRecipe> searchResult = recipeManager_.searchRecipeByIngredient(ingredient);
        std::vector<std::string> dispenseResult;
        for (auto& recipe : searchResult) {
            if (stockManager_.dispensePotion(recipe.potionName)) {
                dispenseResult.push_back(recipe.potionName);
            }
        }
        return dispenseResult; // 없으면 빈 벡터
    }

    void returnPotionByName(const std::string& potionName) {
        stockManager_.returnPotion(potionName);
    }
};

void searchSystem(AlchemyWorkshop& workshop) {
    int choice = 0;
    while (true) {
        std::cout << "\n1. 레시피 이름으로 검색하기" << std::endl;
        std::cout << "2. 포함된 재료로 검색하기" << std::endl;
        std::cout << "3. 이전 메뉴로 돌아가기" << std::endl;
        std::cin >> choice;

        if (std::cin.fail()) {
            std::cout << "잘못된 입력입니다. 숫자를 입력해주세요." << std::endl;
            std::cin.clear();
            std::cin.ignore(10000, '\n');
            continue;
        }
        std::cin.ignore(10000, '\n');

        if (choice == 1) {
            std::string nameInput = "";
            std::cout << "검색할 레시피의 이름을 적어주세요: ";
            getline(std::cin, nameInput);
            PotionRecipe* result = workshop.searchRecipeByName(nameInput);
            if (result == nullptr) {
                std::cout << "검색 결과가 없습니다." << std::endl;
                continue;
            }
            else {
                std::cout << "\n===검색 결과===" << std::endl;
                std::cout << "- 물약 이름: " << result->potionName << std::endl;
                std::cout << "  > 필요 재료: ";
                for (size_t i = 0; i < result->ingredients.size(); ++i) {
                    std::cout << result->ingredients[i];
                    if (i < result->ingredients.size() - 1) {
                        std::cout << ", ";
                    }
                }
                std::cout << std::endl;
                std::cout << "  > 남은 재고: " << workshop.getStockByName(result->potionName) << std::endl;
            }
        }
        else if (choice == 2) {
            std::string ingreInput = "";
            std::cout << "검색할 재료의 이름을 적어주세요: ";
            getline(std::cin, ingreInput);
            std::vector<PotionRecipe> result = workshop.searchRecipeByIngredient(ingreInput);
            if (result.empty()) {
                std::cout << "검색 결과가 없습니다." << std::endl;
                continue;
            }
            else {
                for (auto& recipe : result) {
                    std::cout << "\n===검색 결과===" << std::endl;
                    std::cout << "- 물약 이름: " << recipe.potionName << std::endl;
                    std::cout << "  > 필요 재료: ";
                    for (size_t i = 0; i < recipe.ingredients.size(); ++i) {
                        std::cout << recipe.ingredients[i];
                        if (i < recipe.ingredients.size() - 1) {
                            std::cout << ", ";
                        }
                    }
                    std::cout << std::endl;
                    std::cout << "  > 남은 재고: " << workshop.getStockByName(recipe.potionName) << std::endl;
                }
            }
        }
        else if (choice == 3) {
            std::cout << "이전 메뉴로 돌아갑니다." << std::endl;
            break;
        }
    }
}

void geminiStressTestSystem(AlchemyWorkshop& workshop) {
    std::cout << "\n========================================" << std::endl;
    std::cout << "   🧪 [gemini's STRESS TEST MODULE] START  " << std::endl;
    std::cout << "========================================" << std::endl;

    // [TEST 1] 레시피 중복 등록 방어 로직 검증
    std::cout << "\n[TEST 1] 레시피 중복(이름/재료) 방어 테스트" << std::endl;

    // 1-1. 정상 등록
    std::cout << "1. 기본 레시피 '테스트물약A' 등록 (Water, Herb) -> ";
    workshop.addRecipe("테스트물약A", { "Water", "Herb" });
    // 검증: 등록 후 재고가 3이어야 함
    if (workshop.getStockByName("테스트물약A") == 3) std::cout << "[PASS] 정상 등록됨." << std::endl;
    else std::cout << "[FAIL] 등록 실패 또는 재고 초기화 오류." << std::endl;

    // 1-2. 이름 중복 시도
    std::cout << "2. '테스트물약A' 이름 중복 등록 시도 -> ";
    workshop.addRecipe("테스트물약A", { "DarkMatter" }); // 이름 같음, 재료 다름
    // 로그상 "중복된 이름..."이 뜨고, 재고는 여전히 3이어야 함(초기화 재실행 안 됨)

    // 1-3. 재료 구성 중복(순서 섞음) 시도
    std::cout << "3. '테스트물약B' 재료 중복(순서 바꿈) 등록 시도 (Herb, Water) -> ";
    workshop.addRecipe("테스트물약B", { "Herb", "Water" });
    // 선생님의 로직대로라면 "재료 구성이 완전히 동일한..."이 뜨고 등록되지 않아야 함
    if (workshop.getStockByName("테스트물약B") == 0) std::cout << "[PASS] 재료 중복 걸러냄 (순서 무관 확인)." << std::endl;
    else std::cout << "[FAIL] 재료가 중복되었는데 등록되어버림." << std::endl;


    // [TEST 2] 재고 관리의 극한(Min/Max) 테스트
    std::cout << "\n[TEST 2] 재고 경계값(0~3) 테스트" << std::endl;

    // 2-1. 재고 바닥내기
    std::cout << "1. '테스트물약A' 3회 연속 배포 (현재 3개)" << std::endl;
    workshop.dispensePotionByName("테스트물약A");
    workshop.dispensePotionByName("테스트물약A");
    workshop.dispensePotionByName("테스트물약A"); // 0개 됨

    // 2-2. 없는 재고 배포 시도
    std::cout << "2. 재고 0개 상태에서 추가 배포 시도 -> ";
    bool result = workshop.dispensePotionByName("테스트물약A");
    if (result == false) std::cout << "[PASS] 배포 거부됨 (False 반환 확인)." << std::endl;
    else std::cout << "[FAIL] 없는 재고가 배포됨 (논리 오류)." << std::endl;

    // 2-3. 공병 반납 및 최대치 초과 테스트
    std::cout << "3. 공병 4회 연속 반납 시도 (최대 스톡 3 제한 확인)" << std::endl;
    workshop.returnPotionByName("테스트물약A"); // 1
    workshop.returnPotionByName("테스트물약A"); // 2
    workshop.returnPotionByName("테스트물약A"); // 3
    std::cout << "   >> (4번째 반납 시도 - 경고 떠야 함) -> ";
    workshop.returnPotionByName("테스트물약A"); // 3 유지

    if (workshop.getStockByName("테스트물약A") == 3) std::cout << "[PASS] 재고 3개에서 멈춤 (Max Cap 확인)." << std::endl;
    else std::cout << "[FAIL] 재고가 3개를 초과함 (" << workshop.getStockByName("테스트물약A") << "개)." << std::endl;


    // [TEST 3] 재료 기반 일괄 배포 테스트 (심화 기능)
    std::cout << "\n[TEST 3] 재료 기반 일괄 검색 및 배포 테스트" << std::endl;

    // 환경 조성
    workshop.addRecipe("화염구", { "Fire", "Ash" });
    workshop.addRecipe("화염벽", { "Fire", "Coal" });
    // 둘 다 "Fire"를 가짐. 현재 재고 각각 3개.

    std::cout << "1. 'Fire' 재료가 든 모든 포션 배포 시도 (화염구, 화염벽)" << std::endl;
    std::vector<std::string> dispensed = workshop.dispensePotionByIngredient("Fire");

    std::cout << "   >> 배포된 물약 개수: " << dispensed.size() << "개 (기대값: 2)" << std::endl;
    if (dispensed.size() == 2) {
        std::cout << "[PASS] 정확한 개수가 배포됨." << std::endl;
    }
    else {
        std::cout << "[FAIL] 배포된 개수가 이상함." << std::endl;
    }

    std::cout << "2. 배포 후 재고 확인 (각각 2개여야 함)" << std::endl;
    int stock1 = workshop.getStockByName("화염구");
    int stock2 = workshop.getStockByName("화염벽");
    std::cout << "   >> 화염구: " << stock1 << ", 화염벽: " << stock2 << std::endl;

    if (stock1 == 2 && stock2 == 2) std::cout << "[PASS] 재고 차감 계산 정확함." << std::endl;
    else std::cout << "[FAIL] 재고 차감 계산 오류." << std::endl;

    std::cout << "\n========================================" << std::endl;
    std::cout << "   🧪 [gemini's STRESS TEST MODULE] END    " << std::endl;
    std::cout << "========================================" << std::endl;
}

void spartaStressTestSystem(AlchemyWorkshop& workshop) {
    workshop.addRecipe("Healing Potion", { "Herb", "Water" });
    workshop.addRecipe("Mana Potion", { "Magic Water", "Crystal" });
    workshop.addRecipe("Stamina Potion", { "Herb", "Berry" });
    workshop.addRecipe("Fire Resistance Potion", { "Fire Flower", "Ash" });

    std::cout << "=== 초기 상태 (레시피 추가 + 재고 자동 3개) ===\n";
    workshop.displayAllRecipes();

    std::cout << "\n[재고 확인] Healing Potion 재고: "
        << workshop.getStockByName("Healing Potion") << "\n";

    std::cout << "\n=== 이름으로 지급 테스트 (Healing Potion 3회 지급) ===\n";
    std::cout << "1회 지급: " << (workshop.dispensePotionByName("Healing Potion") ? "성공" : "실패") << "\n";
    std::cout << "2회 지급: " << (workshop.dispensePotionByName("Healing Potion") ? "성공" : "실패") << "\n";
    std::cout << "3회 지급: " << (workshop.dispensePotionByName("Healing Potion") ? "성공" : "실패") << "\n";

    std::cout << "현재 재고: " << workshop.getStockByName("Healing Potion") << "\n";

    std::cout << "4회 지급(재고 없으면 실패): "
        << (workshop.dispensePotionByName("Healing Potion") ? "성공" : "실패") << "\n";

    std::cout << "\n=== 재료로 지급 테스트 (ingredient = Herb) ===\n";
    std::vector<std::string> dispensed = workshop.dispensePotionByIngredient("Herb");

    std::cout << "지급된 물약 수: " << dispensed.size() << "\n";
    for (const std::string& name : dispensed)
        std::cout << "- " << name << "\n";

    std::cout << "\n=== 공병 반환 테스트 (Healing Potion) ===\n";
    workshop.returnPotionByName("Healing Potion");
    workshop.returnPotionByName("Healing Potion");
    workshop.returnPotionByName("Healing Potion"); // 이미 3이면 더 올라가면 안 됨

    std::cout << "반환 후 재고(최대 3 유지): "
        << workshop.getStockByName("Healing Potion") << "\n";

    std::cout << "\n=== 최종 상태 ===\n";
    workshop.displayAllRecipes();
}


void initTestData(AlchemyWorkshop& workshop) {
    // 1. 기초 포션 라인업 (단순 재료)
    workshop.addRecipe("체력 물약(소)", { "Water", "RedHerb" });
    workshop.addRecipe("마나 물약(소)", { "Water", "BlueHerb" });
    workshop.addRecipe("해독제", { "Water", "AntidoteHerb" });
    // 2. 공격형 포션 (공통 재료: Gunpowder, FireStone 등 테스트용)
    workshop.addRecipe("화염병", { "Oil", "Gunpowder" });
    workshop.addRecipe("폭발 물약", { "Gunpowder", "FireStone", "RedHerb" });
    workshop.addRecipe("급조된 폭탄", { "Iron", "Gunpowder" }); // Gunpowder 검색 시 3개 나와야 함
    // 3. 고급 포션 (재료가 많음)
    workshop.addRecipe("엘릭서", { "Water", "RedHerb", "BlueHerb", "GoldDust", "MagicEssence" });
    workshop.addRecipe("현자의 돌조각", { "Mercury", "Sulfur", "Salt", "UnknownMatter" });
    // 4. 특수 효과 포션 (비슷한 재료 교차 테스트)
    workshop.addRecipe("신속의 물약", { "WindFlower", "Water" });
    workshop.addRecipe("투명 물약", { "WindFlower", "GlassDust", "Moonlight" });
    workshop.addRecipe("방어의 비약", { "Iron", "EarthRoot", "Water" });
}


int main() {
    AlchemyWorkshop myWorkshop;

    while (true) {
        std::cout << "⚗️ 연금술 공방 관리 시스템" << std::endl;
        std::cout << "1. 레시피 추가" << std::endl;
        std::cout << "2. 모든 레시피 출력" << std::endl;
        std::cout << "3. 레시피 검색" << std::endl;
        std::cout << "4. 테스트용 임시 레시피 대량 생성" << std::endl;
        std::cout << "5. 과제 공식 스트레스 테스트 실행" << std::endl;
        std::cout << "6. gemini의 스트레스 테스트 실행" << std::endl;
        std::cout << "7. 종료" << std::endl;
        std::cout << "선택: ";

        int choice;
        std::cin >> choice;

        if (std::cin.fail()) {
            std::cout << "잘못된 입력입니다. 숫자를 입력해주세요." << std::endl;
            std::cin.clear();
            std::cin.ignore(10000, '\n');
            continue;
        }

        if (choice == 1) {
            std::string name;
            std::cout << "물약 이름: ";
            std::cin.ignore(10000, '\n');
            std::getline(std::cin, name);

            // 여러 재료를 입력받기 위한 로직
            std::vector<std::string> ingredients_input;
            std::string ingredient;
            std::cout << "필요한 재료들을 입력하세요. (입력 완료 시 '끝' 입력)" << std::endl;

            while (true) {
                std::cout << "재료 입력: ";
                std::getline(std::cin, ingredient);

                // 사용자가 '끝'을 입력하면 재료 입력 종료
                if (ingredient == "끝") {
                    break;
                }
                ingredients_input.push_back(ingredient);
            }

            // 입력받은 재료가 하나 이상 있을 때만 레시피 추가
            if (!ingredients_input.empty()) {
                myWorkshop.addRecipe(name, ingredients_input);
            }
            else {
                std::cout << ">> 재료가 입력되지 않아 레시피 추가를 취소합니다." << std::endl;
            }

        }
        else if (choice == 2) {
            myWorkshop.displayAllRecipes();

        }
        else if (choice == 3) {
            searchSystem(myWorkshop);
        }
        else if (choice == 4) {
            initTestData(myWorkshop);
        }
        else if (choice == 5) {
            spartaStressTestSystem(myWorkshop);
        }
        else if (choice == 6) {
            geminiStressTestSystem(myWorkshop);
        }
        else if (choice == 7) {
            std::cout << "공방 문을 닫습니다..." << std::endl;
            break;
        }
        else {
            std::cout << "잘못된 선택입니다. 다시 시도하세요." << std::endl;
        }
    }

    return 0;
}

'언리얼 7기 본캠프' 카테고리의 다른 글

251224 TIL - C++ 13일차, 레벨 테스트  (1) 2025.12.24
251223 TIL - C++ 12일차, 5번 과제 발제  (0) 2025.12.23
251219 TIL - C++ 10일차  (0) 2025.12.19
251218 TIL - C++ 9일차  (0) 2025.12.18
251217 TIL - C++ 8일차  (0) 2025.12.17