using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; namespace DDD.Restaurant { public class RestaurantManagementState : ScriptableObject { private Dictionary _todayFoodRecipeAndAmounts = new(); private Dictionary _todayDrinkRecipeAndAmounts = new(); private List _todayWorkers = new(); private Dictionary> _cookwareToRecipeMapping = new(); public IReadOnlyDictionary TodayFoodRecipeAndAmounts => _todayFoodRecipeAndAmounts; public IReadOnlyDictionary TodayDrinkRecipeAndAmounts => _todayDrinkRecipeAndAmounts; public IReadOnlyList TodayWorkers => _todayWorkers; public IReadOnlyDictionary> CookwareToRecipeMapping => _cookwareToRecipeMapping; public int AddedTodayMenuCount => AddedTodayFoodCount + AddedTodayDrinkCount; public int AddedTodayFoodCount => _todayFoodRecipeAndAmounts.Count; public int AddedTodayDrinkCount => _todayDrinkRecipeAndAmounts.Count; public int AddedTodayWorkerCount => _todayWorkers.Count; public int AddedTodayCookwareCount => _cookwareToRecipeMapping.Count; public int MatchedTodayMenuWithCookwareCount => _cookwareToRecipeMapping.Values.Count(recipeSet => recipeSet.Count > 0); private RestaurantManagementData GetRestaurantManagementData() => RestaurantData.Instance.ManagementData; public void InitializeReadyForRestaurant() { // TODO : Load from disk if possible (save data) _todayFoodRecipeAndAmounts.Clear(); _todayDrinkRecipeAndAmounts.Clear(); _todayWorkers.Clear(); _cookwareToRecipeMapping.Clear(); } /// /// 체크리스트 항목들의 상태를 확인하는 메서드 /// /// 체크리스트 완료 여부 배열 (순서: 음식레시피, 조리도구, 매칭여부) public bool[] GetChecklistStates() { bool hasFood = HasFoodRecipes(); bool hasCookware = HasCookwares(); bool hasMatching = HasMatchedMenuWithCookware(); return new bool[] { hasFood, hasCookware, hasMatching }; } public bool HasFoodRecipes() { return _todayFoodRecipeAndAmounts.Count > 0; } public bool HasCookwares() { return _cookwareToRecipeMapping.Count > 0; } public bool HasMatchedMenuWithCookware() { return _cookwareToRecipeMapping.Values.Any(recipeSet => recipeSet.Count > 0); } public List GetTodayFoodMenus() { return _todayFoodRecipeAndAmounts.Keys.ToList(); } public int GetTodayFoodAvailableCount(string recipeId) { return _todayFoodRecipeAndAmounts.GetValueOrDefault(recipeId, 0); } public bool IsOpenable() { // TODO : 영업 가능한 상태인지 조건 추가 (최소 요리, 요리도구 배치 등) bool isExistedCookware = CookwareToRecipeMapping.Count > 0; bool isExistedMatchedMenu = _cookwareToRecipeMapping.Values.Any(recipeSet => recipeSet is { Count: > 0 }); var isOpenable = isExistedCookware && isExistedMatchedMenu; return isOpenable; } public bool TryAddTodayMenu(ItemModel model) { string recipeId = model.Id; if (model.ItemType != ItemType.Recipe) return false; if (DataManager.Instance.GetDataAsset().TryGetDataById(recipeId, out RecipeDataEntry recipeData) == false) return false; bool added = false; if (recipeData.RecipeType == RecipeType.FoodRecipe) { if (_todayFoodRecipeAndAmounts.Count >= GetRestaurantManagementData().MaxFoodCount || _todayFoodRecipeAndAmounts.ContainsKey(recipeId)) return false; var foodData = DataManager.Instance.GetDataAsset().GetDataById(recipeData.RecipeResult); var craftableCount = foodData.GetCraftableCount(); foodData.ConsumeAllCraftableIngredients(); _todayFoodRecipeAndAmounts[recipeId] = craftableCount; added = true; } else if (recipeData.RecipeType == RecipeType.DrinkRecipe) { if (_todayDrinkRecipeAndAmounts.Count >= GetRestaurantManagementData().MaxDrinkCount || _todayDrinkRecipeAndAmounts.ContainsKey(recipeId)) return false; var drinkData = DataManager.Instance.GetDataAsset().GetDataById(recipeData.RecipeResult); var craftableCount = drinkData.GetCraftableCount(); drinkData.ConsumeAllCraftableIngredients(); _todayDrinkRecipeAndAmounts[recipeId] = craftableCount; added = true; } if (added) { var cookwareKey = GetRequiredCookwareKey(recipeId); if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeMapping.TryGetValue(cookwareKey, out var recipeSet)) { recipeSet.Add(recipeId); } var dirtyEvt = GameEvents.SmartVariablesDirtyEvent; dirtyEvt.DomainFlags = SmartVariablesDomain.RestaurantToday; EventBus.Broadcast(dirtyEvt); EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent); } return added; } public bool TryRemoveTodayMenu(ItemModel model) { string recipeId = model.Id; var removedEvt = RestaurantEvents.TodayMenuRemovedEvent; if (DataManager.Instance.GetDataAsset().TryGetDataById(recipeId, out RecipeDataEntry recipeData) == false) return false; bool removed = false; int refundCount = 0; if (recipeData.RecipeType == RecipeType.FoodRecipe) { if (_todayFoodRecipeAndAmounts.TryGetValue(recipeId, out refundCount)) { removed = _todayFoodRecipeAndAmounts.Remove(recipeId); removedEvt.InventoryCategoryType = InventoryCategoryType.Food; if (removed) { var foodData = DataManager.Instance.GetDataAsset().GetDataById(recipeData.RecipeResult); foodData.RefundIngredients(refundCount); } } } else if (recipeData.RecipeType == RecipeType.DrinkRecipe) { if (_todayDrinkRecipeAndAmounts.TryGetValue(recipeId, out refundCount)) { removed = _todayDrinkRecipeAndAmounts.Remove(recipeId); removedEvt.InventoryCategoryType = InventoryCategoryType.Drink; if (removed) { var drinkData = DataManager.Instance.GetDataAsset().GetDataById(recipeData.RecipeResult); drinkData.RefundIngredients(refundCount); } } } if (removed) { var cookwareKey = GetRequiredCookwareKey(recipeId); if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeMapping.TryGetValue(cookwareKey, out var recipeSet)) { recipeSet.Remove(recipeId); } var dirtyEvt = GameEvents.SmartVariablesDirtyEvent; dirtyEvt.DomainFlags = SmartVariablesDomain.RestaurantToday; EventBus.Broadcast(dirtyEvt); EventBus.Broadcast(removedEvt); } return removed; } public bool TryAddTodayCookware(ItemModel model) { var cookwareId = model.Id; if (model.HasItem == false || DataManager.Instance.GetDataAsset().ContainsData(cookwareId) == false) return false; if (_cookwareToRecipeMapping.Count >= GetRestaurantManagementData().MaxCookwareCount || _cookwareToRecipeMapping.ContainsKey(cookwareId)) return false; _cookwareToRecipeMapping[cookwareId] = new HashSet(); foreach (var recipeId in _todayFoodRecipeAndAmounts.Keys.Concat(_todayDrinkRecipeAndAmounts.Keys)) { var required = GetRequiredCookwareKey(recipeId); if (required == cookwareId) { _cookwareToRecipeMapping[cookwareId].Add(recipeId); } } var dirtyEvt = GameEvents.SmartVariablesDirtyEvent; dirtyEvt.DomainFlags = SmartVariablesDomain.RestaurantToday; EventBus.Broadcast(dirtyEvt); EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent); return true; } public bool IsContainTodayMenu(string recipeId) => _todayFoodRecipeAndAmounts.ContainsKey(recipeId) || _todayDrinkRecipeAndAmounts.ContainsKey(recipeId); public bool TryRemoveTodayCookware(ItemModel model) { var cookwareId = model.Id; if (DataManager.Instance.GetDataAsset().ContainsData(cookwareId) == false) return false; if (_cookwareToRecipeMapping.Remove(cookwareId) == false) return false; var dirtyEvt = GameEvents.SmartVariablesDirtyEvent; dirtyEvt.DomainFlags = SmartVariablesDomain.RestaurantToday; EventBus.Broadcast(dirtyEvt); var evt = RestaurantEvents.TodayMenuRemovedEvent; evt.InventoryCategoryType = InventoryCategoryType.Cookware; EventBus.Broadcast(evt); return true; } private string GetRequiredCookwareKey(string recipeId) { if (DataManager.Instance.GetDataAsset().TryGetDataById(recipeId, out var recipeData) == false) return null; var resultKey = recipeData.RecipeResult; return recipeData.RecipeType switch { RecipeType.FoodRecipe => DataManager.Instance.GetDataAsset().GetDataById(resultKey).CookwareKey, RecipeType.DrinkRecipe => DataManager.Instance.GetDataAsset().GetDataById(resultKey).CookwareKey, _ => null }; } public bool IsCookwareMatched(string recipeId) { return _cookwareToRecipeMapping.Values.Any(recipeHashSets => recipeHashSets.Contains(recipeId)); } public bool IsTodayMenuMatched(string cookwareId) { if (_cookwareToRecipeMapping.TryGetValue(cookwareId, out var recipeSet)) { return recipeSet.Count > 0; } return false; } public bool HasAddedCookByCookwareKey(string cookwareKey) { return _cookwareToRecipeMapping.ContainsKey(cookwareKey) && _cookwareToRecipeMapping[cookwareKey].Count > 0;; } public bool TryCookingById(string recipeId) { if (_todayFoodRecipeIds.TryGetValue(recipeId, out var foodCount) && foodCount > 0) { _todayFoodRecipeIds[recipeId] -= 1; return true; } if (_todayDrinkRecipeIds.TryGetValue(recipeId, out var drinkCount) && drinkCount > 0) { _todayDrinkRecipeIds[recipeId] -= 1; return true; } return false; } } }