using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; namespace DDD { public class RestaurantManagementState : ScriptableObject { // TODO : 데이터에서 초기화하고, 동적으로 변경 [Title("오늘의 레스토랑 상태")] public int MaxFoodCount = 8; public int MaxDrinkCount = 6; public int MaxCookwareCount = 6; [Title("체크리스트 조건")] public int ChecklistFoodCount = 1; public int ChecklistCookwareCount = 1; public int ChecklistMatchedMenuWithCookwareCount = 1; [Title("실시간 데이터")] [ReadOnly, SerializeField] private bool _isOpenable; [ReadOnly, ShowInInspector] private Dictionary _todayFoodRecipeIds = new(); [ReadOnly, ShowInInspector] private Dictionary _todayDrinkRecipeIds = new(); [ReadOnly, ShowInInspector] private List _todayWorkerIds = new(); [ReadOnly, ShowInInspector] private Dictionary> _cookwareToRecipeIds = new(); public IReadOnlyDictionary TodayFoodRecipeIds => _todayFoodRecipeIds; public IReadOnlyDictionary TodayDrinkRecipeIds => _todayDrinkRecipeIds; public IReadOnlyList TodayWorkerIds => _todayWorkerIds; public IReadOnlyDictionary> CookwareToRecipeIds => _cookwareToRecipeIds; public int AddedTodayMenuCount => AddedTodayFoodCount + AddedTodayDrinkCount; public int AddedTodayFoodCount => _todayFoodRecipeIds.Count; public int AddedTodayDrinkCount => _todayDrinkRecipeIds.Count; public int AddedTodayWorkerCount => _todayWorkerIds.Count; public int AddedTodayCookwareCount => _cookwareToRecipeIds.Count; public int MatchedTodayMenuWithCookwareCount => _cookwareToRecipeIds.Values.Count(recipeSet => recipeSet.Count > 0); public void InitializeReadyForRestaurant() { // TODO : Load from disk if possible (save data) _todayFoodRecipeIds.Clear(); _todayDrinkRecipeIds.Clear(); _todayWorkerIds.Clear(); _cookwareToRecipeIds.Clear(); } /// /// 체크리스트 항목들의 상태를 확인하는 메서드 /// /// 체크리스트 완료 여부 배열 (순서: 음식레시피, 조리도구, 매칭여부) public bool[] GetChecklistStates() { bool hasFood = HasFoodRecipes(); bool hasCookware = HasCookwares(); bool hasMatching = HasMatchedMenuWithCookware(); return new bool[] { hasFood, hasCookware, hasMatching }; } public bool HasFoodRecipes() { return _todayFoodRecipeIds.Count > 0; } public bool HasCookwares() { return _cookwareToRecipeIds.Count > 0; } public bool HasMatchedMenuWithCookware() { return _cookwareToRecipeIds.Values.Any(recipeSet => recipeSet.Count > 0); } public bool IsOpenable() { // TODO : 영업 가능한 상태인지 조건 추가 (최소 요리, 요리도구 배치 등) bool isExistedCookware = CookwareToRecipeIds.Count > 0; bool isExistedMatchedMenu = _cookwareToRecipeIds.Values.Any(recipeSet => recipeSet is { Count: > 0 }); _isOpenable = isExistedCookware && isExistedMatchedMenu; return _isOpenable; } public RestaurantManagementData GetManagementData() { return RestaurantController.Instance.RestaurantData.ManagementData; } public bool TryAddTodayMenu(ItemViewModel model) { string recipeId = model.Id; if (model.ItemType != ItemType.Recipe) return false; if (DataManager.Instance.GetDataSo().TryGetDataById(recipeId, out RecipeData recipeData) == false) return false; bool added = false; if (recipeData.RecipeType == RecipeType.FoodRecipe) { if (_todayFoodRecipeIds.Count >= MaxFoodCount || _todayFoodRecipeIds.ContainsKey(recipeId)) return false; var foodData = DataManager.Instance.GetDataSo().GetDataById(recipeData.RecipeResult); var craftableCount = foodData.GetCraftableCount(); foodData.ConsumeAllCraftableIngredients(); _todayFoodRecipeIds[recipeId] = craftableCount; added = true; } else if (recipeData.RecipeType == RecipeType.DrinkRecipe) { if (_todayDrinkRecipeIds.Count >= MaxDrinkCount || _todayDrinkRecipeIds.ContainsKey(recipeId)) return false; var drinkData = DataManager.Instance.GetDataSo().GetDataById(recipeData.RecipeResult); var craftableCount = drinkData.GetCraftableCount(); drinkData.ConsumeAllCraftableIngredients(); _todayDrinkRecipeIds[recipeId] = craftableCount; added = true; } if (added) { var cookwareKey = GetRequiredCookwareKey(recipeId); if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeIds.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(ItemViewModel model) { string recipeId = model.Id; var removedEvt = RestaurantEvents.TodayMenuRemovedEvent; if (DataManager.Instance.GetDataSo().TryGetDataById(recipeId, out RecipeData recipeData) == false) return false; bool removed = false; int refundCount = 0; if (recipeData.RecipeType == RecipeType.FoodRecipe) { if (_todayFoodRecipeIds.TryGetValue(recipeId, out refundCount)) { removed = _todayFoodRecipeIds.Remove(recipeId); removedEvt.InventoryCategoryType = InventoryCategoryType.Food; if (removed) { var foodData = DataManager.Instance.GetDataSo().GetDataById(recipeData.RecipeResult); foodData.RefundIngredients(refundCount); } } } else if (recipeData.RecipeType == RecipeType.DrinkRecipe) { if (_todayDrinkRecipeIds.TryGetValue(recipeId, out refundCount)) { removed = _todayDrinkRecipeIds.Remove(recipeId); removedEvt.InventoryCategoryType = InventoryCategoryType.Drink; if (removed) { var drinkData = DataManager.Instance.GetDataSo().GetDataById(recipeData.RecipeResult); drinkData.RefundIngredients(refundCount); } } } if (removed) { var cookwareKey = GetRequiredCookwareKey(recipeId); if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeIds.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(ItemViewModel model) { var cookwareId = model.Id; if (model.HasItem == false || DataManager.Instance.GetDataSo().ContainsData(cookwareId) == false) return false; if (_cookwareToRecipeIds.Count >= MaxCookwareCount || _cookwareToRecipeIds.ContainsKey(cookwareId)) return false; _cookwareToRecipeIds[cookwareId] = new HashSet(); foreach (var recipeId in _todayFoodRecipeIds.Keys.Concat(_todayDrinkRecipeIds.Keys)) { var required = GetRequiredCookwareKey(recipeId); if (required == cookwareId) { _cookwareToRecipeIds[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) => _todayFoodRecipeIds.ContainsKey(recipeId) || _todayDrinkRecipeIds.ContainsKey(recipeId); public bool TryRemoveTodayCookware(ItemViewModel model) { var cookwareId = model.Id; if (DataManager.Instance.GetDataSo().ContainsData(cookwareId) == false) return false; if (_cookwareToRecipeIds.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.GetDataSo().TryGetDataById(recipeId, out var recipeData) == false) return null; var resultKey = recipeData.RecipeResult; return recipeData.RecipeType switch { RecipeType.FoodRecipe => DataManager.Instance.GetDataSo().GetDataById(resultKey).CookwareKey, RecipeType.DrinkRecipe => DataManager.Instance.GetDataSo().GetDataById(resultKey).CookwareKey, _ => null }; } public bool IsCookwareMatched(string recipeId) { return _cookwareToRecipeIds.Values.Any(recipeHashSets => recipeHashSets.Contains(recipeId)); } public bool IsTodayMenuMatched(string cookwareId) { if (_cookwareToRecipeIds.TryGetValue(cookwareId, out var recipeSet)) { return recipeSet.Count > 0; } return false; } } }