diff --git a/popcorn/Assets/MyGame/Scenes/marketing/Scripts/CustomerController.cs b/popcorn/Assets/MyGame/Scenes/marketing/Scripts/CustomerController.cs index 9e273d1b..2bde86c5 100644 --- a/popcorn/Assets/MyGame/Scenes/marketing/Scripts/CustomerController.cs +++ b/popcorn/Assets/MyGame/Scenes/marketing/Scripts/CustomerController.cs @@ -21,7 +21,6 @@ public enum CustomerMovingType public enum CustomerState { Walk, - Want, Wait, Order, Leave, @@ -76,12 +75,12 @@ public class CustomerController : MonoBehaviour private float walkSideDirection; public IReadOnlyReactiveProperty MoveEndObservable => moveEndSubject; private readonly ReactiveProperty moveEndSubject = new ReactiveProperty(); - public IReadOnlyReactiveProperty CustomerState => customerState; - private readonly ReactiveProperty customerState = new ReactiveProperty(); + public IReadOnlyReactiveProperty State => state; + private readonly ReactiveProperty state = new ReactiveProperty(); private void Start() { - customerState.AddTo(this); + state.AddTo(this); durationDelta = 0f; this.UpdateAsObservable().Subscribe(_ => { @@ -118,43 +117,42 @@ public class CustomerController : MonoBehaviour public void ChangeCustomerState(CustomerState state) { - customerState.Value = state; + this.state.Value = state; Debug.Log(state); switch (state) { - case global::CustomerState.Walk: + case CustomerState.Walk: SetMove(CustomerMovingType.WalkCenter); // 数秒立ち止まる AddMove(CustomerMovingType.StayBackLook, 2f); AddMove(CustomerMovingType.WalkSide); break; - case global::CustomerState.Want: - // 店に向かう + case CustomerState.Wait: + // 店に向かう&順番待ち + // 近くの場合その場に待機 + // まだ遠い場合待機場所に移動 moves.Clear(); if (currentMovingType == CustomerMovingType.StayBackLook) { SetMove(CustomerMovingType.WalkBackHalf); - break; } - SetMove(CustomerMovingType.WalkCenter); - break; - case global::CustomerState.Wait: - // 順番待ち - // 近くの場合その場に待機 - // まだ遠い場合待機場所に移動 - AddMove(CustomerMovingType.WalkBackHalf); + else + { + SetMove(CustomerMovingType.WalkCenter); + AddMove(CustomerMovingType.WalkBackHalf); + } AddMove(CustomerMovingType.StayBackLook); break; - case global::CustomerState.Order: + case CustomerState.Order: // 受付まで行く AddMove(CustomerMovingType.WalkBack); AddMove(CustomerMovingType.StayBack); break; - case global::CustomerState.Leave: + case CustomerState.Leave: moves.Clear(); SetMove(CustomerMovingType.WalkSide); break; - case global::CustomerState.EatingLeave: + case CustomerState.EatingLeave: AddMove(CustomerMovingType.WalkFrontEat); AddMove(CustomerMovingType.WalkSideEat); break; diff --git a/popcorn/Assets/MyGame/Scenes/marketing/Scripts/Market.cs b/popcorn/Assets/MyGame/Scenes/marketing/Scripts/Market.cs index 71f5c3cc..8b59dcf4 100644 --- a/popcorn/Assets/MyGame/Scenes/marketing/Scripts/Market.cs +++ b/popcorn/Assets/MyGame/Scenes/marketing/Scripts/Market.cs @@ -29,6 +29,7 @@ public class Market : MonoBehaviour private ReactiveProperty shopState = new ReactiveProperty(); private ReactiveCollection waitCustomerList = new ReactiveCollection(); private Subject requestSubject = new Subject(); + private Subject orderSubject = new Subject(); // Start is called before the first frame update void Start() @@ -36,6 +37,7 @@ public class Market : MonoBehaviour shopState.AddTo(this); waitCustomerList.AddTo(this); requestSubject.AddTo(this); + orderSubject.AddTo(this); var gameData = GameDataManager.GameData; CoinManager.Instance.ChangeCoin(gameData.coin); @@ -65,7 +67,8 @@ public class Market : MonoBehaviour }; HeartMeter.Instance.Initialize(shopLevelList.Select(x => x.heart).ToList()); - HeartMeter.Instance.SetHeart(15); + HeartMeter.Instance.SetHeart(gameData.Heart); + HeartMeter.Instance.SetHeart(99999); // 在庫数表示 stockView.SetStock(gameData.StorageTanks); @@ -83,54 +86,63 @@ public class Market : MonoBehaviour // お店の状態設定 shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open; - // 購入リクエスト - shopState - .Where(x => x == ShopState.Open) - .Where(_ => waitCustomerList.Count > 0) - .Select(_ => waitCustomerList[0]) - .Merge(waitCustomerList.ObserveAdd().Select(x => x.Value)) - .BatchFrame() - .Select(x => x.RandomChoose()) // 同時にリクエストが有った場合1人選ぶ - .Where(_ => shopState.Value == ShopState.Open) // 他に購入中の客がいないことを確認 - .Subscribe(x => - { - Debug.Log($"RequestComfirmed"); - waitCustomerList.Remove(x); - // 購入へ - x.ChangeCustomerState(CustomerState.Order); - shopState.Value = ShopState.Busy; - }).AddTo(this); - // お客さん一覧 var customerList = new ReactiveCollection(); customerList.AddTo(this); + + // 購入リクエスト + orderSubject + .Merge(waitCustomerList.ObserveAdd().AsUnitObservable()) + .Merge(shopState.Where(x => x == ShopState.Open).AsUnitObservable()) + .Where(_ => shopState.Value == ShopState.Open) + .BatchFrame() + .Where(_ => waitCustomerList.Count > 0) + .SelectMany(_ => waitCustomerList.ToList().GetRange(0, Mathf.Min(3, waitCustomerList.Count))) + .Subscribe(customer => + { + Debug.Log($"aa order:{customerList.Count(x => x.State.Value == CustomerState.Order)} Request {Time.time} {customer.GetHashCode()}"); + if (customerList.Count(x => x.State.Value == CustomerState.Order) >= 3) + { + shopState.Value = ShopState.Busy; + return; + } + waitCustomerList.Remove(customer); + // 購入へ + customer.ChangeCustomerState(CustomerState.Order); + }).AddTo(this); + // 購入客 customerList.ObserveAdd() .Select(x => x.Value) .Subscribe(customerController => { + customerController.State.Subscribe(c => + { + if (c == CustomerState.EatingLeave) + { + Debug.Log($"aa order:{customerList.Count(x => x.State.Value == CustomerState.Order)} EatingLeave"); + orderSubject.OnNext(default); + } + }).AddTo(customerController); // 店に向かう - customerController.ChangeCustomerState(CustomerState.Want); - waitCustomerList.Add(customerController); - + customerController.ChangeCustomerState(CustomerState.Wait); shopState.Subscribe(x => { switch (x) { case ShopState.Open: - break; case ShopState.Busy: - // 自分が購入中 - if (customerController.CustomerState.Value == CustomerState.Order) - { - return; - } - // 待機 - customerController.ChangeCustomerState(CustomerState.Wait); break; case ShopState.Close: // 売り切れの場合帰る - customerController.ChangeCustomerState(CustomerState.Leave); + if (customerController.State.Value == CustomerState.Order) + { + return; + } + this.CallWaitForSeconds(Random.Range(0f, .4f), () => + { + customerController.ChangeCustomerState(CustomerState.Leave); + }); break; default: throw new ArgumentOutOfRangeException(nameof(x), x, null); @@ -138,70 +150,120 @@ public class Market : MonoBehaviour }).AddTo(customerController); }).AddTo(this); - requestSubject.Subscribe(customerController => + requestSubject.BatchFrame(30, FrameCountType.Update).Subscribe(customers => { - // 売り切れ if (gameData.ShopStock.Count == 0) { shopState.Value = ShopState.Close; + } + var coin = 0; + var orders = new List(); + var dontBuyCustomerList = new List(); + foreach (var controller in customers) + { + Debug.Log(shuffledOrder.Aggregate("", (s, i) => $"{s},{i}")); + // 売り切れ + if (shuffledOrder.Count == 0) + { + controller.ChangeCustomerState(CustomerState.Leave); + dontBuyCustomerList.Add(controller); + break; + } + + // オーダー数 + var orderCount = Random.Range(1,5); + // 在庫取得 + var tmpOrderCount = Mathf.Min(orderCount, shuffledOrder.Count); + // shuffledOrder順に販売 + orders.AddRange(shuffledOrder.GetRange(0, tmpOrderCount)); + shuffledOrder.RemoveRange(0, tmpOrderCount); + + // コーンの味吹き出しを設定(レア度優先など + controller.ChangeWantFlavor(displayFlavors[orders.RandomChoose()]); + } + foreach (var customerController in dontBuyCustomerList) + { + customers.Remove(customerController); + } + if (orders.Count == 0) + { return; } - // shuffledOrder順に販売 - Debug.Log(shuffledOrder.Aggregate("", (s, i) => s + i)); - var orderNum = shuffledOrder[0]; - shuffledOrder.RemoveAt(0); - // コーンの味吹き出しを設定 - customerController.ChangeWantFlavor(displayFlavors[orderNum]); + + // 購入 + var flavors = orders.Select(x => (displayFlavors[x], 0)).ToList(); + coin += SellPopcorn(flavors); + var remainStockCount = gameData.ShopStock.Count; + + // 自動補充 refill + RefillProduct(); + StockFlavorLog(); + + // 補充された場合フレーバー再設定 + var setStockFlag = false; + if (gameData.ShopStock.Count == ShopStockCount) + { + shuffledOrder.AddRange(orders); + Debug.Log($"remain {remainStockCount}, order {orders.Count}"); + var stock = gameData.ShopStock.GetRange(remainStockCount, orders.Count).ToArray(); + for (int i = 0; i < orders.Count; i++) + { + displayFlavors[orders[i]] = stock[i]; + } + } + else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13)) + { + displayFlavors = gameData.ShopStock.Select(x => x).ToList(); + shuffledOrder = ShuffleOrder(displayFlavors.Count); + setStockFlag = true; + } + else if (gameData.ShopStock.Count <= 7 && shuffledOrder.Exists(x => x > 7)) + { + displayFlavors = gameData.ShopStock.Select(x => x).ToList(); + shuffledOrder = ShuffleOrder(displayFlavors.Count); + setStockFlag = true; + } + this.CallWaitForSeconds(1.5f, () => { - // 購入 - SellPopcorn(orderNum); + foreach (var order in orders) + { + cartView.SellStock(order); + } blueView.SellAction(); - // 自動補充 refill - RefillOneProduct(); - StockFlavorLog(); - var setStockFlag = false; - // 補充された場合フレーバー再設定 - if (gameData.ShopStock.Count == ShopStockCount) - { - shuffledOrder.Add(orderNum); - displayFlavors[orderNum] = gameData.ShopStock.Last(); - } - else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13)) - { - displayFlavors = gameData.ShopStock.Select(x => x).ToList(); - shuffledOrder = ShuffleOrder(displayFlavors.Count); - setStockFlag = true; - } - else if (gameData.ShopStock.Count <= 7 && shuffledOrder.Exists(x => x > 7)) - { - displayFlavors = gameData.ShopStock.Select(x => x).ToList(); - shuffledOrder = ShuffleOrder(displayFlavors.Count); - setStockFlag = true; - } + // コイン獲得 + CoinManager.Instance.AddCoinWithEffect(coin, () => { }); + gameData.coin = CoinManager.Instance.OwnCoin; + gameData.Heart += customers.Count; + GameDataManager.SaveGameData(); + shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open; - // 表示更新 + // 表示更新(陳列13=650ms,7=350ms) this.CallWaitForSeconds(1f, () => { - var heartAnimation = customerController.GetComponent(); - heartAnimation.GetHeart(() => + foreach (var customerController in customers) { - HeartMeter.Instance.AddHeart(3); - }); - customerController.ChangeCustomerState(CustomerState.EatingLeave); - + var heartAnimation = customerController.GetComponent(); + heartAnimation.GetHeart(() => + { + HeartMeter.Instance.AddHeart(1); + }); + customerController.ChangeCustomerState(CustomerState.EatingLeave); + } stockView.SetStock(gameData.StorageTanks); if (gameData.ShopStock.Count == ShopStockCount) { // 補充したフレーバーのスキンを設定 - cartView.Refill(orderNum, displayFlavors[orderNum]); + foreach (var order in orders) + { + cartView.Refill(order, displayFlavors[order]); + } } else if (setStockFlag) { cartView.SetStock(displayFlavors); } }); - shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open; }); }).AddTo(this); @@ -254,23 +316,29 @@ public class Market : MonoBehaviour var customer = Instantiate(customerPrefab); var customerController = customer.GetComponent(); customerController.Setup(); - customerController.MoveEndObservable.SkipLatestValueOnSubscribe().DistinctUntilChanged().Subscribe(type => - { - // Debug.Log($"move end {type}"); - switch (type) + customerController.MoveEndObservable + .SkipLatestValueOnSubscribe() + .DistinctUntilChanged() + .Subscribe(type => { - case CustomerMovingType.WalkSide: - case CustomerMovingType.WalkSideEat: - customerList.Remove(customerController); - Destroy(customer); - break; - case CustomerMovingType.StayBack: - requestSubject.OnNext(customerController); - break; - default: - break; - } - }).AddTo(customerController); + // Debug.Log($"move end {type}"); + switch (type) + { + case CustomerMovingType.WalkSide: + case CustomerMovingType.WalkSideEat: + customerList.Remove(customerController); + Destroy(customer); + break; + case CustomerMovingType.WalkBackHalf: + waitCustomerList.Add(customerController); + break; + case CustomerMovingType.StayBack: + requestSubject.OnNext(customerController); + break; + default: + break; + } + }).AddTo(customerController); if (x.isCustomer) { @@ -290,28 +358,27 @@ public class Market : MonoBehaviour }).AddTo(this); } - private void SellPopcorn(int orderNum) + private int SellPopcorn(List<(int flavor, int bonusRate)> flavors) { var gameData = GameDataManager.GameData; // 品切れ if (gameData.ShopStock.Count == 0) { - return; + return 0; } - var targetFlavorId = displayFlavors[orderNum]; - Debug.Log($"sell:{orderNum} flavor:{targetFlavorId} {shuffledOrder.Count}"); + Debug.Log($"sellCount:{flavors.Count} {shuffledOrder.Count}"); - var targetIndex = gameData.ShopStock.FindIndex(x => x == targetFlavorId); - var stockData = gameData.ShopStock[targetIndex]; - gameData.ShopStock.RemoveAt(targetIndex); - cartView.SellStock(orderNum); - - // コイン獲得 - var bonusRate = 0; - var flavor = allRecipe.First(x => x.RecipeId == stockData); - CoinManager.Instance.AddCoinWithEffect(flavor.Price * (1 + bonusRate / 100), () => { }); - gameData.coin = CoinManager.Instance.OwnCoin; - GameDataManager.SaveGameData(); + // フレーバーを売る + var coin = 0; + foreach (var flavorData in flavors) + { + var targetIndex = gameData.ShopStock.FindIndex(x => x == flavorData.flavor); + var flavorRecipe = allRecipe.First(x => x.RecipeId == gameData.ShopStock[targetIndex]); + gameData.ShopStock.RemoveAt(targetIndex); + var bonusRate = 0; + coin += flavorRecipe.Price * (1 + bonusRate / 100); + } + return coin; } private List ShuffleOrder(int length) @@ -337,7 +404,32 @@ public class Market : MonoBehaviour } GameDataManager.SaveGameData(); } - + + private void RefillProduct() + { + // 手前のタンクから出し多分stockをへらす + // へらした分を店頭リストに追加する + var gameData = GameDataManager.GameData; + var shopSpace = ShopStockCount - gameData.ShopStock.Count; + var index = 0; + var tankCount = gameData.StorageTanks.Count; + while (shopSpace > 0) + { + if (index > tankCount - 1) + { + break; + } + var tank = gameData.StorageTanks[index]; + var stockCount = Mathf.Min(shopSpace, tank.Stock); + gameData.ShopStock.AddRange(Enumerable.Repeat(tank.FlavorId, stockCount)); + shopSpace -= stockCount; + tank.Stock -= stockCount; + gameData.StorageTanks[index] = tank; + index++; + } + GameDataManager.SaveGameData(); + } + private void CheckAndFixStock() { if (GameDataManager.GameData.ShopStock.Count > ShopStockCount) diff --git a/popcorn/Assets/MyGame/Scripts/GameDataManager.cs b/popcorn/Assets/MyGame/Scripts/GameDataManager.cs index 150aeca8..932240b8 100644 --- a/popcorn/Assets/MyGame/Scripts/GameDataManager.cs +++ b/popcorn/Assets/MyGame/Scripts/GameDataManager.cs @@ -75,8 +75,8 @@ public sealed class GameData { // タンクポップコーン在庫 [DataMember(Name = "Data20")] public List StorageTanks; - - + [DataMember(Name = "Data21")] + public int Heart = 0; // public void ChangeAvatar(AvatarData avatarData){ // newAvatarIdList.Remove(avatarData.id);