#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
// PotionRecipe 클래스: 재료 목록을 vector<string>으로 변경
class PotionRecipe {
public:
string potionName;
vector<string> ingredients; // 단일 재료에서 재료 '목록'으로 변경
// 생성자: 재료 목록을 받아 초기화하도록 수정
PotionRecipe(const string& name, const vector<string>& ingredients)
: potionName(name), ingredients(ingredients) {
}
};
// StockManager 클래스: 레시피 재고 관리
class StockManager {
private:
map<string, int> potionStock;
const int MAX_STOCK = 3;
public:
// 재고 설정
void initializeStock(string potionName) {
if (potionStock.find(potionName) == potionStock.end()) potionStock.emplace(potionName, MAX_STOCK);
else return;
}
// 물약 사용
bool dispensePotion(string potionName) {
if (potionStock[potionName] > 0) {
potionStock[potionName]--;
return true;
}
else return false;
}
// 빈병 반환
void returnPotion(string potionName) {
if (potionStock[potionName] < MAX_STOCK) {
potionStock[potionName]++;
}
else {
potionStock[potionName] = MAX_STOCK;
}
}
// 재고 정보 반환
int getStock(string potionName) const{
if (potionStock.find(potionName) != potionStock.end()) {
return potionStock.find(potionName)->second;
}
else return -1;
}
};
// RecipeManager 클래스: 레시피 관리
class RecipeManager {
private:
vector<PotionRecipe> recipes; // 레시피를 벡터로 저장
public:
// addRecipe 메서드: 재료 목록(vector)을 매개변수로 받도록 수정
PotionRecipe* addRecipe(const string& name, const vector<string>& ingredients) {
if (findRecipeByName(name) != nullptr) return nullptr; // 같은 이름의 포션이 있으면 nullptr 반환
PotionRecipe pRecipe = PotionRecipe(name, ingredients);
recipes.push_back(pRecipe);
return &recipes.back();
}
// 이름으로 레시피 찾기
PotionRecipe* findRecipeByName(string name) {
for (size_t i = 0; i < recipes.size(); ++i) {
if (name == recipes[i].potionName) {
return &recipes[i];
}
}
return nullptr;
}
// 재료로 레시피 찾기
vector<PotionRecipe> findRecipesByIngredient(string ingredient) {
vector<PotionRecipe> searcedRecipes;
for (size_t i = 0; i < recipes.size(); ++i) {
for (size_t j = 0; j < recipes[i].ingredients.size(); ++j) {
if (ingredient == recipes[i].ingredients[j]) {
searcedRecipes.push_back(recipes[i]);
break;
}
}
}
return searcedRecipes;
}
// 모든 레시피 반환
const vector<PotionRecipe>& getAllRecipes() const{
return recipes;
}
};
// AlchemyWorkshop 클래스
class AlchemyWorkshop {
private:
RecipeManager rManager;
StockManager sManager;
public:
// addRecipe 메서드
void addRecipe(const string& name, const vector<string>& ingredients) {
if (rManager.addRecipe(name, ingredients) != nullptr) { // 해당 이름의 레시피가 없는지 확인
cout << ">> 새로운 레시피 '" << name << "'이(가) 추가되었습니다." << endl;
sManager.initializeStock(name);
}
else cout << ">> 해당 이름의 레시피가 이미 존재합니다." << endl;
}
// 모든 레시피 출력 메서드
void displayAllRecipes() const {
if (rManager.getAllRecipes().empty()) {
cout << "아직 등록된 레시피가 없습니다." << endl;
return;
}
cout << "\n--- [ 전체 레시피 목록 ] ---" << endl;
for (size_t i = 0; i < rManager.getAllRecipes().size(); ++i) {
cout << "- 물약 이름: " << rManager.getAllRecipes()[i].potionName;
cout << " 재고: " << sManager.getStock(rManager.getAllRecipes()[i].potionName) << "병" << endl;
cout << " > 필요 재료: ";
// 재료 목록을 순회하며 출력
for (size_t j = 0; j < rManager.getAllRecipes()[i].ingredients.size(); ++j) {
cout << rManager.getAllRecipes()[i].ingredients[j];
// 마지막 재료가 아니면 쉼표로 구분
if (j < rManager.getAllRecipes()[i].ingredients.size() - 1) {
cout << ", ";
}
}
cout << endl;
}
cout << "---------------------------\n";
}
// 이름으로 물약 재고 찾기
int getStockByName(const string& name) const {
return sManager.getStock(name);
}
// 이름으로 물약 지급
bool dispensePotionByName(const string& name) {
if (sManager.dispensePotion(name)) return true;
else return false;
}
// 재료로 물약 지급
vector<string> dispensePotionsByIngredient(const string& ingredient) {
vector<string> recipesName;
vector<PotionRecipe> recipes = rManager.findRecipesByIngredient(ingredient);
for (PotionRecipe rec : recipes) {
if (sManager.dispensePotion(rec.potionName)) {
recipesName.push_back(rec.potionName);
}
}
if (recipes.empty()) cout << "해당 재료의 레시피가 없습니다." << endl;
return recipesName;
}
// 물약 반환
void returnPotionByName(const string& name) {
sManager.returnPotion(name);
}
};
int main() {
AlchemyWorkshop myWorkshop;
while (true) {
cout << "⚗️ 연금술 공방 관리 시스템" << endl;
cout << "1. 레시피 추가" << endl;
cout << "2. 모든 레시피 출력" << endl;
cout << "3. 물약 재고 확인" << endl;
cout << "4. 이름으로 물약 지급 받기" << endl;
cout << "5. 재료로 물약 지급 받기" << endl;
cout << "6. 빈병 반환하기" << endl;
cout << "7. 종료" << endl;
cout << "선택: ";
int choice;
cin >> choice;
if (cin.fail()) {
cout << "잘못된 입력입니다. 숫자를 입력해주세요." << endl;
cin.clear();
cin.ignore(10000, '\n');
continue;
}
if (choice == 1) {
string name;
cout << "물약 이름: ";
cin.ignore(10000, '\n');
getline(cin, name);
// 여러 재료를 입력받기 위한 로직
vector<string> ingredients_input;
string ingredient;
cout << "필요한 재료들을 입력하세요. (입력 완료 시 '끝' 입력)" << endl;
while (true) {
cout << "재료 입력: ";
getline(cin, ingredient);
// 사용자가 '끝'을 입력하면 재료 입력 종료
if (ingredient == "끝") {
break;
}
ingredients_input.push_back(ingredient);
}
// 입력받은 재료가 하나 이상 있을 때만 레시피 추가
if (!ingredients_input.empty()) {
myWorkshop.addRecipe(name, ingredients_input);
}
else {
cout << ">> 재료가 입력되지 않아 레시피 추가를 취소합니다." << endl;
}
}
else if (choice == 2) {
myWorkshop.displayAllRecipes();
}
else if (choice == 3) {
string potionName;
cout << "확인하려는 물약의 이름: ";
cin.ignore(10000, '\n');
getline(cin, potionName);
if (myWorkshop.getStockByName(potionName) != -1) {
cout << potionName << "의 남은 재고: " << myWorkshop.getStockByName(potionName) << "개" << endl;
}
else {
cout << "해당 이름의 포션이 존재하지 않습니다." << endl;
}
}
else if (choice == 4) {
string potionName;
cout << "지급 받으려는 포션의 이름: ";
cin.ignore(10000, '\n');
getline(cin, potionName);
if (myWorkshop.dispensePotionByName(potionName)) {
cout << potionName << "포션이 하나 지급되었습니다." << endl;
}
else {
cout << potionName << "포션의 재고가 부족합니다." << endl;
}
}
else if (choice == 5) {
string ingredientName;
vector<string> potionNames;
cout << "지급 받으려는 포션의 재료: ";
cin.ignore(10000, '\n');
getline(cin, ingredientName);
potionNames = myWorkshop.dispensePotionsByIngredient(ingredientName);
if (!potionNames.empty()) {
for (size_t i = 0; i < potionNames.size(); ++i) {
cout << potionNames[i];
if (i != potionNames.size()-1) {
cout << ", ";
}
}
cout << "포션이 하나씩 지급되었습니다." << endl;
}
}
else if (choice == 6) {
string potionName;
cout << "반환하려는 포션의 이름: ";
cin.ignore(10000, '\n');
getline(cin, potionName);
myWorkshop.returnPotionByName(potionName);
}
else if (choice == 7) {
cout << "공방 문을 닫습니다..." << endl;
break;
}
else {
cout << "잘못된 선택입니다. 다시 시도하세요." << endl;
}
}
return 0;
}