using System.Collections.Generic; using UnityEngine; namespace ServiceSim { /// /// ロボットの道順(v5b)。サイトが決めた曲がり角の点の並びを持つ。 /// /// 2026-10-22 にエイイチと決めたこと: /// Unity で道を決めるのをやめ、**道順はサイトが決めて渡す**。 /// サイトの試算は卓ごとの道(ふだん走らせる 1.0 m の道、届かなければ 0.8 m の道)を /// もう持っているので、それを曲がり角の点の並びにして JSON に入れてある。 /// Unity のロボットはその点を順にたどるだけ。 /// 人をよける・止まる・立ち往生は Unity の中で起きる(それを測るのが Unity の役目)。 /// /// JSON の形(layout の routes): /// from_pass["T05"] … 受け渡し口の前 → T05 の止まる位置 /// points(最初が受け渡し口の前・最後が止まる位置)/ use / width / length /// between["T05|T12"] … T05 の止まる位置 → T12 の止まる位置 /// 逆向き(T12 → T05)は点を逆にたどる /// 卓 → 受け渡し口は from_pass を逆にたどる /// public class RouteBook { /// 道順 1 本 public class Route { /// 曲がり角の点(XZ。y は 0) public readonly List points = new List(); /// normal(1.0 m の道)/ narrow(0.8 m の道) public string use = "normal"; /// その道の幅(m) public float width; /// JSON が持っている長さ(m) public float length; public bool IsNarrow { get { return use == "narrow"; } } /// 点を結んだ長さ(m)。JSON の length と突き合わせる用 public float PolylineLength { get { float d = 0f; for (int i = 1; i < points.Count; i++) d += Vector3.Distance(points[i - 1], points[i]); return d; } } } readonly Dictionary _fromPass = new Dictionary(); readonly Dictionary _between = new Dictionary(); public int FromPassCount { get { return _fromPass.Count; } } public int BetweenCount { get { return _between.Count; } } static long Key(int a, int b) { return (long)a * 100000L + b; } public void AddFromPass(int tableId, Route r) { _fromPass[tableId] = r; } public void AddBetween(int a, int b, Route r) { _between[Key(a, b)] = r; } public Route FromPass(int tableId) { Route r; return _fromPass.TryGetValue(tableId, out r) ? r : null; } /// a → b の道順。逆向きしか無ければ、その点を逆にたどる public List PointsBetween(int a, int b, out Route used, out bool reversed) { reversed = false; if (_between.TryGetValue(Key(a, b), out used)) return new List(used.points); if (_between.TryGetValue(Key(b, a), out used)) { reversed = true; List p = new List(used.points); p.Reverse(); return p; } used = null; return null; } /// 受け渡し口の前 → 卓 public List PointsFromPass(int tableId, out Route used) { used = FromPass(tableId); return used != null ? new List(used.points) : null; } /// 卓 → 受け渡し口の前(from_pass を逆にたどる) public List PointsToPass(int tableId, out Route used) { used = FromPass(tableId); if (used == null) return null; List p = new List(used.points); p.Reverse(); return p; } /// その卓へ行く道が、0.8 m の道を使うか(確かめの via_narrow) public bool UsesNarrow(int tableId) { Route r = FromPass(tableId); return r != null && r.IsNarrow; } public string UseOf(int tableId) { Route r = FromPass(tableId); return r != null ? r.use : ""; } /// 報告に出す覚え書き public string Summary() { int narrow = 0; foreach (KeyValuePair kv in _fromPass) if (kv.Value.IsNarrow) narrow++; return "受け渡し口から " + _fromPass.Count + " 本(うち 0.8 m の道 " + narrow + " 本)/ " + "卓から卓 " + _between.Count + " 本"; } } }