| | |
| | | /// <returns>返回路由实体集合。</returns> |
| | | public List<Dt_Router> QueryNextRoutes(string startPosi, string endPosi) |
| | | { |
| | | //todo 方法需优化 |
| | | List<Dt_Router> routers = new List<Dt_Router>(); |
| | | try |
| | | { |
| | | //查询下一个路由信息 |
| | | List<Dt_Router> dt_Routers = BaseDal.QueryData(x => (x.NextPosi == endPosi || x.ChildPosi == endPosi), new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | if (dt_Routers.Count > 0) |
| | | // 一次性查询所有路由数据到内存 |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => true); |
| | | |
| | | // 在内存中进行路径搜索 |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | | |
| | | if (routers.Count == 0) |
| | | { |
| | | foreach (var item in dt_Routers) |
| | | { |
| | | //如果下一个路由的起点和终点都匹配,则添加到路由列表中 |
| | | if (item.StartPosi == startPosi && !routers.Any(x => x.Id == item.Id)) |
| | | { |
| | | routers.Add(item); |
| | | } |
| | | else |
| | | { |
| | | //否则,递归查询下一个路由的起点 |
| | | List<Dt_Router> tempRouters = QueryNextRoutes(startPosi, item.StartPosi); |
| | | foreach (var router in tempRouters) |
| | | { |
| | | //如果下一个路由的起点和终点都匹配,则添加到路由列表中 |
| | | if (router.StartPosi == startPosi && !routers.Any(x => x.Id == router.Id)) |
| | | { |
| | | routers.Add(router); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //如果查询不到下一个路由信息,则抛出异常 |
| | | throw new Exception($"该路径未配置或配置错误,请检查设备路由信息,起点:【{startPosi}】,终点:【{endPosi}】"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | //throw new Exception(ex.Message); |
| | | //记录错误信息 |
| | | // 记录错误信息 |
| | | } |
| | | return routers; |
| | | } |
| | |
| | | /// <returns>返回路由实体集合。</returns> |
| | | public List<Dt_Router> QueryNextRoutes(string startPosi, string endPosi, int routeType) |
| | | { |
| | | //todo 方法需优化 |
| | | List<Dt_Router> routers = new List<Dt_Router>(); |
| | | try |
| | | { |
| | | //查询下一个路由信息 |
| | | List<Dt_Router> dt_Routers = BaseDal.QueryData(x => (x.NextPosi == endPosi || x.ChildPosi == endPosi) && x.InOutType == routeType, new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | if (dt_Routers.Count > 0) |
| | | // 一次性查询指定类型的所有路由数据到内存 |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | |
| | | // 在内存中进行路径搜索 |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | | |
| | | if (routers.Count == 0) |
| | | { |
| | | foreach (var item in dt_Routers) |
| | | { |
| | | //如果下一个路由的起点和终点都匹配,则添加到路由列表中 |
| | | if (item.StartPosi == startPosi && !routers.Any(x => x.Id == item.Id)) |
| | | { |
| | | routers.Add(item); |
| | | } |
| | | else |
| | | { |
| | | //否则,递归查询下一个路由的起点 |
| | | List<Dt_Router> tempRouters = QueryNextRoutes(startPosi, item.StartPosi, routeType); |
| | | foreach (var router in tempRouters) |
| | | { |
| | | //如果下一个路由的起点和终点都匹配,则添加到路由列表中 |
| | | if (router.StartPosi == startPosi && !routers.Any(x => x.Id == router.Id)) |
| | | { |
| | | routers.Add(router); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //如果查询不到下一个路由信息,则抛出异常 |
| | | throw new Exception($"该路径未配置或配置错误,请检查设备路由信息,起点:【{startPosi}】,终点:【{endPosi}】"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | //throw new Exception(ex.Message); |
| | | //记录错误信息 |
| | | // 记录错误信息 |
| | | } |
| | | return routers; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 在内存中查找从起点到终点的所有路由 |
| | | /// </summary> |
| | | /// <param name="startPosi">起点位置</param> |
| | | /// <param name="endPosi">终点位置</param> |
| | | /// <param name="allRouters">所有路由数据</param> |
| | | /// <param name="routeType">路由类型(可选)</param> |
| | | /// <returns>符合条件的路由列表</returns> |
| | | private List<Dt_Router> FindRoutesInMemory(string startPosi, string endPosi, List<Dt_Router> allRouters, int? routeType) |
| | | { |
| | | List<Dt_Router> result = new List<Dt_Router>(); |
| | | HashSet<int> addedIds = new HashSet<int>(); |
| | | |
| | | // 构建索引:以 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<Dt_Router> endRouters = new List<Dt_Router>(); |
| | | 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<Dt_Router> path)> queue = new Queue<(Dt_Router, List<Dt_Router>)>(); |
| | | |
| | | // 将所有终点路由加入队列 |
| | | foreach (var endRouter in endRouters) |
| | | { |
| | | queue.Enqueue((endRouter, new List<Dt_Router> { 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<Dt_Router> parentRouters = new List<Dt_Router>(); |
| | | 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<Dt_Router>(currentPath) { parentRouter }; |
| | | queue.Enqueue((parentRouter, newPath)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据起点获取下一个单个子节点路由 |
| | | /// </summary> |
| | | /// <param name="startPosi">起点/当前位置</param> |
| | | /// <returns>返回下一个路由节点,如果没有则返回null</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi) |
| | | { |
| | | try |
| | | { |
| | | // 查询从起点出发的所有路由 |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | |
| | | // 返回第一个路由 |
| | | return routes.FirstOrDefault(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // 记录错误信息 |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据起点和路由类型获取下一个单个子节点路由 |
| | | /// </summary> |
| | | /// <param name="startPosi">起点/当前位置</param> |
| | | /// <param name="routeType">路由类型</param> |
| | | /// <returns>返回下一个路由节点,如果没有则返回null</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi, int routeType) |
| | | { |
| | | try |
| | | { |
| | | // 查询从起点出发的指定类型路由 |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | |
| | | // 返回第一个路由 |
| | | return routes.FirstOrDefault(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // 记录错误信息 |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据起点、终点方向和路由类型获取下一个单个子节点路由(智能选择朝向终点的路由) |
| | | /// </summary> |
| | | /// <param name="startPosi">起点/当前位置</param> |
| | | /// <param name="endPosi">终点位置(用于方向判断)</param> |
| | | /// <param name="routeType">路由类型</param> |
| | | /// <returns>返回下一个路由节点,优先返回朝向终点的路由,如果没有则返回null</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi, string endPosi, int routeType) |
| | | { |
| | | try |
| | | { |
| | | // 查询从起点出发的指定类型路由 |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, |
| | | new Dictionary<string, OrderByType> { { 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<Dt_Router> 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; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取从起点到终点的完整路径(按顺序返回每个子节点路由) |
| | | /// </summary> |
| | | /// <param name="startPosi">起点位置</param> |
| | | /// <param name="endPosi">终点位置</param> |
| | | /// <param name="routeType">路由类型</param> |
| | | /// <returns>返回有序的路由列表,如果找不到路径则返回空列表</returns> |
| | | public List<Dt_Router> QueryRoutePath(string startPosi, string endPosi, int routeType) |
| | | { |
| | | List<Dt_Router> path = new List<Dt_Router>(); |
| | | string currentPosi = startPosi; |
| | | HashSet<string> visitedPositions = new HashSet<string>(); |
| | | |
| | | 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<Dt_Router>(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return new List<Dt_Router>(); |
| | | } |
| | | |
| | | return path; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | /// <param name="deviceCode">设备编号</param> |
| | | /// <returns>返回路由点位编号(输送线站台编号)集合</returns> |
| | | // 根据设备编码查询所有位置 |
| | | public List<string> QueryAllPositions(string deviceCode) |
| | | { |
| | | // 创建一个字符串列表,用于存储所有位置 |
| | |
| | | // 遍历所有结束的路由 |
| | | foreach (var item in dt_Routers) |
| | | { |
| | | // 获取当前路由的子路由 |
| | | string routes = $"{item.NextPosi},"; |
| | | // 获取当前路由的父路由 |
| | | string str = GetPreviousRoutes(item.StartPosi, allRouters, item.InOutType); |
| | | // 如果父路由不为空 |
| | | if (!string.IsNullOrEmpty(str)) |
| | | // 获取所有可能的完整路径 |
| | | List<List<string>> allPaths = GetAllPaths(item.StartPosi, item.NextPosi, allRouters, item.InOutType); |
| | | |
| | | // 为每条独立路径生成结果 |
| | | foreach (var path in allPaths) |
| | | { |
| | | // 去掉最后一个逗号 |
| | | if (str.EndsWith(",")) |
| | | str = str.Substring(0, str.Length - 1); |
| | | // 将父路由添加到子路由中 |
| | | routes += str; |
| | | } |
| | | // 如果当前路由是入口 |
| | | if (item.InOutType == RouterInOutType.In.ObjToInt()) |
| | | { |
| | | // 将子路由反转并添加到data中 |
| | | List<string> itemRouters = routes.Split(",").Reverse().ToList(); |
| | | object obj = new { type = RouterInOutType.In, routes = itemRouters }; |
| | | data.Add(obj); |
| | | } |
| | | // 如果当前路由是出口 |
| | | else |
| | | { |
| | | // 将子路由反转并添加到data中 |
| | | List<string> itemRouters = routes.Split(",").Reverse().ToList(); |
| | | object obj = new { type = RouterInOutType.Out, routes = itemRouters }; |
| | | data.Add(obj); |
| | | // 如果当前路由是入口 |
| | | if (item.InOutType == RouterInOutType.In.ObjToInt()) |
| | | { |
| | | object obj = new { type = RouterInOutType.In, routes = path }; |
| | | data.Add(obj); |
| | | } |
| | | // 如果当前路由是出口 |
| | | else |
| | | { |
| | | object obj = new { type = RouterInOutType.Out, routes = path }; |
| | | data.Add(obj); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | return data; |
| | | } |
| | | |
| | | private string GetPreviousRoutes(string startPosi, List<Dt_Router> allRouters, int routerType) |
| | | /// <summary> |
| | | /// 获取从起点到终点的所有完整路径 |
| | | /// </summary> |
| | | /// <param name="startPosi">当前起始位置</param> |
| | | /// <param name="endPosi">终点位置</param> |
| | | /// <param name="allRouters">所有路由数据</param> |
| | | /// <param name="routerType">路由类型</param> |
| | | /// <returns>所有完整路径列表,每条路径是从起点到终点的位置列表</returns> |
| | | private List<List<string>> GetAllPaths(string startPosi, string endPosi, List<Dt_Router> allRouters, int routerType) |
| | | { |
| | | // 定义一个空字符串routers |
| | | string routers = string.Empty; |
| | | // 判断startPosi是否为空 |
| | | if (!string.IsNullOrEmpty(startPosi)) |
| | | List<List<string>> result = new List<List<string>>(); |
| | | |
| | | // 从终点开始反向查找所有路径 |
| | | List<List<string>> reversePaths = new List<List<string>>(); |
| | | BuildReversePaths(startPosi, new List<string> { endPosi, startPosi }, allRouters, routerType, reversePaths); |
| | | |
| | | // 将反向路径转为正向(从起点到终点) |
| | | foreach (var reversePath in reversePaths) |
| | | { |
| | | // 判断routers是否以逗号结尾 |
| | | if (!routers.EndsWith(",")) |
| | | // 如果不是,则将startPosi添加到routers中,并在后面加上逗号 |
| | | routers += $"{startPosi},"; |
| | | else |
| | | // 如果是,则将startPosi添加到routers中 |
| | | routers += $"{startPosi}"; |
| | | result.Add(reversePath.AsEnumerable().Reverse().ToList()); |
| | | } |
| | | // 从allRouters中筛选出NextPosi等于startPosi且InOutType等于routerType的元素,并转换为List |
| | | List<Dt_Router> preRouters = allRouters.Where(x => x.NextPosi == startPosi && x.InOutType == routerType).ToList(); |
| | | // 遍历preRouters中的每个元素 |
| | | foreach (var item in preRouters) |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 递归构建反向路径(从终点向起点查找) |
| | | /// </summary> |
| | | /// <param name="currentStartPosi">当前节点的起始位置</param> |
| | | /// <param name="currentPath">当前已构建的路径(反向,从终点开始)</param> |
| | | /// <param name="allRouters">所有路由数据</param> |
| | | /// <param name="routerType">路由类型</param> |
| | | /// <param name="result">收集所有完整路径</param> |
| | | private void BuildReversePaths(string currentStartPosi, List<string> currentPath, List<Dt_Router> allRouters, int routerType, List<List<string>> result) |
| | | { |
| | | // 查找当前节点的前置节点(NextPosi等于当前StartPosi的路由) |
| | | List<Dt_Router> preRouters = allRouters.Where(x => x.NextPosi == currentStartPosi && x.InOutType == routerType).ToList(); |
| | | |
| | | // 如果没有前置节点,说明已经到达路径起点,保存当前路径 |
| | | if (preRouters.Count == 0) |
| | | { |
| | | // 调用GetPreviousRoutes方法,传入item.StartPosi、allRouters和routerType,并将返回值赋给str |
| | | string str = GetPreviousRoutes(item.StartPosi, allRouters, routerType); |
| | | // 判断str是否为空 |
| | | if (!string.IsNullOrEmpty(str)) |
| | | { |
| | | // 判断routers是否以逗号结尾 |
| | | if (routers.EndsWith(",")) |
| | | // 如果是,则将str添加到routers中 |
| | | routers += $"{str}"; |
| | | else |
| | | // 如果不是,则将str添加到routers中,并在后面加上逗号 |
| | | routers += $"{str},"; |
| | | } |
| | | result.Add(new List<string>(currentPath)); |
| | | return; |
| | | } |
| | | // 返回routers |
| | | return routers; |
| | | |
| | | // 对每个前置节点,创建新的路径分支 |
| | | foreach (var preRouter in preRouters) |
| | | { |
| | | // 创建新的路径副本 |
| | | List<string> newPath = new List<string>(currentPath); |
| | | newPath.Add(preRouter.StartPosi); |
| | | |
| | | // 递归查找前置节点 |
| | | BuildReversePaths(preRouter.StartPosi, newPath, allRouters, routerType, result); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |