using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Repository;
using ICacheService = WIDESEAWCS_Core.Caches.ICacheService;
namespace WIDESEAWCS_QuartzJob.Service
{
///
/// 路由配置业务层
///
public class RouterService : ServiceBase, IRouterService
{
private readonly IDeviceProtocolRepository _deviceProtocolRepository;
private readonly IDeviceInfoRepository _deviceInfoRepository;
private readonly ICacheService _cacheService;
///
/// 路由配置业务层
///
///
///
///
public RouterService(IRouterRepository BaseDal, IDeviceProtocolRepository deviceProtocolRepository, IDeviceInfoRepository deviceInfoRepository, ICacheService cacheService) : base(BaseDal)
{
_deviceProtocolRepository = deviceProtocolRepository;
_deviceInfoRepository = deviceInfoRepository;
_cacheService = cacheService;
}
///
/// 根据起点/当前位置、终点获取下一个子节点。
///
/// 起点/当前位置。
/// 终点。
/// 返回路由实体集合。
public List QueryNextRoutes(string startPosi, string endPosi)
{
List routers = new List();
try
{
// 一次性查询所有路由数据到内存
List allRouters = BaseDal.QueryData(x => true);
// 在内存中进行路径搜索
routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null);
if (routers.Count == 0)
{
throw new Exception($"该路径未配置或配置错误,请检查设备路由信息,起点:【{startPosi}】,终点:【{endPosi}】");
}
}
catch (Exception ex)
{
// 记录错误信息
}
return routers;
}
///
/// 根据起点/当前位置、终点获取下一个子节点。
///
/// 起点/当前位置。
/// 终点。
/// 路由类型。
/// 返回路由实体集合。
public List QueryNextRoutes(string startPosi, string endPosi, int routeType)
{
List routers = new List();
try
{
// 一次性查询指定类型的所有路由数据到内存
List allRouters = BaseDal.QueryData(x => x.InOutType == routeType);
// 在内存中进行路径搜索
routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType);
if (routers.Count == 0)
{
throw new Exception($"该路径未配置或配置错误,请检查设备路由信息,起点:【{startPosi}】,终点:【{endPosi}】");
}
}
catch (Exception ex)
{
// 记录错误信息
}
return routers;
}
///
/// 在内存中查找从起点到终点的所有路由
///
/// 起点位置
/// 终点位置
/// 所有路由数据
/// 路由类型(可选)
/// 符合条件的路由列表
private List FindRoutesInMemory(string startPosi, string endPosi, List allRouters, int? routeType)
{
List result = new List();
HashSet addedIds = new HashSet();
// 构建索引:以 NextPosi 和 ChildPosi 为键的字典,加速查找
var routersByNext = allRouters
.GroupBy(r => r.NextPosi)
.ToDictionary(g => g.Key, g => g.ToList());
var routersByChild = allRouters
.GroupBy(r => r.ChildPosi)
.ToDictionary(g => g.Key, g => g.ToList());
// 找到所有指向终点的路由(终点的父节点)
List endRouters = new List();
if (routersByNext.ContainsKey(endPosi))
endRouters.AddRange(routersByNext[endPosi]);
if (routersByChild.ContainsKey(endPosi))
endRouters.AddRange(routersByChild[endPosi].Where(r => !endRouters.Any(e => e.Id == r.Id)));
// 按 IsEnd 降序排序
endRouters = endRouters.OrderByDescending(r => r.IsEnd).ToList();
// 使用队列进行广度优先搜索
Queue<(Dt_Router router, List path)> queue = new Queue<(Dt_Router, List)>();
// 将所有终点路由加入队列
foreach (var endRouter in endRouters)
{
queue.Enqueue((endRouter, new List { endRouter }));
}
// 广度优先搜索
while (queue.Count > 0)
{
var (currentRouter, currentPath) = queue.Dequeue();
// 如果当前路由的起点就是目标起点,找到完整路径
if (currentRouter.StartPosi == startPosi)
{
// 将路径中的所有路由添加到结果中(去重)
foreach (var router in currentPath)
{
if (!addedIds.Contains(router.Id))
{
result.Add(router);
addedIds.Add(router.Id);
}
}
continue;
}
// 查找当前路由起点的父路由
List parentRouters = new List();
if (routersByNext.ContainsKey(currentRouter.StartPosi))
parentRouters.AddRange(routersByNext[currentRouter.StartPosi]);
if (routersByChild.ContainsKey(currentRouter.StartPosi))
parentRouters.AddRange(routersByChild[currentRouter.StartPosi].Where(r => !parentRouters.Any(p => p.Id == r.Id)));
// 将父路由加入队列
foreach (var parentRouter in parentRouters)
{
// 避免循环引用
if (!currentPath.Any(p => p.Id == parentRouter.Id))
{
var newPath = new List(currentPath) { parentRouter };
queue.Enqueue((parentRouter, newPath));
}
}
}
return result;
}
///
/// 根据起点获取下一个单个子节点路由
///
/// 起点/当前位置
/// 返回下一个路由节点,如果没有则返回null
public Dt_Router QueryNextRoute(string startPosi)
{
try
{
// 查询从起点出发的所有路由
List routes = BaseDal.QueryData(x => x.StartPosi == startPosi,
new Dictionary { { nameof(Dt_Router.IsEnd), OrderByType.Desc } });
// 返回第一个路由
return routes.FirstOrDefault();
}
catch (Exception ex)
{
// 记录错误信息
return null;
}
}
///
/// 根据起点和路由类型获取下一个单个子节点路由
///
/// 起点/当前位置
/// 路由类型
/// 返回下一个路由节点,如果没有则返回null
public Dt_Router QueryNextRoute(string startPosi, int routeType)
{
try
{
// 查询从起点出发的指定类型路由
List routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType,
new Dictionary { { nameof(Dt_Router.IsEnd), OrderByType.Desc } });
// 返回第一个路由
return routes.FirstOrDefault();
}
catch (Exception ex)
{
// 记录错误信息
return null;
}
}
///
/// 根据起点、终点方向和路由类型获取下一个单个子节点路由(智能选择朝向终点的路由)
///
/// 起点/当前位置
/// 终点位置(用于方向判断)
/// 路由类型
/// 返回下一个路由节点,优先返回朝向终点的路由,如果没有则返回null
public Dt_Router QueryNextRoute(string startPosi, string endPosi, int routeType)
{
try
{
// 查询从起点出发的指定类型路由
List routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType,
new Dictionary { { nameof(Dt_Router.IsEnd), OrderByType.Desc } });
if (routes.Count == 0)
return null;
// 优先选择直接指向终点的路由
Dt_Router directRoute = routes.FirstOrDefault(x => x.NextPosi == endPosi || x.ChildPosi == endPosi);
if (directRoute != null)
return directRoute;
// 如果没有直接路由,使用查找算法找到朝向终点的路由
List allRouters = BaseDal.QueryData(x => x.InOutType == routeType);
foreach (var route in routes)
{
// 检查从这个路由的下一个位置是否能到达终点
var pathToEnd = FindRoutesInMemory(route.NextPosi, endPosi, allRouters, routeType);
if (pathToEnd.Count > 0)
return route;
}
// 如果都不能到达终点,返回第一个路由
return routes.FirstOrDefault();
}
catch (Exception ex)
{
// 记录错误信息
return null;
}
}
///
/// 根据起点、终点方向和路由类型获取下一个单个子节点路由(智能选择朝向终点的路由)
///
/// 起点/当前位置
/// 终点位置(用于方向判断)
/// 返回下一个路由节点,优先返回朝向终点的路由,如果没有则返回null
public Dt_Router QueryNextRoute(string startPosi, string endPosi)
{
try
{
// 查询从起点出发的指定类型路由
List routes = BaseDal.QueryData(x => x.StartPosi == startPosi,
new Dictionary { { nameof(Dt_Router.IsEnd), OrderByType.Desc } });
if (routes.Count == 0)
return null;
// 优先选择直接指向终点的路由
Dt_Router directRoute = routes.FirstOrDefault(x => x.NextPosi == endPosi || x.ChildPosi == endPosi);
if (directRoute != null)
return directRoute;
//// 如果没有直接路由,使用查找算法找到朝向终点的路由
//List allRouters = BaseDal.QueryData(x => x.InOutType == routeType);
//foreach (var route in routes)
//{
// // 检查从这个路由的下一个位置是否能到达终点
// var pathToEnd = FindRoutesInMemory(route.NextPosi, endPosi, allRouters, routeType);
// if (pathToEnd.Count > 0)
// return route;
//}
// 如果都不能到达终点,返回第一个路由
return routes.FirstOrDefault();
}
catch (Exception ex)
{
// 记录错误信息
return null;
}
}
///
/// 获取从起点到终点的完整路径(按顺序返回每个子节点路由)
///
/// 起点位置
/// 终点位置
/// 路由类型
/// 返回有序的路由列表,如果找不到路径则返回空列表
public List QueryRoutePath(string startPosi, string endPosi, int routeType)
{
List path = new List();
string currentPosi = startPosi;
HashSet visitedPositions = new HashSet();
try
{
while (currentPosi != endPosi)
{
if (visitedPositions.Contains(currentPosi))
{
break;
}
visitedPositions.Add(currentPosi);
Dt_Router nextRoute = QueryNextRoute(currentPosi, endPosi, routeType);
if (nextRoute == null)
{
break;
}
path.Add(nextRoute);
currentPosi = nextRoute.NextPosi;
if (path.Count > 1000)
{
break;
}
}
if (currentPosi != endPosi)
{
return new List();
}
}
catch (Exception ex)
{
return new List();
}
return path;
}
///
/// 根据设备编号获取对应的路由点位编号(输送线站台编号)信息
///
/// 设备编号
/// 返回路由点位编号(输送线站台编号)集合
public List QueryAllPositions(string deviceCode)
{
// 创建一个字符串列表,用于存储所有位置
List positions = new List();
var device = _cacheService.Get>($"{RedisPrefix.System}:{RedisName.DevicePositions}:{deviceCode}");
if (device.IsNullOrEmpty())
{
try
{
// 查询所有进入路由器的位置
List inRouterPositions = BaseDal.QueryData(x => x.ChildPosiDeviceCode == deviceCode && x.InOutType == RouterInOutType.In.ObjToInt()).GroupBy(x => x.StartPosi).Select(x => x.Key).ToList();
// 查询所有离开路由器的位置
List outRouterPositions = BaseDal.QueryData(x => x.ChildPosiDeviceCode == deviceCode && x.InOutType == RouterInOutType.Out.ObjToInt()).GroupBy(x => x.ChildPosi).Select(x => x.Key).ToList();
// 将进入和离开路由器的位置添加到列表中
positions.AddRange(inRouterPositions);
positions.AddRange(outRouterPositions);
// 返回去重后的位置列表
return positions.GroupBy(x => x).Select(x => x.Key).ToList();
}
catch
{
}
finally
{
_cacheService.TryAdd($"{RedisPrefix.System}:{RedisName.DevicePositions}:{deviceCode}", positions);
}
}
else
positions = device;
// 返回位置列表
return positions;
}
///
/// 获取路由表中所有完整的路由信息(前端调用展示数据)。
///
/// 匿名对象集合。
public List