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 + " 本";
}
}
}