718 lines
28 KiB
C#
718 lines
28 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using SimpleLite.RCS;
|
|
using SimpleLite.RCS.CarTypes;
|
|
using SimpleLite.CADTools;
|
|
using SimpleLite.Props;
|
|
using SimpleLite.UI;
|
|
using SimpleCore;
|
|
using SimpleCore.Compiler;
|
|
using SimpleCore.Library;
|
|
using SimpleCore.PropType;
|
|
using SimpleCore.Traffic;
|
|
using StandardScene.InterLock;
|
|
using StandardScene.Model;
|
|
using static StandardScene.Chained.ChainedDeliveryMission;
|
|
|
|
namespace StandardScene
|
|
{
|
|
/// <summary>
|
|
/// 插件本地化设置
|
|
/// </summary>
|
|
public class CustomOperationsBeforeLoading
|
|
{
|
|
public static void Set()
|
|
{
|
|
///死锁提醒
|
|
TrafficControl.OnDeadLock = (loopingCar) =>
|
|
{
|
|
try
|
|
{
|
|
var cars = string.Join(",", loopingCar.Select(p => $"{p.id}"));
|
|
var msg = $"小车:{cars}间发生死锁" +
|
|
$"请及时人工介入处理!!!!";
|
|
MessageBox.Show(msg);
|
|
}
|
|
catch { }
|
|
};
|
|
}
|
|
}
|
|
public class NoReflectionApi : Attribute
|
|
{
|
|
|
|
}
|
|
|
|
public class ReflectionApiWithParameter : Attribute
|
|
{
|
|
public string name;
|
|
public string desc;
|
|
public string Hint;
|
|
}
|
|
|
|
public static class Commons
|
|
{
|
|
public static VehicleStatus GetVehicleStatus(Car car)
|
|
{
|
|
if(car is DummyCar && car.lstatus.Contains("上线"))
|
|
return VehicleStatus.Normal;
|
|
if (car.lstatus.Contains("正常但未初始化")||car.lstatus.Contains("Normal but not initialized"))
|
|
return VehicleStatus.NeedInit;
|
|
if (car.lstatus.Contains("正常") || car.lstatus.Contains("Normal")||car.lstatus.Contains("上线"))
|
|
return VehicleStatus.Normal;
|
|
if (car.lstatus.Contains("自动驾驶系统失联") || car.lstatus.Contains("Autonomous driving system lost"))
|
|
return VehicleStatus.Offline;
|
|
return VehicleStatus.Unknown;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取车辆状态
|
|
/// </summary>
|
|
/// <param name="car">车辆</param>
|
|
/// <param name="key">状态-键</param>
|
|
/// <returns>状态-值</returns>
|
|
public static string GetCarStatus(Car car, string key)
|
|
{
|
|
string value = "0";
|
|
if (car == null) return value;
|
|
if (car.status.enums.TryGetValue(key, out var valueStr))
|
|
value = valueStr;
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加标签
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <param name="tag"></param>
|
|
/// <param name="value"></param>
|
|
public static void AddOrUpdateTag<T>(T item, string tag, string value) where T : TagSet
|
|
{
|
|
if (item.Contains(tag))
|
|
item.Remove(tag);
|
|
item.Add(tag, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除标签
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="item"></param>
|
|
/// <param name="tag"></param>
|
|
public static void DeleteTag<T>(T item, string tag) where T : TagSet
|
|
{
|
|
if (item.Contains(tag))
|
|
{
|
|
item.Remove(tag);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清空标签
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="item"></param>
|
|
public static void ClearTags<T>(T item) where T : TagSet
|
|
{
|
|
item.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加或更新字段
|
|
/// </summary>
|
|
/// <param name="car"></param>
|
|
/// <param name="field"></param>
|
|
/// <param name="value"></param>
|
|
public static void AddOrUpdateCarField(Car car, string field, string value)
|
|
{
|
|
if (car.fields.ContainsKey(field))
|
|
{
|
|
car.fields.Remove(field);
|
|
car.fields.Add(field, value);
|
|
}
|
|
else
|
|
car.fields.Add(field, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除字段
|
|
/// </summary>
|
|
/// <param name="car"></param>
|
|
/// <param name="field"></param>
|
|
public static void DeleteCarField(Car car, string field)
|
|
{
|
|
if (car.fields.ContainsKey(field))
|
|
{
|
|
car.fields.Remove(field);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清空字段
|
|
/// </summary>
|
|
/// <param name="car"></param>
|
|
public static void ClearCarFields(Car car)
|
|
{
|
|
car.fields.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加或更新site的字段
|
|
/// </summary>
|
|
/// <param name="site"></param>
|
|
/// <param name="field"></param>
|
|
/// <param name="value"></param>
|
|
public static void AddOrUpdateSiteField(Site site, string field, string value)
|
|
{
|
|
if (site.fields.ContainsKey(field))
|
|
{
|
|
site.fields.Remove(field);
|
|
site.fields.Add(field, value);
|
|
}
|
|
else
|
|
site.fields.Add(field, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除site的字段
|
|
/// </summary>
|
|
/// <param name="site"></param>
|
|
/// <param name="field"></param>
|
|
public static void DeleteSiteField(Site site, string field)
|
|
{
|
|
if (site.fields.ContainsKey(field))
|
|
{
|
|
site.fields.Remove(field);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清空site的字段
|
|
/// </summary>
|
|
/// <param name="site"></param>
|
|
public static void ClearSiteFields(Site site)
|
|
{
|
|
site.fields.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查给定字符串是否为合法的 HTTP/HTTPS URL(至少包含协议与主机)。
|
|
/// </summary>
|
|
/// <param name="url">待校验的 URL 字符串</param>
|
|
/// <returns>true 表示 URL 合法</returns>
|
|
public static bool IsValidHttpUrl(string url)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(url)) return false;
|
|
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri)) return false;
|
|
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) return false;
|
|
if (string.IsNullOrEmpty(uri.Host)) return false;
|
|
return true;
|
|
}
|
|
|
|
public static double CarValue(Car car, string key)
|
|
{
|
|
if (car.fields.TryGetValue("electricCurrent", out var strelectricCurrent))
|
|
return double.Parse(strelectricCurrent);
|
|
if (key == "Soc" && (car.name.Contains("模拟") || car.name.ToLower().Contains("sim")))
|
|
{
|
|
|
|
if (car.fields.TryGetValue("Soc", out var strSoc))
|
|
return double.Parse(strSoc);
|
|
|
|
return 100;
|
|
}
|
|
|
|
var value = "0";
|
|
if (car.status.enums.TryGetValue(key, out var valueStr))
|
|
value = valueStr;
|
|
return double.Parse(value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加或更新mission的字段
|
|
/// </summary>
|
|
/// <param name="mission"></param>
|
|
/// <param name="field"></param>
|
|
/// <param name="value"></param>
|
|
public static void AddOrUpdateMissionField(Mission mission, string field, string value)
|
|
{
|
|
if (mission.fields.ContainsKey(field))
|
|
{
|
|
mission.fields.Remove(field);
|
|
mission.fields.Add(field, value);
|
|
}
|
|
else
|
|
mission.fields.Add(field, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除mission的字段
|
|
/// </summary>
|
|
/// <param name="mission"></param>
|
|
/// <param name="field"></param>
|
|
/// <returns></returns>
|
|
public static void DeleteMissionField(Mission mission, string field)
|
|
{
|
|
if (mission.fields.ContainsKey(field))
|
|
mission.fields.Remove(field);
|
|
}
|
|
public static List<AbstractCar> GetOnlineCars()
|
|
{
|
|
return SimpleLib.GetAllCars().Where(c => c.GetLastSite() != -1 && Commons.GetVehicleStatus((Car)c)== VehicleStatus.Normal).ToList();
|
|
}
|
|
public static bool IsSceneSiteByCode(int[] siteCodes)
|
|
{
|
|
try
|
|
{
|
|
foreach (var siteCode in siteCodes)
|
|
{
|
|
var site = SimpleLib.GetAllSites().FirstOrDefault(s => s.id == siteCode);
|
|
if (site == null) return false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($@"IsSceneSite 校验报错=>{ex.Message}");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static readonly object PlanSession = new object();
|
|
|
|
public static int SelectCar(AbstractCar car, bool enableGoingStandbyCar = false, bool needCharge = false, bool checkHoldCar = false)
|
|
{
|
|
var carHaveCoordination = (Car)car;
|
|
var conditions = car.GetLastSite() != -1 && GetVehicleStatus((Car)car)== VehicleStatus.Normal&&
|
|
!car.tags.Contains("changePriority") &&
|
|
!car.tags.Contains("priority") && !car.tags.Contains("occupied")
|
|
&& !car.tags.Contains("agvOffline")
|
|
&& car.status.pendingLocks.Length == 0 && !car.tags.Contains("deliver") &&//pendingLocks临时增加解决车接多任务问题
|
|
(!car.tags.Contains("shouldCharge") || needCharge)
|
|
&& !car.tags.Contains("currentWorkStep") && !car.fields.ContainsKey("StopAccept") && car.tags.Contains("Online"); //巡航任务未完成的车
|
|
if (car.name.Contains("模拟"))
|
|
{
|
|
conditions = car.GetLastSite() != -1 &&
|
|
(!car.tags.Contains("holdCar") || !checkHoldCar) && !car.tags.Contains("occupied")
|
|
|
|
&& car.status.pendingLocks.Length == 0 && !car.tags.Contains("deliver") &&//pendingLocks临时增加解决车接多任务问题
|
|
(!car.tags.Contains("shouldCharge") || needCharge)
|
|
&& !car.tags.Contains("currentWorkStep") && !car.fields.ContainsKey("StopAccept"); //巡航任务未完成的车
|
|
}
|
|
//((carHaveCoordination.haveCoordination || car.name.Contains("模拟")) && (!car.tags.Contains("shouldCharge") || needCharge));
|
|
if (conditions) return 1;
|
|
|
|
if (enableGoingStandbyCar && car.tags.TryGetValue("dest", out var dst) &&
|
|
int.TryParse(dst, out var dstId) &&
|
|
SimpleLib.GetSite(dstId).fields.ContainsKey(GetGiveWayType((Car)car))) return 1;
|
|
return -1;
|
|
}
|
|
|
|
private static string GetGiveWayType(Car car)
|
|
{
|
|
if (car.fields.ContainsKey("mover")) return "standbyMover";
|
|
if (car.fields.ContainsKey("loader")) return "standbyLoader";
|
|
return "giveWay";
|
|
}
|
|
public static bool SiteHaveTask(Site site)
|
|
{
|
|
var siteHaveTask = SimpleLib.GetAllCars().ToList().FindAll(o =>
|
|
{
|
|
if (o.status.pendingLocks.Length > 0)
|
|
{
|
|
if (o.status.pendingLocks.Contains(site.id))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if (o.status.holdingLocks.Length > 0)
|
|
{
|
|
if (o.status.holdingLocks.Contains(site.id))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
return false;
|
|
}).Count != 0;
|
|
return siteHaveTask;
|
|
}
|
|
public static SegmentPlan GetNearestPlan(Car car, Func<Site, bool> test, int srcId = -1, bool disableConflict = false)
|
|
{
|
|
var curRouteLength = float.MaxValue;
|
|
SegmentPlan targetPlan = null;
|
|
foreach (var site in SimpleLib.GetAllSites())
|
|
{
|
|
if (!test(site)) continue;
|
|
bool occupied = false;
|
|
foreach (var cc in SimpleLib.GetAllCars())
|
|
{
|
|
if (cc != car)
|
|
{
|
|
if (cc.tags.Contains("dest") && cc.tags.IsEqual("dest", site.id.ToString()) ||
|
|
cc.status.holdingLocks.Contains(site.id))
|
|
occupied = true;
|
|
}
|
|
}
|
|
|
|
if (occupied) continue;
|
|
|
|
var mPlan = new SegmentPlan { usingCar = car };
|
|
if (disableConflict)
|
|
mPlan.fields["forbid_cross"] = "false";
|
|
try
|
|
{
|
|
var newRouteLength = mPlan.FindRoute(
|
|
SimpleLib.GetSite(srcId == -1 ? car.GetLastSite() : srcId),
|
|
SimpleLib.GetSite(site.id));
|
|
|
|
if (newRouteLength < curRouteLength)
|
|
{
|
|
curRouteLength = newRouteLength;
|
|
targetPlan = mPlan;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
return targetPlan;
|
|
}
|
|
|
|
public static void NearestTask(List<Delivery> deliveries, List<Delivery> runningDeliveries = null)
|
|
{
|
|
try
|
|
{
|
|
var curW = float.MaxValue;
|
|
var priority = int.MinValue;
|
|
Delivery priorityNextDelivery = null;
|
|
Delivery deliveryTask = null;
|
|
|
|
//车不是空闲车,但这个任务结束的时候离另一个将要执行的任务很近。
|
|
//(通常来说是同一个工序的,除非单纯地返空托(或路线规划失败,跳别的任务了未按优先级执行)在仓库)
|
|
// 车空闲
|
|
foreach (var car in SimpleLib.GetAllCars().OfType<Car>()) //找到那个车 距离待执行任务最近
|
|
{
|
|
DeleteTag(car.tags, "changePriority");
|
|
//车的状态是OK的
|
|
if (car.GetLastSite() == -1 || car.tags.Contains("agvOffline") || car.tags.Contains("occupied")) continue;
|
|
//车已经被分配过任务了
|
|
if (deliveries.FirstOrDefault(t => t.UsingCar == car) != null) continue;
|
|
|
|
int dst = 0;
|
|
#region ObsoleteCode
|
|
//if (car.tags.ContainsKey("occupied")) //说明是正在执行任务的车
|
|
//{
|
|
|
|
// if (car.tags.ContainsKey("dest")
|
|
// && deliverys.Where(d => d.usingCar != null && d.usingCar == car) == null //并且这个车没有需要等待的任务执行的任务
|
|
// //还存在一种情况车被选了但中途有高优先级的任务进来
|
|
// )
|
|
// {
|
|
// //这个车正在执行的任务
|
|
// dst = int.Parse(car.tags["dest"]);
|
|
// }
|
|
// else
|
|
// {
|
|
// //这个车已经有需要等待的任务了。
|
|
// continue;
|
|
// }
|
|
|
|
|
|
//}
|
|
//else //车空闲
|
|
//{
|
|
// dst = car.GetLastSite();
|
|
//}
|
|
//无效
|
|
#endregion
|
|
dst = car.GetLastSite();
|
|
if (dst == -1)
|
|
{
|
|
//输出日志 变更dst;
|
|
dst = car.status.holdingLocks.First();
|
|
Diagnosis.Post($"调度小车{car.name}:{car.id}的GetLastSite 为 -1 。变更 holdingLocks.First() 为小车初始点{dst}");
|
|
}
|
|
//空闲的车 //如果有多个那个离的最近
|
|
|
|
foreach (var delivery in deliveries.Where(d => d.UsingCar == null))
|
|
{
|
|
//车是否能接到该任务。
|
|
if (car.fields.ContainsKey("group") && !string.IsNullOrEmpty(car.fields["group"]) && !car.fields["group"].Contains(delivery.Group))
|
|
continue;
|
|
|
|
var mPlan = new SegmentPlan { usingCar = car };
|
|
|
|
try
|
|
{
|
|
var myW = mPlan.FindRoute(
|
|
SimpleLib.GetSite(dst),
|
|
SimpleLib.GetSite(delivery.Src));
|
|
|
|
//找到最近的,
|
|
if (myW < curW)
|
|
{
|
|
curW = myW;
|
|
//找到优先级最高的。且距离最近
|
|
if (delivery.Priority >= priority)
|
|
{
|
|
priorityNextDelivery = delivery;
|
|
priority = delivery.Priority;
|
|
Diagnosis.Post($"{priorityNextDelivery.Id}/{priorityNextDelivery.Group}/{priority}", " delivery.priority");
|
|
}
|
|
|
|
//找到距离最近的。
|
|
Delivery nextDelivery = delivery;
|
|
|
|
if (nextDelivery != priorityNextDelivery) //并且这两个任务不同 优先级高的比较远
|
|
{
|
|
if (runningDeliveries != null)
|
|
{
|
|
//优先级高的先执行
|
|
Delivery deliveryRunning = null; // runningDeliveries.Where(d => d.group == priorityNextDelivery.group).FirstOrDefault();
|
|
|
|
//有车正在执行优先级高的任务。有的话就不让车过去
|
|
if (deliveryRunning != null) //true
|
|
{
|
|
Diagnosis.Post($"{deliveryRunning.Id}/{deliveryRunning.UsingCar?.id}/" +
|
|
$"{deliveryRunning.Group}/{deliveryRunning.Priority}", "deliveryRunning");
|
|
deliveryTask = nextDelivery;
|
|
}
|
|
else
|
|
{
|
|
deliveryTask = priorityNextDelivery;
|
|
Diagnosis.Post($"{priorityNextDelivery.Id}/{priorityNextDelivery.UsingCar?.id}/" +
|
|
$"{priorityNextDelivery.Group}/{priorityNextDelivery.Priority}", "priorityNextDelivery1");
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
deliveryTask = priorityNextDelivery;
|
|
Diagnosis.Post($"{priorityNextDelivery.Id}/{priorityNextDelivery.UsingCar?.id}/" +
|
|
$"{priorityNextDelivery.Group}/{priorityNextDelivery.Priority}", "priorityNextDelivery2");
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
deliveryTask = nextDelivery;
|
|
Diagnosis.Post($"{nextDelivery.Id}/{nextDelivery.UsingCar?.id}/" +
|
|
$"{nextDelivery.Group}/{nextDelivery.Priority}", "nextDelivery");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message + ex.ToString());
|
|
}
|
|
}
|
|
if (deliveryTask != null)
|
|
{
|
|
deliveryTask.UsingCar = car;
|
|
deliveryTask.Priority = 50;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
Console.WriteLine(ex.Message + ex.ToString());
|
|
}
|
|
}
|
|
|
|
public static async Task GoSite(AbstractCar car, Site targetSite, int step, string action = "/", bool reverse = false)
|
|
{
|
|
|
|
try
|
|
{
|
|
var plan = new SegmentPlan
|
|
{
|
|
usingCar = car,
|
|
fields =
|
|
{
|
|
["reverse"] = reverse.ToString(),
|
|
["action"] = action,
|
|
["allow_destination_on_route"] = "true"
|
|
}
|
|
};
|
|
/* if (stations!=null && stations.Count()>=1)
|
|
{
|
|
var finishLeftPtlSites = SimpleLib.GetAllSites().Where(site => site.name.Contains("TaskStation")).ToList();
|
|
foreach (var site in finishLeftPtlSites)
|
|
{
|
|
var stationCode = site.name.Split('-')[1];
|
|
if (stations.Contains(stationCode))
|
|
{
|
|
site.fields.Add("askInfons1", "1");
|
|
}
|
|
}
|
|
}*/
|
|
plan.FindRoute(SimpleLib.GetSite(car.GetLastSite()), targetSite);
|
|
//plan.HintNotEnding();
|
|
var program = plan.Compile("move");
|
|
car.tags.Add("occupied", $"go{targetSite.id}");
|
|
Console.WriteLine($">>Script:{program.script}");
|
|
var tsk = program.Queue();
|
|
/* if (stations != null && stations.Count() >= 1)
|
|
{
|
|
var finishLeftPtlSites = SimpleLib.GetAllSites().Where(site => site.name.Contains("TaskStation")).ToList();
|
|
foreach (var site in finishLeftPtlSites)
|
|
{
|
|
var stationCode = site.name.Split('-')[1];
|
|
if (stations.Contains(stationCode))
|
|
{
|
|
site.fields.Remove("askInfons1");
|
|
}
|
|
}
|
|
}*/
|
|
await tsk;
|
|
car.tags.Remove("occupied");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message + "重新执行");
|
|
Thread.Sleep(3000);
|
|
}
|
|
}
|
|
|
|
public static SegmentPlan GenerateEscapePlan(SegmentPlan dstPlan, Func<Site, bool> escapeSiteCondition = null)
|
|
{
|
|
var curW = float.MaxValue;
|
|
var car = dstPlan.usingCar;
|
|
|
|
var escapedSites = SimpleLib.GetAllCars().Where(cc => cc.status.escape.Length > 0)
|
|
.Select(cc => cc.status.escape.Last()).ToHashSet();
|
|
|
|
SegmentPlan planEsc = null;
|
|
foreach (var site in SimpleLib.GetAllSites())
|
|
{
|
|
if (site.id == dstPlan.Destination.id || site.id == dstPlan.Source.id) continue;
|
|
if (escapedSites.Contains(site.id)) continue;
|
|
if (escapeSiteCondition != null && !escapeSiteCondition(site)) continue;
|
|
|
|
bool occupied = false;
|
|
foreach (var cc in SimpleLib.GetAllCars())
|
|
{
|
|
if (cc != car)
|
|
{
|
|
if (cc.status.holdingLocks.Contains(site.id) ||
|
|
(cc.tags.Contains("dest") && cc.tags["dest"] == site.id.ToString())) occupied = true;
|
|
}
|
|
}
|
|
|
|
if (occupied) continue;
|
|
|
|
TryGeneratePlan(dstPlan.usingCar, dstPlan.Destination, site, ref curW, ref planEsc);
|
|
}
|
|
|
|
return planEsc;
|
|
}
|
|
private static void TryGeneratePlan(AbstractCar car, Site srcSite, Site dstSite, ref float curW, ref SegmentPlan generatedPlan)
|
|
{
|
|
var mPlan = new SegmentPlan { usingCar = car, findLoop = false, fields = new Dictionary<string, string>() };
|
|
mPlan.fields["forbid_cross"] = "false";
|
|
try
|
|
{
|
|
var actuallyFindRoute = false;
|
|
|
|
var myw = TryGetWeight(srcSite, dstSite);
|
|
if (myw < 0)
|
|
{
|
|
myw = mPlan.FindRoute(srcSite, dstSite);
|
|
AddWeight(srcSite, dstSite, myw);
|
|
actuallyFindRoute = true;
|
|
}
|
|
|
|
if (myw < curW)
|
|
{
|
|
if (!actuallyFindRoute) mPlan.FindRoute(srcSite, dstSite);
|
|
curW = myw;
|
|
generatedPlan = mPlan;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
public static Dictionary<(Site, Site), float> weightDictionary = new();
|
|
public static float TryGetWeight(Site s1, Site s2)
|
|
{
|
|
lock (weightDictionary)
|
|
{
|
|
if (weightDictionary.TryGetValue((s1, s2), out var w)) return w;
|
|
if (weightDictionary.TryGetValue((s2, s1), out var ww)) return ww;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static void AddWeight(Site s1, Site s2, float w)
|
|
{
|
|
lock (weightDictionary) weightDictionary[(s1, s2)] = w;
|
|
}
|
|
|
|
|
|
|
|
public static SegmentPlan SimpleToNearestPlan(AbstractCar car, Func<Site, bool> test, int srcID = -1)
|
|
{
|
|
var curw = float.MaxValue;
|
|
SegmentPlan targetPlan = null;
|
|
var srcSite = SimpleLib.GetSite(srcID == -1 ? car.GetLastSite() : srcID);
|
|
|
|
foreach (var site in SimpleLib.GetAllSites())
|
|
{
|
|
if (!test(site)) continue;
|
|
if (site.id == srcSite.id) continue;
|
|
bool occupied = false;
|
|
foreach (var cc in SimpleLib.GetAllCars())
|
|
{
|
|
// if (cc != car)//当前
|
|
{
|
|
if (cc.status.holdingLocks.Contains(site.id) ||
|
|
(cc.tags.Contains("dest") && cc.tags["dest"] == site.id.ToString())) occupied = true;
|
|
}
|
|
}
|
|
|
|
if (occupied) continue;
|
|
TryGeneratePlan(car, srcSite, site, ref curw, ref targetPlan);
|
|
}
|
|
|
|
return targetPlan;
|
|
}
|
|
[DllImport("kernel32.dll")]
|
|
static extern IntPtr GetConsoleWindow();
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
|
|
|
|
private static bool ShowConsole = false;
|
|
|
|
public static void ShowConsoleFun()
|
|
{
|
|
ShowConsole = !ShowConsole;
|
|
var handle = GetConsoleWindow();
|
|
int n = ShowConsole ? 0 : 5;
|
|
Console.WriteLine(n);
|
|
ShowWindow(handle, n);
|
|
|
|
}
|
|
public static void HideConsoleFun()
|
|
{
|
|
var handle = GetConsoleWindow();
|
|
ShowWindow(handle, 0);
|
|
}
|
|
}
|
|
}
|