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 { /// /// 策略实体 指可抽象出来的策略 /// public class AlgorTacticsCommon { #region 设备均衡 确定任务数最少对应的巷道下的货位列表 /// /// 设备均衡策略 /// /// AMS设备数据 /// 可用的货位列表 /// 返回使用的设备号 /// 计算后可用的货位列表 public List EquipmentBalance(List lstDevice, List lstTrueLocation, out string deviceCode) { //计算后可用的货位列表 List location_roadray = new List(); 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 巷道均衡 返回巷道对应的货位列表 /// /// 巷道均衡策略 /// /// 可用的货位信息数据 /// 计算后返回的实体 public List RoadWayBalance(List lstTrueLocation) { //指定计算后返回的实体 List location_roadray = new List(); //按照巷道分组 并获得巷道中可用货位的数据 //之后进行倒叙 找到可用货位最多的巷道 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 就近原则 只返回一个货位实体 /// /// 就近原则 /// /// 一个巷道内的所有货位数据 /// public List NearbyBalance(List lstTrueLocation) { List lstNearLocation = new List(); 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 #region 就近原则 只返回一个货位实体 /// /// 就近原则 /// /// 一个巷道内的所有货位数据 /// public List NearbyBalanceRow(List lstTrueLocation) { List lstNearLocation = new List(); 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 货位平均使用原则 只返回一个货位实体 /// /// 货位平均使用原则 /// /// 一个巷道内的所有货位数据 /// public AutoBomLocationAbbreEntity AverageBalance(List 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 宇寿入库 先进后出 /// /// 就近原则 /// /// 一个巷道内的所有货位数据 /// public List FirstInLastOut(List lstTrueLocation, List lstAllLocation, List lstLockLItem, List lstStrate) { List location_rowray = new List(); List lstResultLocation = new List(); List lstFalseLocation = new List(); List lstEmptyCol = new List(); //获得库区中含有空货位的列 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 隆基入库 先进后出 /// /// 就近原则 /// /// 一个巷道内的所有货位数据 /// public List FirstInLastOutLj(List lstTrueLocation, List lstAllLocation, List lstLockLItem, List lstStrate) { List location_rowray = new List(); List lstResultLocation = new List(); List lstFalseLocation = new List(); List lstEmptyCol = new List(); //获得库区中含有空货位的列 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 设备均衡 确定任务数最少对应的巷道下的货位列表 /// /// 设备均衡策略 /// /// AMS设备数据 /// 可用的货位列表 /// 返回使用的设备号 /// 计算后可用的货位列表 public List EquipmentBalanceOut(List lstDevice, List lstTrueLocation, out string deviceCode) { //计算后可用的货位列表 List location_roadray = new List(); 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 巷道均衡 返回巷道对应的货位列表 /// /// 巷道均衡策略 /// /// 可用的货位信息数据 /// 计算后返回的实体 public List RoadWayBalanceOut(List lstTrueLocation) { //指定计算后返回的实体 List location_roadray = new List(); //按照巷道分组 并获得巷道中可用货位的数据 //之后进行倒叙 找到可用货位最多的巷道 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 就近原则 只返回一个货位实体 /// /// 就近原则 /// /// 一个巷道内的所有货位数据 /// public List NearbyBalanceOut(List lstTrueLocation) { List lstNearLocation = new List(); 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 } }