using HH.WMS.Common.Algorithm;
|
using HH.WMS.Entitys.Algorithm;
|
using HH.WMS.Entitys.Basic;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace HH.WMS.Common.Algorithm
|
{
|
/// <summary>
|
/// 策略实体 指可抽象出来的策略
|
/// </summary>
|
public class AlgorTacticsCommon
|
{
|
#region 设备均衡 确定任务数最少对应的巷道下的货位列表
|
/// <summary>
|
/// 设备均衡策略
|
/// </summary>
|
/// <param name="lstDevice">AMS设备数据</param>
|
/// <param name="lstTrueLocation">可用的货位列表</param>
|
/// <param name="deviceCode">返回使用的设备号</param>
|
/// <returns>计算后可用的货位列表</returns>
|
public List<AutoBomLocationAbbreEntity> EquipmentBalance(List<Device> lstDevice, List<AutoBomLocationAbbreEntity> lstTrueLocation, out string deviceCode)
|
{
|
//计算后可用的货位列表
|
List<AutoBomLocationAbbreEntity> location_roadray = new List<AutoBomLocationAbbreEntity>();
|
if (lstDevice == null || lstDevice.Count == 0)
|
{
|
location_roadray = lstTrueLocation;
|
deviceCode = "";
|
}
|
else
|
{
|
//按照任务数量顺序排列
|
lstDevice = lstDevice.OrderBy(o => o.taskNum).ToList();
|
|
//设备号
|
string device = string.Empty;
|
|
foreach (Device model in lstDevice)
|
{
|
string[] roadRay = model.roadWay.Split(',');
|
//获得当前设备所属巷道下的所有货位
|
location_roadray = lstTrueLocation.Where(o => roadRay.Contains(o.CN_S_ROADWAY)).ToList();
|
if (location_roadray != null && location_roadray.Count > 0)
|
{
|
device = model.deviceCode;
|
break;
|
}
|
}
|
deviceCode = device;
|
}
|
return location_roadray;
|
}
|
#endregion
|
|
#region 巷道均衡 返回巷道对应的货位列表
|
/// <summary>
|
/// 巷道均衡策略
|
/// </summary>
|
/// <param name="lstTrueLocation">可用的货位信息数据</param>
|
/// <returns>计算后返回的实体</returns>
|
public List<AutoBomLocationAbbreEntity> RoadWayBalance(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
//指定计算后返回的实体
|
List<AutoBomLocationAbbreEntity> location_roadray = new List<AutoBomLocationAbbreEntity>();
|
|
//按照巷道分组 并获得巷道中可用货位的数据
|
//之后进行倒叙 找到可用货位最多的巷道
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROADWAY).Select(g => (new
|
{
|
roadWay = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty);
|
Log.AlgorInfo("InAssign-FlatAreaGetLocation", "RoadWayBalance后数据:" + JsonConvert.SerializeObject(v));
|
|
//倒叙排列后的巷道 循环
|
foreach (var item in v)
|
{
|
//取得巷道列表中可用货位最多的巷道 并获取巷道中所有货位
|
location_roadray = lstTrueLocation.Where(o => o.CN_S_ROADWAY == item.roadWay).ToList();
|
|
if (location_roadray != null && location_roadray.Count > 0)
|
{
|
break;
|
}
|
}
|
return location_roadray;
|
}
|
#endregion
|
#region 排均衡 返回巷道对应的货位列表
|
/// <summary>
|
/// 巷道均衡策略
|
/// </summary>
|
/// <param name="lstTrueLocation">可用的货位信息数据</param>
|
/// <returns>计算后返回的实体</returns>
|
public List<AutoBomLocationAbbreEntity> RowWayBalance(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
//指定计算后返回的实体
|
List<AutoBomLocationAbbreEntity> location_roadray = new List<AutoBomLocationAbbreEntity>();
|
|
//按照巷道分组 并获得巷道中可用货位的数据
|
//之后进行倒叙 找到可用货位最多的巷道
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROW).Select(g => (new
|
{
|
row = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty);
|
|
//倒叙排列后的巷道 循环
|
foreach (var item in v)
|
{
|
//取得巷道列表中可用货位最多的巷道 并获取巷道中所有货位
|
location_roadray = lstTrueLocation.Where(o => o.CN_S_ROW == item.row).ToList();
|
|
if (location_roadray != null && location_roadray.Count > 0)
|
{
|
break;
|
}
|
}
|
return location_roadray;
|
}
|
#endregion
|
#region 就近原则 只返回一个货位实体
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<AutoBomLocationAbbreEntity> NearbyBalance(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
List<AutoBomLocationAbbreEntity> lstNearLocation = new List<AutoBomLocationAbbreEntity>();
|
if (lstTrueLocation == null || lstTrueLocation.Count == 0)
|
{
|
return lstNearLocation;
|
}
|
//先判断是否存在多个巷道,如果存在就近选择一个巷道
|
var location_roadray = lstTrueLocation.OrderBy(o => o.CN_S_ROADWAY).Select(o => o.CN_S_ROADWAY).Distinct().ToList();
|
if(location_roadray!=null && location_roadray.Count >1 )
|
{
|
lstTrueLocation = lstTrueLocation.Where(o => o.CN_S_ROADWAY == location_roadray[0].ToString()).ToList();
|
}
|
//按照排分组 并获得排中可用货位的数据
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROW).Select(g => (new
|
{
|
row = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty).ThenBy(o => o.row).ToList();//按照货位可用数量进行倒叙,找到可用货位最多的排
|
//如果每一排中可用货位相同,则在顺序排列,取最近的排
|
Log.AlgorInfo("InAssign-FlatAreaGetLocation", "按照排分组后数据:" + JsonConvert.SerializeObject(v));
|
//找到排空货位最多的排
|
var v_row = lstTrueLocation.Where(o => o.CN_S_ROW == v[0].row).ToList();
|
|
//找到最小的列
|
var v_col = v_row.OrderBy(o => o.CN_S_COL.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_COL)).ToList();
|
var min_col = v_col[0].CN_S_COL;
|
|
//找到一个排下最小的列对应的所有货位
|
var v_f = v_row.Where(o => o.CN_S_COL == min_col).OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstNearLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstNearLocation;
|
}
|
#endregion
|
#region 就远原则 只返回一个货位实体
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<AutoBomLocationAbbreEntity> FarbyBalance(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
List<AutoBomLocationAbbreEntity> lstNearLocation = new List<AutoBomLocationAbbreEntity>();
|
if (lstTrueLocation == null || lstTrueLocation.Count == 0)
|
{
|
return lstNearLocation;
|
}
|
//先判断是否存在多个巷道,如果存在就近选择一个巷道
|
var location_roadray = lstTrueLocation.OrderBy(o => o.CN_S_ROADWAY).Select(o => o.CN_S_ROADWAY).Distinct().ToList();
|
if (location_roadray != null && location_roadray.Count > 1)
|
{
|
lstTrueLocation = lstTrueLocation.Where(o => o.CN_S_ROADWAY == location_roadray[0].ToString()).ToList();
|
}
|
//按照排分组 并获得排中可用货位的数据
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROW).Select(g => (new
|
{
|
row = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty).ThenBy(o => o.row).ToList();//按照货位可用数量进行倒叙,找到可用货位最多的排
|
//如果每一排中可用货位相同,则在顺序排列,取最近的排
|
Log.AlgorInfo("InAssign-FlatAreaGetLocation", "按照排分组后数据:" + JsonConvert.SerializeObject(v));
|
//找到排空货位最多的排
|
var v_row = lstTrueLocation.Where(o => o.CN_S_ROW == v[0].row).ToList();
|
|
//找到最小的列
|
var v_col = v_row.OrderByDescending(o => o.CN_S_COL.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_COL)).ToList();
|
var max_col = v_col[0].CN_S_COL;
|
|
//找到一个排下最小的列对应的所有货位
|
var v_f = v_row.Where(o => o.CN_S_COL == max_col).OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstNearLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstNearLocation;
|
}
|
#endregion
|
|
#region 就近原则 只返回一个货位实体
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<AutoBomLocationAbbreEntity> NearbyBalanceRow(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
List<AutoBomLocationAbbreEntity> lstNearLocation = new List<AutoBomLocationAbbreEntity>();
|
if (lstTrueLocation == null || lstTrueLocation.Count == 0)
|
{
|
return lstNearLocation;
|
}
|
//先判断是否存在多个巷道,如果存在就近选择一个巷道
|
var location_row = lstTrueLocation.OrderBy(o => o.CN_S_ROW).Select(o => o.CN_S_ROW).Distinct().ToList();
|
|
//找到排空货位最多的排
|
var v_row = lstTrueLocation.Where(o => o.CN_S_ROW == location_row[0]).ToList();
|
|
//找到最小的列
|
var v_col = v_row.OrderBy(o => o.CN_S_COL.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_COL)).ToList();
|
var min_col = v_col[0].CN_S_COL;
|
|
//找到一个排下最小的列对应的所有货位
|
var v_f = v_row.Where(o => o.CN_S_COL == min_col).OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstNearLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstNearLocation;
|
}
|
#endregion
|
|
#region 货位平均使用原则 只返回一个货位实体
|
/// <summary>
|
/// 货位平均使用原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public AutoBomLocationAbbreEntity AverageBalance(List<AutoBomLocationAbbreEntity> lstTrueLocation)
|
{
|
AutoBomLocationAbbreEntity nearLocationEntity = new AutoBomLocationAbbreEntity();
|
if (lstTrueLocation == null || lstTrueLocation.Count == 0)
|
{
|
return nearLocationEntity;
|
}
|
//按照排分组 并获得排中可用货位的数据
|
var v = lstTrueLocation.OrderBy(o => o.CN_N_INTASK_QTY).ToList();//按照货位可用数量进行升序, 找到CN_N_INTASK_QTY最小的货位
|
|
nearLocationEntity = v.FirstOrDefault();
|
return nearLocationEntity;
|
}
|
#endregion
|
|
#region 宇寿入库 先进后出
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<AutoBomLocationAbbreEntity> FirstInLastOut(List<AutoBomLocationAbbreEntity> lstTrueLocation, List<AutoBomLocationAbbreEntity> lstAllLocation, List<AutoBomLocationAbbreEntity> lstLockLItem, List<string> lstStrate)
|
{
|
List<AutoBomLocationAbbreEntity> location_rowray = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstResultLocation = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstFalseLocation = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstEmptyCol = new List<AutoBomLocationAbbreEntity>();
|
|
//获得库区中含有空货位的列
|
if (lstStrate.Contains("InSmallToBig"))
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => o.CN_S_ROW).ThenBy(o => int.Parse(o.CN_S_COL)).Distinct().ToList();
|
}
|
else if (lstStrate.Contains("InBigToSmall"))
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => o.CN_S_ROW).ThenByDescending(o => int.Parse(o.CN_S_COL)).Distinct().ToList();
|
}
|
else
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => o.CN_S_ROW).ThenBy(o => int.Parse(o.CN_S_COL)).Distinct().ToList();
|
}
|
// Log.AlgorInfo("InAssign-FirstInLastOut", "lstEmptyCol数据:" + JsonConvert.SerializeObject(lstEmptyCol));
|
|
|
//查找最小列中的货位
|
location_rowray = lstTrueLocation.Where(o => o.CN_S_COL == lstEmptyCol[0].CN_S_COL && o.CN_S_ROW == lstEmptyCol[0].CN_S_ROW).ToList();
|
|
//找到该列下最小的层
|
var v_f = location_rowray.OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstResultLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstResultLocation;
|
}
|
|
|
#endregion
|
#region 隆基入库 先进后出
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<AutoBomLocationAbbreEntity> FirstInLastOutLj(List<AutoBomLocationAbbreEntity> lstTrueLocation, List<AutoBomLocationAbbreEntity> lstAllLocation, List<AutoBomLocationAbbreEntity> lstLockLItem, List<string> lstStrate)
|
{
|
List<AutoBomLocationAbbreEntity> location_rowray = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstResultLocation = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstFalseLocation = new List<AutoBomLocationAbbreEntity>();
|
List<AutoBomLocationAbbreEntity> lstEmptyCol = new List<AutoBomLocationAbbreEntity>();
|
|
//获得库区中含有空货位的列
|
if (lstStrate.Contains("InSmallToBig"))
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => int.Parse(o.CN_S_COL)).ThenBy(o => o.CN_S_ROW).Distinct().ToList();
|
}
|
else if (lstStrate.Contains("InBigToSmall"))
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => int.Parse(o.CN_S_COL)).ThenByDescending(o => o.CN_S_ROW).Distinct().ToList();
|
}
|
else
|
{
|
lstEmptyCol = lstTrueLocation.OrderBy(o => int.Parse(o.CN_S_COL)).ThenBy(o => o.CN_S_ROW).Distinct().ToList();
|
}
|
Log.AlgorInfo("InAssign-FirstInLastOut", "lstEmptyCol数据:" + JsonConvert.SerializeObject(lstEmptyCol));
|
|
|
//查找最小列中的货位
|
location_rowray = lstTrueLocation.Where(o => o.CN_S_COL == lstEmptyCol[0].CN_S_COL && o.CN_S_ROW == lstEmptyCol[0].CN_S_ROW).ToList();
|
|
//找到该列下最小的层
|
var v_f = location_rowray.OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstResultLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstResultLocation;
|
}
|
|
|
#endregion
|
|
#region 设备均衡 确定任务数最少对应的巷道下的货位列表
|
/// <summary>
|
/// 设备均衡策略
|
/// </summary>
|
/// <param name="lstDevice">AMS设备数据</param>
|
/// <param name="lstTrueLocation">可用的货位列表</param>
|
/// <param name="deviceCode">返回使用的设备号</param>
|
/// <returns>计算后可用的货位列表</returns>
|
public List<outAssignLocation> EquipmentBalanceOut(List<Device> lstDevice, List<outAssignLocation> lstTrueLocation, out string deviceCode)
|
{
|
//计算后可用的货位列表
|
List<outAssignLocation> location_roadray = new List<outAssignLocation>();
|
if (lstDevice == null || lstDevice.Count == 0)
|
{
|
location_roadray = lstTrueLocation;
|
deviceCode = "";
|
}
|
else
|
{
|
//按照任务数量顺序排列
|
lstDevice = lstDevice.OrderBy(o => o.taskNum).ToList();
|
|
//设备号
|
string device = string.Empty;
|
|
foreach (Device model in lstDevice)
|
{
|
string[] roadRay = model.roadWay.Split(',');
|
//获得当前设备所属巷道下的所有货位
|
location_roadray = lstTrueLocation.Where(o => roadRay.Contains(o.CN_S_ROADWAY)).ToList();
|
if (location_roadray != null && location_roadray.Count > 0)
|
{
|
device = model.deviceCode;
|
break;
|
}
|
}
|
deviceCode = device;
|
}
|
return location_roadray;
|
}
|
#endregion
|
|
#region 巷道均衡 返回巷道对应的货位列表
|
/// <summary>
|
/// 巷道均衡策略
|
/// </summary>
|
/// <param name="lstTrueLocation">可用的货位信息数据</param>
|
/// <returns>计算后返回的实体</returns>
|
public List<outAssignLocation> RoadWayBalanceOut(List<outAssignLocation> lstTrueLocation)
|
{
|
//指定计算后返回的实体
|
List<outAssignLocation> location_roadray = new List<outAssignLocation>();
|
|
//按照巷道分组 并获得巷道中可用货位的数据
|
//之后进行倒叙 找到可用货位最多的巷道
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROADWAY).Select(g => (new
|
{
|
roadWay = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty);
|
|
//倒叙排列后的巷道 循环
|
foreach (var item in v)
|
{
|
//取得巷道列表中可用货位最多的巷道 并获取巷道中所有货位
|
location_roadray = lstTrueLocation.Where(o => o.CN_S_ROADWAY == item.roadWay).ToList();
|
|
if (location_roadray != null && location_roadray.Count > 0)
|
{
|
break;
|
}
|
}
|
return location_roadray;
|
}
|
#endregion
|
|
#region 就近原则 只返回一个货位实体
|
/// <summary>
|
/// 就近原则
|
/// </summary>
|
/// <param name="lstTrueLocation">一个巷道内的所有货位数据</param>
|
/// <returns></returns>
|
public List<outAssignLocation> NearbyBalanceOut(List<outAssignLocation> lstTrueLocation)
|
{
|
List<outAssignLocation> lstNearLocation = new List<outAssignLocation>();
|
if (lstTrueLocation == null || lstTrueLocation.Count == 0)
|
{
|
return lstNearLocation;
|
}
|
//先判断是否存在多个巷道,如果存在就近选择一个巷道
|
var location_roadray = lstTrueLocation.OrderBy(o => o.CN_S_ROADWAY).Select(o => o.CN_S_ROADWAY).Distinct().ToList();
|
if (location_roadray != null && location_roadray.Count > 1)
|
{
|
lstTrueLocation = lstTrueLocation.Where(o => o.CN_S_ROADWAY == location_roadray[0].ToString()).ToList();
|
}
|
//按照排分组 并获得排中可用货位的数据
|
var v = lstTrueLocation.GroupBy(x => x.CN_S_ROW).Select(g => (new
|
{
|
row = g.Key,
|
qty = g.Count()
|
})).OrderByDescending(o => o.qty).ThenBy(o => o.row).ToList();//按照货位可用数量进行倒叙,找到可用货位最多的排
|
//如果每一排中可用货位相同,则在顺序排列,取最近的排
|
|
//找到排空货位最多的排
|
var v_row = lstTrueLocation.Where(o => o.CN_S_ROW == v[0].row).ToList();
|
|
//找到最小的列
|
var v_col = v_row.OrderBy(o => o.CN_S_COL.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_COL)).ToList();
|
var min_col = v_col[0].CN_S_COL;
|
|
//找到一个排下最小的列对应的所有货位
|
var v_f = v_row.Where(o => o.CN_S_COL == min_col).OrderBy(o => o.CN_S_FLOOR.Trim().Length == 0 ? 0 : int.Parse(o.CN_S_FLOOR)).ToList();
|
|
//先按照层倒叙取最小的层
|
var min_floor = v_f[0].CN_S_FLOOR;
|
|
//获得层最小的单个
|
lstNearLocation.Add(v_f.Where(o => o.CN_S_FLOOR == min_floor).FirstOrDefault());
|
return lstNearLocation;
|
}
|
#endregion
|
|
|
|
}
|
}
|