ProjectDDD/Assets/_DDD/_Scripts/RestaurantState/FlowStates/RestaurantManagementState.cs
2025-08-19 12:12:10 +09:00

274 lines
11 KiB
C#

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<string, int> _todayFoodRecipeIds = new();
[ReadOnly, ShowInInspector] private Dictionary<string, int> _todayDrinkRecipeIds = new();
[ReadOnly, ShowInInspector] private List<string> _todayWorkerIds = new();
[ReadOnly, ShowInInspector] private Dictionary<string, HashSet<string>> _cookwareToRecipeIds = new();
public IReadOnlyDictionary<string, int> TodayFoodRecipeIds => _todayFoodRecipeIds;
public IReadOnlyDictionary<string, int> TodayDrinkRecipeIds => _todayDrinkRecipeIds;
public IReadOnlyList<string> TodayWorkerIds => _todayWorkerIds;
public IReadOnlyDictionary<string, HashSet<string>> 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();
}
/// <summary>
/// 체크리스트 항목들의 상태를 확인하는 메서드
/// </summary>
/// <returns>체크리스트 완료 여부 배열 (순서: 음식레시피, 조리도구, 매칭여부)</returns>
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<RecipeDataSo>().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<FoodDataSo>().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<DrinkDataSo>().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<RecipeDataSo>().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<FoodDataSo>().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<DrinkDataSo>().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<CookwareDataSo>().ContainsData(cookwareId) == false) return false;
if (_cookwareToRecipeIds.Count >= MaxCookwareCount || _cookwareToRecipeIds.ContainsKey(cookwareId)) return false;
_cookwareToRecipeIds[cookwareId] = new HashSet<string>();
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<CookwareDataSo>().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<RecipeDataSo>().TryGetDataById(recipeId, out var recipeData) == false) return null;
var resultKey = recipeData.RecipeResult;
return recipeData.RecipeType switch
{
RecipeType.FoodRecipe => DataManager.Instance.GetDataSo<FoodDataSo>().GetDataById(resultKey).CookwareKey,
RecipeType.DrinkRecipe => DataManager.Instance.GetDataSo<DrinkDataSo>().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;
}
}
}