--- cs:140/Service/ServiceOps.cs +++ cs:141/Service/ServiceOps.cs @@ -279,6 +279,15 @@ readonly Dictionary> _lastBatch = new Dictionary>(); + /// + /// 止まる所の番号 → その所で降ろす皿(依頼 v8 の 1)。 + /// + /// StartRun に渡す stops を作るループは SlotOf が null の皿を飛ばすので、 + /// 「止まる所の番号=batch の番号」とは限らない。だからこの対応表で引く。 + /// + readonly Dictionary> _stopDishes = + new Dictionary>(); + int _nextDishId = 1; // ---- 記録(TripLogger と ExperimentRunner が読む)---- @@ -616,6 +625,8 @@ _pass.Clear(); _jobs.Clear(); _carrying.Clear(); + _stopDishes.Clear(); // 止まる所と皿の対応表(依頼 v8 の 1) + _lastBatch.Clear(); dishWaitMin.Clear(); seatWaitMin.Clear(); turnMin.Clear(); @@ -778,14 +789,21 @@ if (spots.Count > 0) r.SetStandbyPoint(spots[(_robots.Count - 1) % spots.Count]); } r.TripCompleted += OnRobotRunDone; + r.StopArrived += OnRobotStopArrived; // 卓に着いた時点で届いたにする(依頼 v8 の 1) } public void ClearRobots() { for (int i = 0; i < _robots.Count; i++) - if (_robots[i] != null) _robots[i].TripCompleted -= OnRobotRunDone; + { + if (_robots[i] == null) continue; + _robots[i].TripCompleted -= OnRobotRunDone; + _robots[i].StopArrived -= OnRobotStopArrived; + } _robots.Clear(); _carrying.Clear(); + _stopDishes.Clear(); + _lastBatch.Clear(); } /// 店の中の時刻を進める(ExperimentRunner が毎コマ呼ぶ) @@ -1530,7 +1548,10 @@ List batch = PickBatch(r); if (batch.Count == 0) continue; + // 止まる所と皿を、同じ並びで組む(依頼 v8 の 1)。 + // SlotOf が null の皿は止まる所を作れないので、どちらからも外す List stops = new List(); + List stopDishes = new List(); for (int k = 0; k < batch.Count; k++) { TableSlot s = SlotOf(batch[k].tableIndex); @@ -1541,10 +1562,12 @@ stop.aisleEntrance = s.aisleEntrance; stop.aisleZone = s.aisleZone; stops.Add(stop); + stopDishes.Add(batch[k]); } if (stops.Count == 0) continue; _carrying[r] = batch; + _stopDishes[r] = stopDishes; r.StartRun(stops, store.PassPoint, NowS); } } @@ -1599,8 +1622,37 @@ static float Flat(Vector3 d) { d.y = 0f; return d.magnitude; } /// - /// ロボットの1走りが終わった。届けた料理を記録し、 - /// 届けられなかった料理は受け渡し口の先頭に戻す。 + /// ロボットが止まる所(卓)に着いた(依頼 v8 の 1)。 + /// + /// サイトの試算と同じで、**卓に着いた時点でその皿は届いた**。 + /// 受け渡しの 25 秒(RobotSpec.tableDwellSec)はこのあとなので、 + /// 客は受け渡し口へ戻るのを待たずに食べ始められる + /// (前は往復の最後にまとめて届いたにしていて、料理の待ちが + /// 1皿あたり 1.0〜1.3 分長く出ていた)。 + /// + void OnRobotStopArrived(ServingRobotController r, int stopIndex) + { + List stopDishes; + if (!_stopDishes.TryGetValue(r, out stopDishes) || stopDishes == null) return; + if (stopIndex < 0 || stopIndex >= stopDishes.Count) return; + + DishArrived(stopDishes[stopIndex], true); + } + + /// + /// ロボットの1走りぶんの片づけが終わった(依頼 v8 の 2)。 + /// + /// ExperimentRunner は trips.csv を書くときに LastBatchOf を読むので、 + /// ServingRobotController.TripCompleted を直に受けると、呼ばれる順番によって + /// **1つ前の往復の皿**を読んでしまっていた。 + /// ここで片づけを終えてから出すこのイベントを受ければ、順番に頼らずに済む。 + /// + public event System.Action RunRecorded; + + /// + /// ロボットの1走りが終わった。 + /// 卓に着いた皿はもう届いているので何もしない。 + /// まだ届いていない皿(arrivedS < 0)だけを受け渡し口の先頭へ戻す。 /// void OnRobotRunDone(ServingRobotController r) { @@ -1609,6 +1661,7 @@ _lastBatch[r] = batch; // trips.csv を書くために残す _carrying[r] = new List(); + _stopDishes[r] = new List(); // なぜ届けられなかったか。ロボットが持っている結果から決める。 // v5 3章:動けなくなってもスタッフが動かせば走りは続くので、 @@ -1618,12 +1671,16 @@ : r.Stuck ? "動けなくなった" : "着かなかった"; - int done = Mathf.Clamp(r.StopsCompleted, 0, batch.Count); for (int i = 0; i < batch.Count; i++) { - if (i < done) DishArrived(batch[i], true); - else RequeueDish(batch[i], r.robotId, why); + // 卓に着いた時点で DishArrived してあるので、arrivedS で見分ける + // (StopsCompleted の数で数えない。止まる所と皿の並びは対応表で持っている) + if (batch[i].arrivedS >= 0f) continue; + RequeueDish(batch[i], r.robotId, why); } + + // 片づけが終わってから知らせる(ここで LastBatchOf を読んでよい) + if (RunRecorded != null) RunRecorded(r); } /// そのロボットがいま載せている料理