路径算法调整为动态规划方式,新增预任务申请功能
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Org.BouncyCastle.Asn1.Mozilla;
|
||||||
|
|
||||||
namespace Tnb.WarehouseMgr.Entities.Consts
|
namespace Tnb.WarehouseMgr.Entities.Consts
|
||||||
{
|
{
|
||||||
@@ -12,5 +13,21 @@ namespace Tnb.WarehouseMgr.Entities.Consts
|
|||||||
/// 出入库单据状态TypeID
|
/// 出入库单据状态TypeID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string WMS_INSTOCK_D_BILL_STATUS_TYPEID = "25065133038101";
|
public const string WMS_INSTOCK_D_BILL_STATUS_TYPEID = "25065133038101";
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务生成EnCode
|
||||||
|
/// </summary>
|
||||||
|
public const string WMS_PRETASK_H_ENCODE = "PreTaskGen";
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务单据状态-待下发Id
|
||||||
|
/// </summary>
|
||||||
|
public const string PRETASK_BILL_STATUS_DXF_ID = "26126822610469";
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务生成业务类型-载具移入Id
|
||||||
|
/// </summary>
|
||||||
|
public const string BIZTYPE_MOVEIN_ID = "26121988909861";
|
||||||
|
/// <summary>
|
||||||
|
/// 单据状态-作业中
|
||||||
|
/// </summary>
|
||||||
|
public const string BILLSTATUS_ON_ID = "25065143245845";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Tnb.WarehouseMgr.Entities.Dto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 生成预任务成功后输入参数
|
||||||
|
/// </summary>
|
||||||
|
public class GenPreTaskUpInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务Id
|
||||||
|
/// </summary>
|
||||||
|
public string PreTaskId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 载具Id
|
||||||
|
/// </summary>
|
||||||
|
public string CarryId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 载具起始库位Id
|
||||||
|
/// </summary>
|
||||||
|
public string CarryStartLocationId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 载具起始库位编号
|
||||||
|
/// </summary>
|
||||||
|
public string CarryStartLocationCode { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 库位IdS
|
||||||
|
/// </summary>
|
||||||
|
public List<string> LocationIds { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务操作记录
|
||||||
|
/// </summary>
|
||||||
|
public List<WmsHandleH> PreTaskRecords { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 预任务条码记录
|
||||||
|
/// </summary>
|
||||||
|
public List<WmsHandleCode> PreTaskHandleCodes { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Tnb.WarehouseMgr.Entities
|
||||||
|
{
|
||||||
|
public interface IWmsRoadEntity
|
||||||
|
{
|
||||||
|
string startpoint_id { get; set; }
|
||||||
|
string endpoint_id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -134,4 +134,24 @@ public partial class WmsPretaskH : BaseEntity<string>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? timestamp { get; set; }
|
public DateTime? timestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程任务Id
|
||||||
|
/// </summary>
|
||||||
|
public string? f_flowtaskid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程引擎Id
|
||||||
|
/// </summary>
|
||||||
|
public string? f_flowid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 起始库位编号
|
||||||
|
/// </summary>
|
||||||
|
public string startlocation_code { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标库位编号
|
||||||
|
/// </summary>
|
||||||
|
public string endlocation_code { get; set; } = string.Empty;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Tnb.WarehouseMgr.Entities;
|
|||||||
/// 路段管理表
|
/// 路段管理表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("wms_road")]
|
[SugarTable("wms_road")]
|
||||||
public partial class WmsRoad : BaseEntity<string>
|
public partial class WmsRoad : BaseEntity<string>, IWmsRoadEntity
|
||||||
{
|
{
|
||||||
public WmsRoad()
|
public WmsRoad()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,5 +34,11 @@ namespace Tnb.WarehouseMgr.Interfaces
|
|||||||
/// <param name="preTasks"></param>
|
/// <param name="preTasks"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<bool> GenPreTask(List<WmsPretaskH> preTasks);
|
Task<bool> GenPreTask(List<WmsPretaskH> preTasks);
|
||||||
|
/// <summary>
|
||||||
|
/// 生成预任务成功后操作
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task GenTaskHandleAfter(GenPreTaskUpInput input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,5 +16,7 @@ namespace Tnb.WarehouseMgr
|
|||||||
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
|
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
|
||||||
{
|
{
|
||||||
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
|
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
215
WarehouseMgr/Tnb.WarehouseMgr/Dijkstra.cs
Normal file
215
WarehouseMgr/Tnb.WarehouseMgr/Dijkstra.cs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
//using System;
|
||||||
|
//using System.Collections.Generic;
|
||||||
|
//using System.Linq;
|
||||||
|
//using System.Text;
|
||||||
|
//using System.Threading.Tasks;
|
||||||
|
//using JNPF.Common.Contracts;
|
||||||
|
//using NPOI.SS.Formula.Functions;
|
||||||
|
//using Tnb.WarehouseMgr.Entities;
|
||||||
|
|
||||||
|
//namespace Tnb.WarehouseMgr
|
||||||
|
//{
|
||||||
|
// /// <summary>
|
||||||
|
// /// 迪杰斯特拉(最短路径算法)
|
||||||
|
// /// </summary>
|
||||||
|
// public class Dijkstra<T> where T : BaseEntity<string>, IWmsRoadEntity, new()
|
||||||
|
// {
|
||||||
|
// public static int MAX = int.MaxValue;
|
||||||
|
|
||||||
|
// public int mEdgNum; // 边的数量
|
||||||
|
// public VNode[] mVexs; // 顶点数组
|
||||||
|
// //private EData[] edges; //边的数组
|
||||||
|
// /*
|
||||||
|
// * 创建图
|
||||||
|
// *
|
||||||
|
// * 参数说明:
|
||||||
|
// * vexs -- 顶点数组
|
||||||
|
// * edges -- 边
|
||||||
|
// */
|
||||||
|
// public Dijkstra(string[] vexs, EData[] edges)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// // 初始化"顶点数"和"边数"
|
||||||
|
// int vlen = vexs.Length;
|
||||||
|
// int elen = edges.Length;
|
||||||
|
|
||||||
|
// // 初始化"顶点"
|
||||||
|
// mVexs = new VNode[vlen];
|
||||||
|
// for (int i = 0; i < mVexs.Length; i++)
|
||||||
|
// {
|
||||||
|
// mVexs[i] = new VNode();
|
||||||
|
// mVexs[i].data = vexs[i];
|
||||||
|
// mVexs[i].firstEdge = null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 初始化"边"
|
||||||
|
// mEdgNum = elen;
|
||||||
|
// for (int i = 0; i < elen; i++)
|
||||||
|
// {
|
||||||
|
// // 读取边的起始顶点和结束顶点
|
||||||
|
// string c1 = edges[i].start;
|
||||||
|
// string c2 = edges[i].end;
|
||||||
|
// int weight = edges[i].weight;
|
||||||
|
|
||||||
|
// // 读取边的起始顶点和结束顶点
|
||||||
|
// int p1 = GetPosition(c1);
|
||||||
|
// int p2 = GetPosition(c2);
|
||||||
|
// // 初始化node1
|
||||||
|
// ENode node1 = new ENode();
|
||||||
|
// node1.ivex = p2;
|
||||||
|
// node1.weight = weight;
|
||||||
|
// // 将node1链接到"p1所在链表的末尾"
|
||||||
|
// if (mVexs[p1].firstEdge == null)
|
||||||
|
// mVexs[p1].firstEdge = node1;
|
||||||
|
// else
|
||||||
|
// LinkLast(mVexs[p1].firstEdge, node1);
|
||||||
|
// // 初始化node2
|
||||||
|
// ENode node2 = new ENode();
|
||||||
|
// node2.ivex = p1;
|
||||||
|
// node2.weight = weight;
|
||||||
|
// // 将node2链接到"p2所在链表的末尾"
|
||||||
|
// if (mVexs[p2].firstEdge == null)
|
||||||
|
// mVexs[p2].firstEdge = node2;
|
||||||
|
// else
|
||||||
|
// LinkLast(mVexs[p2].firstEdge, node2);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// * 将node节点链接到list的最后
|
||||||
|
// */
|
||||||
|
// private void LinkLast(ENode list, ENode node)
|
||||||
|
// {
|
||||||
|
// ENode p = list;
|
||||||
|
|
||||||
|
// while (p.nextEdge != null)
|
||||||
|
// p = p.nextEdge;
|
||||||
|
// p.nextEdge = node;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// * 返回ch位置
|
||||||
|
// */
|
||||||
|
// private int GetPosition(string ch)
|
||||||
|
// {
|
||||||
|
// for (int i = 0; i < mVexs.Length; i++)
|
||||||
|
// if (mVexs[i].data == ch)
|
||||||
|
// return i;
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// * 获取边<start, end>的权值;若start和end不是连通的,则返回无穷大。
|
||||||
|
// */
|
||||||
|
// private int GetWeight(int start, int end)
|
||||||
|
// {
|
||||||
|
// if (start == end)
|
||||||
|
// return 0;
|
||||||
|
|
||||||
|
// ENode node = mVexs[start].firstEdge;
|
||||||
|
// while (node != null)
|
||||||
|
// {
|
||||||
|
// if (end == node.ivex)
|
||||||
|
// return node.weight;
|
||||||
|
// node = node.nextEdge;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return MAX;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /*
|
||||||
|
// * Dijkstra最短路径。
|
||||||
|
// * 即,统计图中"起点D"到其它各个顶点的最短路径。
|
||||||
|
// *
|
||||||
|
// * 参数说明:
|
||||||
|
// * vs -- 起始顶点(start vertex)。
|
||||||
|
// * prev -- 前驱顶点数组。即,prev[i]的值是"起点D"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
|
||||||
|
// * dist -- 长度数组。即,dist[i]是"起点D"到"顶点i"的最短路径的长度。
|
||||||
|
// */
|
||||||
|
// public void CalcDijkstra(int vs, int[] prev, int[] dist, List<T> roads)
|
||||||
|
// {
|
||||||
|
// //List<T> vertexs = new(); //最短路径串联的点位列表
|
||||||
|
// // flag[i]=true表示"起点D"到"顶点i"的最短路径已成功获取。
|
||||||
|
// bool[] flag = new bool[mVexs.Length];
|
||||||
|
|
||||||
|
// // 初始化
|
||||||
|
// for (int i = 0; i < mVexs.Length; i++)
|
||||||
|
// {
|
||||||
|
// flag[i] = false; // 顶点i的最短路径还没获取到。
|
||||||
|
// prev[i] = 0; // 顶点i的前驱顶点为0。
|
||||||
|
// dist[i] = GetWeight(vs, i); // 顶点i的最短路径为"起点D"到"顶点i"的权。
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 对"起点D"自身进行初始化
|
||||||
|
// flag[vs] = true;
|
||||||
|
// dist[vs] = 0;
|
||||||
|
|
||||||
|
// // 遍历mVexs.Length-1次;每次找出一个顶点的最短路径。
|
||||||
|
// int k = 0;
|
||||||
|
// for (int i = 1; i < mVexs.Length; i++)
|
||||||
|
// {
|
||||||
|
// // 寻找当前最小的路径
|
||||||
|
// // 即,在未获取最短路径的顶点中,找到离起点D最近的顶点(k)。
|
||||||
|
// int min = MAX;
|
||||||
|
// for (int j = 0; j < mVexs.Length; j++)
|
||||||
|
// {
|
||||||
|
// if (flag[j] == false && dist[j] < min)
|
||||||
|
// {
|
||||||
|
// min = dist[j];
|
||||||
|
// k = j;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // 标记"顶点k"为已经获取到最短路径
|
||||||
|
// flag[k] = true;
|
||||||
|
// // 更新当前最短路径和前驱顶点
|
||||||
|
// // 即,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
|
||||||
|
// for (int j = 0; j < mVexs.Length; j++)
|
||||||
|
// {
|
||||||
|
// int tmp = GetWeight(k, j);
|
||||||
|
// tmp = (tmp == MAX ? MAX : (min + tmp)); // 防止溢出
|
||||||
|
// if (flag[j] == false && (tmp < dist[j]))
|
||||||
|
// {
|
||||||
|
// dist[j] = tmp;
|
||||||
|
// prev[j] = k;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// 邻接表中表对应的链表的顶点
|
||||||
|
// /// </summary>
|
||||||
|
// public class ENode
|
||||||
|
// {
|
||||||
|
// public int ivex; // 该边所指向的顶点的位置
|
||||||
|
// public int weight; // 该边的权
|
||||||
|
// public ENode nextEdge; // 指向下一条弧的指针
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// 邻接表中表的顶点
|
||||||
|
// /// </summary>
|
||||||
|
// public class VNode
|
||||||
|
// {
|
||||||
|
// public string data; // 顶点信息
|
||||||
|
// public ENode firstEdge; // 指向第一条依附该顶点的弧
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// 边的结构体
|
||||||
|
// /// </summary>
|
||||||
|
// public class EData
|
||||||
|
// {
|
||||||
|
// public string start; // 边的起点
|
||||||
|
// public string end; // 边的终点
|
||||||
|
// public int weight; // 边的权重
|
||||||
|
|
||||||
|
// public EData(string start, string end, int weight)
|
||||||
|
// {
|
||||||
|
// this.start = start;
|
||||||
|
// this.end = end;
|
||||||
|
// this.weight = weight;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
69
WarehouseMgr/Tnb.WarehouseMgr/Dp.cs
Normal file
69
WarehouseMgr/Tnb.WarehouseMgr/Dp.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JNPF.Templates;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using Spire.Doc;
|
||||||
|
using Tnb.WarehouseMgr.Entities;
|
||||||
|
|
||||||
|
namespace Tnb.WarehouseMgr
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 动态规划类
|
||||||
|
/// </summary>
|
||||||
|
public class Dp
|
||||||
|
{
|
||||||
|
private const int Max = int.MaxValue;
|
||||||
|
private int Min = int.MaxValue;
|
||||||
|
private int Deep = 0;
|
||||||
|
/// <summary>
|
||||||
|
/// 动态规划函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roads"></param>
|
||||||
|
/// <param name="sPointId"></param>
|
||||||
|
/// <param name="ePointId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public void DpFunc(List<WmsRoad> roads, List<WmsRoad> subRoads, List<string> pointIds, Dictionary<string, bool> isVisited, string sPointId, string ePointId)
|
||||||
|
{
|
||||||
|
Deep++;
|
||||||
|
|
||||||
|
var sRoads = roads.FindAll(x => x.startpoint_id == sPointId).ToList();
|
||||||
|
var sRoads_EPointIds = sRoads.Select(x => x.endpoint_id).ToList();
|
||||||
|
|
||||||
|
if (!isVisited[sPointId])
|
||||||
|
{
|
||||||
|
Console.WriteLine($"code={roads.Find(x => x.startpoint_id == sPointId).startpoint_code}");
|
||||||
|
pointIds.Add(sPointId);
|
||||||
|
}
|
||||||
|
var eSubRoads = sRoads.FindAll(x => x.endpoint_id == ePointId);
|
||||||
|
if (eSubRoads?.Count > 0)
|
||||||
|
{
|
||||||
|
pointIds.Add(ePointId);
|
||||||
|
Console.WriteLine($"Deep={Deep}");
|
||||||
|
foreach (var kvp in isVisited)
|
||||||
|
{
|
||||||
|
isVisited[kvp.Key] = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subRoads = roads.FindAll(x => sRoads_EPointIds.Contains(x.startpoint_id)).ToList();
|
||||||
|
if (subRoads?.Count > 0 && !isVisited[sPointId])
|
||||||
|
{
|
||||||
|
isVisited[sPointId] = true;
|
||||||
|
for (int i = 0; i < subRoads.Count; i++)
|
||||||
|
{
|
||||||
|
var sIdx = subRoads[i].startpoint_id;
|
||||||
|
if (!isVisited[sIdx])
|
||||||
|
{
|
||||||
|
DpFunc(roads, subRoads, pointIds, isVisited, sIdx, ePointId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,6 @@ using Tnb.Common.Utils;
|
|||||||
using Tnb.WarehouseMgr.Entities;
|
using Tnb.WarehouseMgr.Entities;
|
||||||
using Tnb.WarehouseMgr.Entities.Consts;
|
using Tnb.WarehouseMgr.Entities.Consts;
|
||||||
using Tnb.WarehouseMgr.Entities.Dto;
|
using Tnb.WarehouseMgr.Entities.Dto;
|
||||||
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
|
|
||||||
using Tnb.WarehouseMgr.Entities.Enums;
|
using Tnb.WarehouseMgr.Entities.Enums;
|
||||||
using Tnb.WarehouseMgr.Interfaces;
|
using Tnb.WarehouseMgr.Interfaces;
|
||||||
|
|
||||||
@@ -224,6 +223,31 @@ namespace Tnb.WarehouseMgr
|
|||||||
var row = await _db.Insertable(preTasks).ExecuteCommandAsync();
|
var row = await _db.Insertable(preTasks).ExecuteCommandAsync();
|
||||||
return row > 0;
|
return row > 0;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 生成预任务后续处理
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[NonAction]
|
||||||
|
public async Task GenTaskHandleAfter(GenPreTaskUpInput input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _db.Ado.BeginTranAsync();
|
||||||
|
//根据载具移入Id,回更单据状态
|
||||||
|
await _db.Updateable<WmsMoveInstock>().SetColumns(it => new WmsMoveInstock { status = WmsWareHouseConst.BILLSTATUS_ON_ID }).Where(it => it.id == input.PreTaskId).ExecuteCommandAsync();
|
||||||
|
//根据生成的预任务,插入预任务操作记录
|
||||||
|
await _db.Insertable(input.PreTaskRecords).ExecuteCommandAsync();
|
||||||
|
//根据载具ID,更新是否锁定和赋值起始库位
|
||||||
|
await _db.Updateable<WmsCarryH>().SetColumns(it => new WmsCarryH { is_lock = 1, location_id = input.CarryStartLocationId, location_code = input.CarryStartLocationCode }).Where(it => it.id == input.CarryId).ExecuteCommandAsync();
|
||||||
|
//根据所有库位更新库位的锁定状态为“锁定”
|
||||||
|
await _db.Updateable<BasLocation>().SetColumns(it => new BasLocation { is_lock = 1 }).Where(it => input.LocationIds.Contains(it.id)).ExecuteCommandAsync();
|
||||||
|
await _db.Ado.CommitTranAsync();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _db.Ado.RollbackTranAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 路径算法
|
/// 路径算法
|
||||||
@@ -243,34 +267,84 @@ namespace Tnb.WarehouseMgr
|
|||||||
private async Task<List<WmsPointH>> LocPathCalcAlgorithms(string pStartId, string pEndId, List<WmsRoad> roads)
|
private async Task<List<WmsPointH>> LocPathCalcAlgorithms(string pStartId, string pEndId, List<WmsRoad> roads)
|
||||||
{
|
{
|
||||||
var points = await _db.Queryable<WmsPointH>().ToListAsync();
|
var points = await _db.Queryable<WmsPointH>().ToListAsync();
|
||||||
var startObj = points.Find(x => x.id == pStartId);
|
List<WmsPointH> results = new();
|
||||||
var endObj = points.Find(x => x.id == pEndId);
|
List<WmsRoad> subRoads = new();
|
||||||
var sIndex = points.IndexOf(startObj);
|
Dictionary<string, bool> isVisited = roads.Select(x => x.startpoint_id).Distinct().ToDictionary(x => x, x => false);
|
||||||
var eIndex = points.IndexOf(endObj);
|
|
||||||
var vexs = points.Select(p => p.id).ToArray();
|
List<string> pointIds = new();
|
||||||
EData[] edges = new EData[roads.Count];
|
List<string> codes = new();
|
||||||
for (int i = 0; i < edges.Length; i++)
|
Dp dp = new();
|
||||||
|
|
||||||
|
dp.DpFunc(roads, subRoads, pointIds, isVisited, pStartId, pEndId);
|
||||||
|
foreach (var pid in pointIds)
|
||||||
{
|
{
|
||||||
var start = roads[i].startpoint_id;
|
var point = points.Find(x => x.id == pid);
|
||||||
var end = roads[i].endpoint_id;
|
results.Add(point);
|
||||||
var weight = roads[i].distance;
|
|
||||||
edges[i] = new EData(start, end, weight);
|
|
||||||
}
|
}
|
||||||
Dijkstra<WmsPointH> pG = new(vexs, edges);
|
|
||||||
int[] prev = new int[pG.mVexs.Length];
|
#region dijkstra
|
||||||
int[] dist = new int[pG.mVexs.Length];
|
//var points = await _db.Queryable<WmsPointH>().ToListAsync();
|
||||||
List<WmsPointH> vertexs = new() { startObj };
|
//var startObj = points.Find(x => x.id == pStartId);
|
||||||
pG.CalcDijkstra(sIndex, prev, dist);
|
//var endObj = points.Find(x => x.id == pEndId);
|
||||||
var pointIds = points.Select(p => p.id).ToList();
|
//var sIndex = points.IndexOf(startObj);
|
||||||
List<string> result = new();
|
//var eIndex = points.IndexOf(endObj);
|
||||||
GetPoints(pointIds, prev, result, eIndex);
|
//if (eIndex < sIndex)
|
||||||
var shortestPathPoints = points.FindAll(x => result.Contains(x.id));
|
//{
|
||||||
shortestPathPoints.Add(points.Find(x => x.id == pStartId));
|
// var tempIndex = sIndex;
|
||||||
List<WmsPointH> results = new() { startObj };
|
// sIndex = eIndex;
|
||||||
var isVisited = shortestPathPoints.ToDictionary(x => x.id, x => false);
|
// eIndex = tempIndex;
|
||||||
isVisited[pStartId] = true;
|
// var temp = points[sIndex];
|
||||||
MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
|
// points[sIndex] = points[eIndex];
|
||||||
results.Add(endObj);
|
// points[eIndex] = temp;
|
||||||
|
//}
|
||||||
|
|
||||||
|
////MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
|
||||||
|
|
||||||
|
|
||||||
|
//var vexs = points.Select(p => p.id).ToArray();
|
||||||
|
//EData[] edges = new EData[roads.Count];
|
||||||
|
//for (int i = 0; i < edges.Length; i++)
|
||||||
|
//{
|
||||||
|
// var start = roads[i].startpoint_id;
|
||||||
|
// var end = roads[i].endpoint_id;
|
||||||
|
// var weight = roads[i].distance;
|
||||||
|
// edges[i] = new EData(start, end, weight);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//Dijkstra pG = new(vexs, edges);
|
||||||
|
//int[] prev = new int[pG.mVexs.Length];
|
||||||
|
//int[] dist = new int[pG.mVexs.Length];
|
||||||
|
//List<WmsPointH> vertexs = new() { startObj };
|
||||||
|
//pG.CalcDijkstra(sIndex, prev, dist);
|
||||||
|
//var pointIds = points.Select(p => p.id).ToList();
|
||||||
|
//List<string> result = new();
|
||||||
|
//GetPoints(pointIds, prev, result, eIndex);
|
||||||
|
|
||||||
|
//var items =new List<string>();
|
||||||
|
//foreach (var item in prev.Where(x=>x!=0))
|
||||||
|
//{
|
||||||
|
// if (points[item] != null)
|
||||||
|
// {
|
||||||
|
// items.Add(points[item].point_code);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//var @strings = string.Join(",", items.OrderBy(o=>o));
|
||||||
|
|
||||||
|
//var shortestPathPoints = points.FindAll(x => result.Contains(x.id));
|
||||||
|
//if (shortestPathPoints.IndexOf(startObj) < 0)
|
||||||
|
//{
|
||||||
|
// shortestPathPoints.Add(startObj);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//List<WmsPointH> results = new() { startObj };
|
||||||
|
//var isVisited = shortestPathPoints.ToDictionary(x => x.id, x => false);
|
||||||
|
//var isVisited2 = shortestPathPoints.ToDictionary(x => x.id, x => false);
|
||||||
|
//isVisited[pStartId] = true;
|
||||||
|
|
||||||
|
//MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId);
|
||||||
|
//results.Add(endObj);
|
||||||
|
#endregion
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -319,18 +393,18 @@ namespace Tnb.WarehouseMgr
|
|||||||
var isOk = false;
|
var isOk = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//await _db.Ado.BeginTranAsync();
|
await _db.Ado.BeginTranAsync();
|
||||||
isOk = await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
|
isOk = await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
|
||||||
if (entities?.Count > 0)
|
if (entities?.Count > 0)
|
||||||
{
|
{
|
||||||
var row = await _db.Storageable(entities).ExecuteCommandAsync();
|
var row = await _db.Storageable(entities).ExecuteCommandAsync();
|
||||||
isOk = row > 0;
|
isOk = row > 0;
|
||||||
}
|
}
|
||||||
//await _db.Ado.CommitTranAsync();
|
await _db.Ado.CommitTranAsync();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
//await _db.Ado.RollbackTranAsync();
|
await _db.Ado.RollbackTranAsync();
|
||||||
}
|
}
|
||||||
return isOk;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,22 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using JNPF.Common.Core.Manager;
|
||||||
using JNPF.Common.Dtos.VisualDev;
|
using JNPF.Common.Dtos.VisualDev;
|
||||||
|
using JNPF.Common.Enums;
|
||||||
|
using JNPF.Common.Extension;
|
||||||
|
using JNPF.Common.Security;
|
||||||
|
using JNPF.FriendlyException;
|
||||||
|
using JNPF.Systems.Interfaces.System;
|
||||||
using JNPF.VisualDev;
|
using JNPF.VisualDev;
|
||||||
using JNPF.VisualDev.Entitys;
|
using JNPF.VisualDev.Entitys;
|
||||||
using JNPF.VisualDev.Interfaces;
|
using JNPF.VisualDev.Interfaces;
|
||||||
|
using Mapster;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Tnb.BasicData.Entities;
|
using Tnb.BasicData.Entities;
|
||||||
using Tnb.WarehouseMgr.Entities;
|
using Tnb.WarehouseMgr.Entities;
|
||||||
|
using Tnb.WarehouseMgr.Entities.Consts;
|
||||||
using Tnb.WarehouseMgr.Entities.Dto;
|
using Tnb.WarehouseMgr.Entities.Dto;
|
||||||
using Tnb.WarehouseMgr.Interfaces;
|
using Tnb.WarehouseMgr.Interfaces;
|
||||||
|
|
||||||
@@ -27,46 +35,106 @@ namespace Tnb.WarehouseMgr
|
|||||||
private readonly IRunService _runService;
|
private readonly IRunService _runService;
|
||||||
private readonly IVisualDevService _visualDevService;
|
private readonly IVisualDevService _visualDevService;
|
||||||
private readonly IWareHouseService _wareHouseService;
|
private readonly IWareHouseService _wareHouseService;
|
||||||
|
private readonly IBillRullService _billRullService;
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
public WmsCarryMoveInStockService(
|
public WmsCarryMoveInStockService(
|
||||||
ISqlSugarRepository<WmsCarryH> repository,
|
ISqlSugarRepository<WmsCarryH> repository,
|
||||||
IRunService runService,
|
IRunService runService,
|
||||||
IVisualDevService visualDevService,
|
IVisualDevService visualDevService,
|
||||||
IWareHouseService wareHouseService)
|
IWareHouseService wareHouseService,
|
||||||
|
IUserManager userManager,
|
||||||
|
IBillRullService billRullService)
|
||||||
{
|
{
|
||||||
_db = repository.AsSugarClient();
|
_db = repository.AsSugarClient();
|
||||||
_runService = runService;
|
_runService = runService;
|
||||||
_visualDevService = visualDevService;
|
_visualDevService = visualDevService;
|
||||||
_wareHouseService = wareHouseService;
|
_wareHouseService = wareHouseService;
|
||||||
|
_userManager = userManager;
|
||||||
|
_billRullService = billRullService;
|
||||||
OverideFuncs.CreateAsync = CarryMoveIn;
|
OverideFuncs.CreateAsync = CarryMoveIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<dynamic> CarryMoveIn(VisualDevModelDataCrInput input)
|
private async Task<dynamic> CarryMoveIn(VisualDevModelDataCrInput input)
|
||||||
{
|
{
|
||||||
VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleId, true);
|
|
||||||
await _runService.Create(templateEntity, input);
|
try
|
||||||
//入库取终点
|
|
||||||
var inStockStrategyInput = new InStockStrategyQuery { warehouse_id = input.data[nameof(InStockStrategyQuery.warehouse_id)].ToString(), Size = 1 };
|
|
||||||
var endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput);
|
|
||||||
WmsPointH sPoint = null;
|
|
||||||
WmsPointH ePoint = null;
|
|
||||||
if (input.data.ContainsKey(nameof(WmsPointH.location_id)))
|
|
||||||
{
|
{
|
||||||
sPoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == input.data[nameof(WmsPointH.location_id)].ToString());
|
await _db.Ado.BeginTranAsync();
|
||||||
|
|
||||||
|
VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleId, true);
|
||||||
|
await _runService.Create(templateEntity, input);
|
||||||
|
//入库取终点
|
||||||
|
var inStockStrategyInput = new InStockStrategyQuery { warehouse_id = input.data[nameof(InStockStrategyQuery.warehouse_id)].ToString(), Size = 1 };
|
||||||
|
var endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput);
|
||||||
|
WmsPointH sPoint = null;
|
||||||
|
WmsPointH ePoint = null;
|
||||||
|
if (input.data.ContainsKey(nameof(WmsPointH.location_id)))
|
||||||
|
{
|
||||||
|
sPoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == input.data[nameof(WmsPointH.location_id)].ToString());
|
||||||
|
}
|
||||||
|
if (endLocations?.Count > 0)
|
||||||
|
{
|
||||||
|
ePoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == endLocations[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sPoint != null && ePoint != null)
|
||||||
|
{
|
||||||
|
var points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id);
|
||||||
|
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
|
||||||
|
if (points?.Count > 0)
|
||||||
|
{
|
||||||
|
if (points.Count <= 2) throw new AppFriendlyException("该路径不存在", 500);
|
||||||
|
var preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it =>
|
||||||
|
{
|
||||||
|
var sPoint = it.FirstOrDefault();
|
||||||
|
var ePoint = it.LastOrDefault();
|
||||||
|
|
||||||
|
WmsPretaskH preTask = new();
|
||||||
|
preTask.org_id = _userManager.User.OrganizeId;
|
||||||
|
preTask.startlocation_id = sPoint?.location_id;
|
||||||
|
preTask.startlocation_code = sPoint?.location_code;
|
||||||
|
preTask.endlocation_id = ePoint?.location_id;
|
||||||
|
preTask.endlocation_code = ePoint?.location_code;
|
||||||
|
preTask.start_floor = sPoint?.floor.ToString();
|
||||||
|
preTask.end_floor = ePoint?.floor.ToString();
|
||||||
|
preTask.bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult();
|
||||||
|
preTask.status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID;
|
||||||
|
preTask.biz_type = WmsWareHouseConst.BIZTYPE_MOVEIN_ID;
|
||||||
|
preTask.carry_id = input.data[nameof(preTask.carry_id)]?.ToString()!;
|
||||||
|
preTask.carry_code = input.data[nameof(preTask.carry_code)]?.ToString()!;
|
||||||
|
preTask.area_id = sPoint?.area_id;
|
||||||
|
preTask.area_code = it.Key;
|
||||||
|
preTask.require_id = input.data["ReturnIdentity"].ToString();
|
||||||
|
preTask.require_code = input.data[nameof(preTask.bill_code)]?.ToString()!;
|
||||||
|
preTask.create_id = _userManager.UserId;
|
||||||
|
preTask.create_time = DateTime.Now;
|
||||||
|
return preTask;
|
||||||
|
}).ToList();
|
||||||
|
var isOk = await _wareHouseService.GenPreTask(preTasks);
|
||||||
|
if (isOk)
|
||||||
|
{
|
||||||
|
var preTaskUpInput = new GenPreTaskUpInput();
|
||||||
|
preTaskUpInput.PreTaskId = input.data["ReturnIdentity"].ToString();
|
||||||
|
preTaskUpInput.CarryId = input.data[nameof(WmsCarryD.carry_id)]?.ToString()!;
|
||||||
|
preTaskUpInput.CarryStartLocationId = points.FirstOrDefault().location_id;
|
||||||
|
preTaskUpInput.CarryStartLocationCode = points.FirstOrDefault().location_code;
|
||||||
|
preTaskUpInput.LocationIds = points.Select(x => x.id).ToList();
|
||||||
|
preTaskUpInput.PreTaskRecords = preTasks.Adapt<List<WmsHandleH>>();
|
||||||
|
preTaskUpInput.PreTaskRecords.ForEach(x => x.id = SnowflakeIdHelper.NextId());
|
||||||
|
await _wareHouseService.GenTaskHandleAfter(preTaskUpInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
await _db.Ado.CommitTranAsync();
|
||||||
}
|
}
|
||||||
if (endLocations?.Count > 0)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ePoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == endLocations[0].id);
|
await _db.Ado.RollbackTranAsync();
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
if (sPoint != null && ePoint != null)
|
return Task.FromResult(true);
|
||||||
{
|
|
||||||
var points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id);
|
|
||||||
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
|
|
||||||
//根据载具移入Id,回更单据状态
|
|
||||||
//根据生成的预任务,插入预任务操作记录
|
|
||||||
//根据载具ID,更新是否锁定和赋值起始库位
|
|
||||||
//根据所有库位更新库位的锁定状态为“锁定”
|
|
||||||
}
|
|
||||||
return Task.FromResult(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using SqlSugar;
|
|||||||
using Tnb.Common.Utils;
|
using Tnb.Common.Utils;
|
||||||
using Tnb.WarehouseMgr.Entities;
|
using Tnb.WarehouseMgr.Entities;
|
||||||
using Tnb.WarehouseMgr.Entities.Consts;
|
using Tnb.WarehouseMgr.Entities.Consts;
|
||||||
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
|
using Tnb.WarehouseMgr.Entities.Dto;
|
||||||
using Tnb.WarehouseMgr.Entities.Enums;
|
using Tnb.WarehouseMgr.Entities.Enums;
|
||||||
using Tnb.WarehouseMgr.Interfaces;
|
using Tnb.WarehouseMgr.Interfaces;
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,9 @@ namespace Tnb.WarehouseMgr
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 路径管理业务类
|
/// 路径管理业务类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiDescriptionSettings(Tag = ModuleConsts.Tag, Area = ModuleConsts.Area, Order = 700)]
|
|
||||||
[Route("api/[area]/[controller]/[action]")]
|
|
||||||
[OverideVisualDev(ModuleId)]
|
[OverideVisualDev(ModuleId)]
|
||||||
|
|
||||||
public class WmsRouteMgrService : IOverideVisualDevService, IWmsRouteMgrService, IDynamicApiController, ITransient
|
public class WmsRouteMgrService : BaseWareHouseService, IWmsRouteMgrService
|
||||||
{
|
{
|
||||||
private const string ModuleId = "26100621140773";
|
private const string ModuleId = "26100621140773";
|
||||||
private readonly ISqlSugarClient _db;
|
private readonly ISqlSugarClient _db;
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ namespace Tnb.Common.Utils
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 迪杰斯特拉(最短路径算法)
|
/// 迪杰斯特拉(最短路径算法)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Dijkstra<T> where T : BaseEntity<string>, new()
|
public class Dijkstra
|
||||||
{
|
{
|
||||||
public static int MAX = int.MaxValue;
|
public static int MAX = int.MaxValue;
|
||||||
|
|
||||||
public int mEdgNum; // 边的数量
|
public int mEdgNum; // 边的数量
|
||||||
public VNode[] mVexs; // 顶点数组
|
public VNode[] mVexs; // 顶点数组
|
||||||
|
private EData[] edges; //边的数组
|
||||||
/*
|
/*
|
||||||
* 创建图
|
* 创建图
|
||||||
*
|
*
|
||||||
@@ -27,7 +27,7 @@ namespace Tnb.Common.Utils
|
|||||||
*/
|
*/
|
||||||
public Dijkstra(string[] vexs, EData[] edges)
|
public Dijkstra(string[] vexs, EData[] edges)
|
||||||
{
|
{
|
||||||
|
this.edges = edges;
|
||||||
// 初始化"顶点数"和"边数"
|
// 初始化"顶点数"和"边数"
|
||||||
int vlen = vexs.Length;
|
int vlen = vexs.Length;
|
||||||
int elen = edges.Length;
|
int elen = edges.Length;
|
||||||
@@ -142,7 +142,7 @@ namespace Tnb.Common.Utils
|
|||||||
// 对"起点D"自身进行初始化
|
// 对"起点D"自身进行初始化
|
||||||
flag[vs] = true;
|
flag[vs] = true;
|
||||||
dist[vs] = 0;
|
dist[vs] = 0;
|
||||||
|
HashSet<int> set = new();
|
||||||
// 遍历mVexs.Length-1次;每次找出一个顶点的最短路径。
|
// 遍历mVexs.Length-1次;每次找出一个顶点的最短路径。
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int i = 1; i < mVexs.Length; i++)
|
for (int i = 1; i < mVexs.Length; i++)
|
||||||
@@ -154,9 +154,12 @@ namespace Tnb.Common.Utils
|
|||||||
{
|
{
|
||||||
if (flag[j] == false && dist[j] < min)
|
if (flag[j] == false && dist[j] < min)
|
||||||
{
|
{
|
||||||
|
|
||||||
min = dist[j];
|
min = dist[j];
|
||||||
k = j;
|
k = j;
|
||||||
|
set.Add(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 标记"顶点k"为已经获取到最短路径
|
// 标记"顶点k"为已经获取到最短路径
|
||||||
flag[k] = true;
|
flag[k] = true;
|
||||||
@@ -173,14 +176,6 @@ namespace Tnb.Common.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打印dijkstra最短路径的结果
|
|
||||||
//Console.WriteLine("dijkstra({0}): \n", mVexs[vs].data);
|
|
||||||
//for (int i = 0; i < mVexs.Length; i++)
|
|
||||||
//{
|
|
||||||
// Console.WriteLine("shortest({0}, {1})={2}\n", mVexs[vs].data, mVexs[i].data, dist[i]);
|
|
||||||
//}
|
|
||||||
//return vertexs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +184,17 @@ namespace Tnb.Common.Utils
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ENode
|
public class ENode
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 该边所指向的顶点的位置
|
||||||
|
/// </summary>
|
||||||
public int ivex; // 该边所指向的顶点的位置
|
public int ivex; // 该边所指向的顶点的位置
|
||||||
|
/// <summary>
|
||||||
|
/// 该边的权
|
||||||
|
/// </summary>
|
||||||
public int weight; // 该边的权
|
public int weight; // 该边的权
|
||||||
|
/// <summary>
|
||||||
|
/// 指向下一条弧的指针
|
||||||
|
/// </summary>
|
||||||
public ENode nextEdge; // 指向下一条弧的指针
|
public ENode nextEdge; // 指向下一条弧的指针
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user