private static Problem GetProblem(Airline airline) { //机场限制和航班限制 var problem = CheckCondition.CheckAirLine(airline); //限制没有问题,则检查故障表 var TyphoonProblem = CheckCondition.IsExistTyphoon(airline); if (airline.PreviousAirline != null) { if (airline.PreviousAirline.FixMethod == enmFixMethod.EmptyFly || (airline.ModifiedPlaneID != null && airline.PlaneID != null && !airline.ModifiedPlaneID.Equals(airline.PlaneID))) { //向上查找第一个不是取消的航班 var PreviousNotCancel = airline.PreviousAirline; while (PreviousNotCancel.FixMethod == enmFixMethod.Cancel) { if (PreviousNotCancel.PreviousAirline != null) { PreviousNotCancel = PreviousNotCancel.PreviousAirline; } } //从这个开始的最后一个不是取消的航班 //检查一下是否过站时间有问题 if (airline.ModifiedStartTime.Subtract(PreviousNotCancel.ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes) { problem.IsNotEnoughStayAirportTime = true; problem.TakeoffAfterThisTimeFixStayTime = PreviousNotCancel.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes); } } } //检查是否同时有两个问题 if (problem.DetailType != ProblemType.None && TyphoonProblem.DetailType != ProblemType.None) { //台风提早起飞的6小时检查时候,可能遇见台风和 problem.DetailType = ProblemType.AirPortTyphoonMix; return(problem); } ; if (TyphoonProblem.DetailType != ProblemType.None) { TyphoonProblem.IsNotEnoughStayAirportTime = problem.IsNotEnoughStayAirportTime; TyphoonProblem.TakeoffAfterThisTimeFixStayTime = problem.TakeoffAfterThisTimeFixStayTime; return(TyphoonProblem); } return(problem); }
public static void ModifyTest() { Airline A0001 = new Airline() { ID = "A0001", Date = "2016-6-15", No = "1", StartAirPort = "北京", EndAirPort = "武汉", StartTime = DateTime.Parse("2016/6/15 14:47"), EndTime = DateTime.Parse("2016/6/15 16:33") }; A0001.ModifiedStartTime = DateTime.Parse("2016/6/15 13:47"); Utility.Log("A0001:StartTime:" + A0001.StartTime); Utility.Log("A0001:EndTime :" + A0001.EndTime); Utility.Log("A0001:ModifiedStartTime:" + A0001.ModifiedStartTime); Utility.Log("A0001:ModifiedEndTime :" + A0001.ModifiedEndTime); }
//两个航班生成联程 public CombinedVoyage(Airline first, Airline second) { //ComboAirLineKey Check if (!first.ComboAirLineKey.Equals(second.ComboAirLineKey)) { if (Utility.IsDebugMode) { Utility.Log("ComboAirLineKey Not Match:[" + first.No + "] VS [" + second.No + "]"); } else { throw new Exception("ComboAirLineKey Not Match!"); } } First = first; Second = second; Date = first.Date; No = first.No; StartAirPort = first.StartAirPort; TransformAirPort = first.EndAirPort; EndAirPort = second.EndAirPort; StartTimeFirst = first.StartTime; EndTimeFirst = first.EndTime; StartTimeSecond = second.StartTime; EndTimeSecond = second.EndTime; PlaneType = first.PlaneType; PlaneID = first.ModifiedPlaneID; //仅两段都是国内的联程航班可以拉直。 //中间机场台风问题可以拉直 DirectAirLine = new Airline { StartAirPort = StartAirPort, EndAirPort = EndAirPort, StartTime = StartTimeFirst, //EndTime已经是经过计算的 EndTime = EndTimeDirect, ModifiedStartTime = StartTimeFirst, PlaneID = PlaneID, ModifiedPlaneID = PlaneID, PlaneType = PlaneType }; }
public static void RunTest() { Airline A0001 = new Airline() { ID = "A0001", Date = "2016-6-15", No = "1", StartAirPort = "北京", EndAirPort = "武汉" }; Airline A0002 = new Airline() { ID = "A0002", Date = "2016-6-19", No = "2", StartAirPort = "武汉", EndAirPort = "北京" }; //联合运输 Airline A0003 = new Airline() { ID = "A0003", Date = "2016-6-20", No = "3", StartAirPort = "上海", EndAirPort = "巴黎" }; Airline A0004 = new Airline() { ID = "A0004", Date = "2016-6-20", No = "3", StartAirPort = "巴黎", EndAirPort = "上海" }; CombinedVoyage C0001 = new CombinedVoyage(A0001, A0002); CombinedVoyage C0002 = new CombinedVoyage(A0003, A0004); }
static void AdjustTakeOffTime(Airline emptyfly) { //以下四种策略进行可行性测试 //如果起飞之前停在台风机场 var StayCheck = IsStayAtTyphoonAirportBeforeTakeOff(emptyfly); if (StayCheck.isOverlap) { //修改起飞时间到最早起飞时间 emptyfly.ModifiedStartTime = StayCheck.typhonn.StartTime; } //如果降落之后停在台风机场 StayCheck = IsStayAtTyphoonAirportAfterLand(emptyfly); if (StayCheck.isOverlap) { //修改起飞时间到最晚起飞时间 emptyfly.ModifiedStartTime = StayCheck.typhonn.EndTime.Subtract(emptyfly.FlightSpan); } }
public static void CheckAirPortProhibit() { //航班一览 //失败:起飞机场关闭 Airline A0001 = new Airline() { ID = "A0001", StartAirPort = "SH", EndAirPort = "BJ", StartTime = new DateTime(2017, 3, 15, 20, 0, 0), EndTime = new DateTime(2017, 3, 15, 23, 0, 0) }; var problem = CheckCondition.CheckAirLine(A0001); Utility.Log("StartTime:" + A0001.StartTime); Utility.Log("TakeOffEarlyTime:" + problem.TakeOffBeforeThisTime + " TakeoffLateTime:" + problem.TakeoffAfterThisTime); //失败:起飞机场关闭(跨日) Airline A0002 = new Airline() { ID = "A0002", StartAirPort = "BJ", EndAirPort = "SH", StartTime = new DateTime(2017, 3, 14, 23, 30, 0), EndTime = new DateTime(2017, 3, 15, 3, 0, 0) }; problem = CheckCondition.CheckAirLine(A0002); Utility.Log("StartTime:" + A0002.StartTime); Utility.Log("LandEarlyTime:" + problem.TakeOffBeforeThisTime + " LandLateTime:" + problem.TakeoffAfterThisTime); Airline A0003 = new Airline() { ID = "A0003", StartAirPort = "BJ", EndAirPort = "SH", StartTime = new DateTime(2017, 3, 15, 1, 30, 0), EndTime = new DateTime(2017, 3, 15, 4, 0, 0) }; problem = CheckCondition.CheckAirLine(A0003); Utility.Log("StartTime:" + A0003.StartTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); //失败:降落机场关闭 Airline B0001 = new Airline() { ID = "B0001", StartAirPort = "BJ", EndAirPort = "SH", StartTime = new DateTime(2017, 3, 15, 15, 0, 0), EndTime = new DateTime(2017, 3, 15, 19, 0, 0) }; problem = CheckCondition.CheckAirLine(B0001); Utility.Log("EndTime:" + B0001.EndTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); //失败:降落机场关闭(跨日,次日) Airline B0002 = new Airline() { ID = "B0002", StartAirPort = "SH", EndAirPort = "BJ", StartTime = new DateTime(2017, 3, 14, 22, 30, 0), EndTime = new DateTime(2017, 3, 15, 1, 0, 0) }; problem = CheckCondition.CheckAirLine(B0002); Utility.Log("EndTime:" + B0002.EndTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); //失败:降落机场关闭(跨日,当日) Airline B0003 = new Airline() { ID = "B0003", StartAirPort = "SH", EndAirPort = "BJ", StartTime = new DateTime(2017, 3, 14, 21, 30, 0), EndTime = new DateTime(2017, 3, 14, 23, 0, 0) }; problem = CheckCondition.CheckAirLine(B0003); Utility.Log("EndTime:" + B0003.EndTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); }
//进行签转 private static void TryTransFer(Airline airline, int NeedForTrans) { //TODO:签转顺序问题,不同顺序可能造成满座,结果不同 foreach (var targetAirline in Solution.AirlineDic.Values) { if (targetAirline.StartAirPort != airline.StartAirPort || targetAirline.EndAirPort != airline.EndAirPort) { continue; //相同起始机场 } if (targetAirline.ID == airline.ID) { continue; //去除自己 } if (targetAirline.FixMethod != enmFixMethod.UnFixed && targetAirline.FixMethod != enmFixMethod.ChangePlane) { continue; //没有调整或者单纯换机型 } if (targetAirline.EmptySeatCnt == 0) { continue; //是否有空座位 } if (targetAirline.ModifiedStartTime < airline.StartTime) { continue; //签转到后续航班 } if (targetAirline.ModifiedStartTime.Subtract(airline.StartTime).TotalMinutes > Utility.DelayInternationalMaxMinute) { continue; } if (targetAirline.EmptySeatCnt >= NeedForTrans) { targetAirline.ReceiveEndorseList.Add(new Airline.EndorseInfo() { AirlineID = airline.ID, GuestCnt = NeedForTrans }); airline.SendEndorseList.Add(new Airline.EndorseInfo() { AirlineID = targetAirline.ID, GuestCnt = NeedForTrans }); break; } else { //EmptySeatCnt是计算属性,所以这里必须使用变量 var transCnt = targetAirline.EmptySeatCnt; targetAirline.ReceiveEndorseList.Add(new Airline.EndorseInfo() { AirlineID = airline.ID, GuestCnt = transCnt }); airline.SendEndorseList.Add(new Airline.EndorseInfo() { AirlineID = targetAirline.ID, GuestCnt = transCnt }); NeedForTrans -= transCnt; } } }
private static bool FixCombinedVoyage(int index, List <Airline> PlaneAirlineList) { //同时,拉直航程,会出现提前问题 //使用常规方法进行修复 Utility.Log("开始修复联程问题-航班号:" + PlaneAirlineList[index].No); var StandScore = Statistics.WriteResult(PlaneAirlineList); Utility.Log("调整前的分数:" + StandScore); bool R1 = true; bool R2 = true; var CloneAirline = Utility.DeepCopy(PlaneAirlineList); Airline first = CloneAirline[index]; Airline second = first.NextAirLine; if (first.Problem != null && (first.Problem.DetailType != ProblemType.None) || first.Problem.IsNotEnoughStayAirportTime) { Utility.Log("修复前半段:"); R1 = FixAirportProblemByChangeTakeOffTime(CloneAirline, index, first); } second.Problem = GetProblem(second); if (second.Problem != null && (second.Problem.DetailType != ProblemType.None) || second.Problem.IsNotEnoughStayAirportTime) { Utility.Log("修复后半段:"); R2 = FixAirportProblemByChangeTakeOffTime(CloneAirline, index + 1, second); } var AfterFixScore = Statistics.WriteResult(CloneAirline); Utility.Log("调整后的增加分数:" + (AfterFixScore - StandScore)); CloneAirline = Utility.DeepCopy(PlaneAirlineList); first = CloneAirline[index]; second = first.NextAirLine; CombinedVoyage combined = first.ComboAirline; if (combined.CanChangeDirect) { //CanDirect是拉直的前提条件 //如果决定拉直航程,看一下拉直之后是否存在问题 var problem = GetProblem(combined.DirectAirLine); var ResultDirect = true; //存在问题的情况下,起飞和降落是否能调整起飞时间解决问题 switch (problem.DetailType) { case ProblemType.TyphoonTakeOff: //台风引起的无法飞行,可以提前飞行! if (!FixTyphoonTakeOffByChangeTakeOffTime(combined.DirectAirLine)) { ResultDirect = false; Utility.Log("[无法修复]联程航班ID:" + first.ID); } else { first.Problem = combined.DirectAirLine.Problem; first.ModifiedStartTime = combined.DirectAirLine.ModifiedStartTime; } break; case ProblemType.AirportProhibitTakeOff: case ProblemType.AirportProhibitLand: case ProblemType.TyphoonLand: //降落(机场限制)具有可用最早最晚降落时间 if (!FixByChangeTakeOffTime(combined.DirectAirLine)) { ResultDirect = false; Utility.Log("[无法修复]联程航班ID:" + first.ID); } else { first.Problem = combined.DirectAirLine.Problem; first.ModifiedStartTime = combined.DirectAirLine.ModifiedStartTime; } break; case ProblemType.None: break; default: Utility.Log("联程错误:" + problem.DetailType.ToString()); ResultDirect = false; break; } var AfterDirectFixScore = double.MaxValue; if (ResultDirect) { //第一段航程进行标注:直航 if (first.Problem == null) { first.Problem = new Problem(); } first.FixMethod = enmFixMethod.Direct; first.ImportFac = combined.ImportFac; first.EndAirPort = combined.DirectAirLine.EndAirPort; //第二段航程进行标注:取消 if (second.Problem == null) { second.Problem = new Problem(); } second.FixMethod = enmFixMethod.CancelByDirect; second.ImportFac = combined.ImportFac; AfterDirectFixScore = Statistics.WriteResult(CloneAirline); Utility.Log("调整后的增加分数:" + (AfterDirectFixScore - StandScore)); } if (R1 && R2 && (!ResultDirect || AfterFixScore < AfterDirectFixScore)) { //R1,R2成功,并且 拉直失败 或者 常规比较划算 if (first.Problem != null && first.Problem.DetailType != ProblemType.None) { FixAirportProblemByChangeTakeOffTime(PlaneAirlineList, index, first); } if (second.Problem != null && second.Problem.DetailType != ProblemType.None) { FixAirportProblemByChangeTakeOffTime(PlaneAirlineList, index + 1, second); } return(true); } else { //使用拉直 if (ResultDirect) { first = PlaneAirlineList[index]; second = first.NextAirLine; //第一段航程进行标注:直航 if (first.Problem == null) { first.Problem = new Problem(); } first.FixMethod = enmFixMethod.Direct; first.ImportFac = combined.ImportFac; first.EndAirPort = combined.DirectAirLine.EndAirPort; //第二段航程进行标注:取消 if (second.Problem == null) { second.Problem = new Problem(); } second.FixMethod = enmFixMethod.CancelByDirect; second.ImportFac = combined.ImportFac; AfterDirectFixScore = Statistics.WriteResult(CloneAirline); return(true); } } } else { if (R1 && R2) { //R1,R2成功,并且 拉直失败 或者 常规比较划算 if (first.Problem != null && first.Problem.DetailType != ProblemType.None) { FixAirportProblemByChangeTakeOffTime(PlaneAirlineList, index, first); } if (second.Problem != null && second.Problem.DetailType != ProblemType.None) { FixAirportProblemByChangeTakeOffTime(PlaneAirlineList, index + 1, second); } return(true); } } return(false); }
private static Airline GetEmptyFly(List <Airline> AirlineList, int StartIndex, int EndIndex) { var EmptyFly = new Airline(); //起飞时间取起飞前50分钟 int EmptyFlySpan = Solution.FlyTimeDic[AirlineList[StartIndex].PlaneType + int.Parse(AirlineList[StartIndex].StartAirPort).ToString("D2") + int.Parse(AirlineList[EndIndex].StartAirPort).ToString("D2")]; EmptyFly.EndTime = AirlineList[EndIndex].StartTime.AddMinutes(-Utility.StayAtAirPortMinutes); EmptyFly.StartTime = EmptyFly.EndTime.AddMinutes(-EmptyFlySpan); EmptyFly.ModifiedStartTime = EmptyFly.StartTime; EmptyFly.ModifiedPlaneID = AirlineList[StartIndex].ModifiedPlaneID; EmptyFly.PlaneType = AirlineList[StartIndex].PlaneType; EmptyFly.FixMethod = enmFixMethod.EmptyFly; EmptyFly.StartAirPort = AirlineList[StartIndex].StartAirPort; EmptyFly.EndAirPort = AirlineList[EndIndex].StartAirPort; //调整调机后航班的PreviousAirLine的值 AirlineList[EndIndex].PreviousAirline = EmptyFly; EmptyFly.NextAirLine = AirlineList[EndIndex]; AirlineList[StartIndex - 1].NextAirLine = EmptyFly; EmptyFly.PreviousAirline = AirlineList[StartIndex - 1]; //目标机场能否降落? var TyphoonProblem = CheckCondition.IsExistTyphoon(EmptyFly); switch (TyphoonProblem.DetailType) { //调整落地时间 case ProblemType.TyphoonLand: //获得降落机场停机的最后降落时间 foreach (var typhoon in CheckCondition.TyphoonList) { if (typhoon.AirPort == EmptyFly.EndAirPort) { EmptyFly.EndTime = typhoon.EndTime; EmptyFly.StartTime = EmptyFly.EndTime.AddMinutes(-EmptyFlySpan); EmptyFly.ModifiedStartTime = EmptyFly.StartTime; //过站时间不足的处理 if (EmptyFly.NextAirLine.ModifiedStartTime.Subtract(EmptyFly.ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes) { EmptyFly.NextAirLine.Problem = new Problem { TakeOffBeforeThisTime = DateTime.MinValue, TakeoffAfterThisTime = EmptyFly.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes) }; FixAirportProblemByChangeTakeOffTime(AirlineList, EndIndex, EmptyFly.NextAirLine); } if (AirlineList[EndIndex].IsUseTyphoonRoom) { //如果降落的时候使用IsCanEmptyFly方法是用了机库,这里通过调整,使得不用到机库,退还机库 CheckCondition.TyphoonAirportRemain[EmptyFly.EndAirPort]++; } break; } } break; case ProblemType.TyphoonTakeOff: //获得起飞机场停机的最早起飞时间 foreach (var typhoon in CheckCondition.TyphoonList) { if (typhoon.AirPort == EmptyFly.StartAirPort && typhoon.TroubleType.Equals("起飞")) { EmptyFly.StartTime = typhoon.StartTime; EmptyFly.EndTime = EmptyFly.StartTime.AddMinutes(EmptyFlySpan); EmptyFly.ModifiedStartTime = EmptyFly.StartTime; //最早时间起飞,再影响上一个航班也没有办法了 break; } } break; } var AirportCloseLand = CheckCondition.IsAirPortAvalible(EmptyFly.EndAirPort, EmptyFly.ModifiedEndTime); var AirportCloseTakeoff = CheckCondition.IsAirPortAvalible(EmptyFly.StartAirPort, EmptyFly.ModifiedStartTime); if (!AirportCloseLand.IsAvalible) { var TempProblem = new Problem(); CheckCondition.SetRecoverInfo(EmptyFly, TempProblem, AirportCloseLand, false); EmptyFly.ModifiedStartTime = TempProblem.TakeoffAfterThisTime; } if (!AirportCloseTakeoff.IsAvalible) { var TempProblem = new Problem(); CheckCondition.SetRecoverInfo(EmptyFly, TempProblem, AirportCloseTakeoff, true); EmptyFly.ModifiedStartTime = TempProblem.TakeOffBeforeThisTime; } AdjustTakeOffTime(EmptyFly); return(EmptyFly); }
public static (bool isOverlap, Typhoon typhonn) IsStayAtTyphoonAirportAfterLand(Airline airline) { foreach (var typhoon in CheckCondition.TyphoonList) { if (typhoon.AirPort.Equals(airline.EndAirPort) && typhoon.TroubleType.Equals("停机")) { if (airline.NextAirLine != null) { //降落在台风后面 bool LandTimeInRange = typhoon.IsInRange(airline.ModifiedEndTime); bool TakeOffTimeInRange = typhoon.IsInRange(airline.NextAirLine.ModifiedStartTime); return(LandTimeInRange || TakeOffTimeInRange, typhoon); } } else { continue; } } return(false, new Typhoon()); }
public static (bool isOverlap, Typhoon typhonn) IsStayAtTyphoonAirportBeforeTakeOff(Airline airline) { foreach (var typhoon in CheckCondition.TyphoonList) { if (typhoon.AirPort.Equals(airline.StartAirPort) && typhoon.TroubleType.Equals("停机")) { if (airline.PreviousAirline != null) { //前一班降落时间是否在台风停机时段之后,如果之后,则返回否,不然为真 return(airline.PreviousAirline.ModifiedEndTime < typhoon.EndTime, typhoon); } } else { continue; } } return(false, new Typhoon()); }
/// <summary> /// 航班可用性检查 /// </summary> /// <param name="airline"></param> /// <returns></returns> public static Problem CheckAirLine(Airline airline) { //问题列表 List <Problem> ProblemList = new List <Problem>(); //机场关闭限制的检查 //起飞,降落机场的确认 var checkResult = IsAirPortAvalible(airline.StartAirPort, airline.ModifiedStartTime); if (!checkResult.IsAvalible) { var problem = new Problem(); Utility.Log("[机场关闭限制:起飞]航班ID:[" + airline.ID + "] 机场:[" + airline.StartAirPort + "] 时间:[" + airline.ModifiedStartTime + "]"); problem.DetailType = ProblemType.AirportProhibitTakeOff; SetRecoverInfo(airline, problem, checkResult, true); Utility.Log("StartTime:" + airline.ModifiedStartTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); ProblemList.Add(problem); } checkResult = IsAirPortAvalible(airline.EndAirPort, airline.ModifiedEndTime); if (!checkResult.IsAvalible) { var problem = new Problem(); Utility.Log("[机场关闭限制:降落]航班ID:[" + airline.ID + "] 机场:[" + airline.EndAirPort + "] 时间:[" + airline.ModifiedEndTime + "]"); problem.DetailType = ProblemType.AirportProhibitLand; SetRecoverInfo(airline, problem, checkResult, false); Utility.Log("EndTime:" + airline.ModifiedEndTime); Utility.Log("TakeOffBeforeThisTime:" + problem.TakeOffBeforeThisTime + " TakeoffAfterThisTime:" + problem.TakeoffAfterThisTime); ProblemList.Add(problem); } //航班-飞机限制的检查 if (!IsAirlinePlaneAvalible(airline.StartAirPort, airline.EndAirPort, airline.ModifiedPlaneID)) { var problem = new Problem(); Utility.Log("[飞行限制 ]航班ID:[" + airline.ID + "] 起飞机场:[" + airline.StartAirPort + "] 降落机场:[" + airline.EndAirPort + "] 飞机编号:[" + airline.ModifiedPlaneID + "]"); problem.DetailType = ProblemType.AirLinePlaneProhibit; ProblemList.Add(problem); } if (ProblemList.Count > 1) { if (ProblemList[0].TakeoffAfterThisTime > ProblemList[1].TakeoffAfterThisTime) { return(ProblemList[0]); } else { return(ProblemList[1]); } } ; if (ProblemList.Count == 0) { ProblemList.Add(new Problem()); if (Utility.PrintInfo) { Utility.Log("[正常 ]航班ID:[" + airline.ID + "]"); } } return(ProblemList[0]); }
//读取CSV文件 public static void ReadCSV() { StreamReader reader = null; //飞行表 if (File.Exists(Utility.FlyTimeCSV)) { reader = new StreamReader(Utility.FlyTimeCSV); Utility.Log("读取飞行时间表文件:" + Utility.FlyTimeCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { var items = reader.ReadLine().Split(","); var key = items[0] + int.Parse(items[1]).ToString("D2") + int.Parse(items[2]).ToString("D2"); //原数据存在主键重复的问题 if (!FlyTimeDic.ContainsKey(key)) { FlyTimeDic.Add(key, int.Parse(items[3])); } } reader.Close(); Utility.Log("飞行时间记录数:" + FlyTimeDic.Count); } //读取航班信息表 Utility.Log("读取航班信息文件:" + Utility.AirlineCSV); reader = new StreamReader(Utility.AirlineCSV); List <Airline> AirlineList = new List <Airline>(); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { var airline = new Airline(reader.ReadLine()); AirlineList.Add(airline); AirlineDic.Add(airline.ID, airline); } reader.Close(); var SameComboAirKey = AirlineList.GroupBy((x) => { return(x.ComboAirLineKey); }); foreach (var item in SameComboAirKey) { if (item.Count() == 2) { Airline first; Airline second; if (item.First().StartTime > item.Last().StartTime) { first = item.Last(); second = item.First(); } else { first = item.First(); second = item.Last(); } var combined = new CombinedVoyage(first, second); first.IsFirstCombinedVoyage = true; first.ComboAirline = combined; second.ComboAirline = combined; CombinedVoyageList.Add(combined); } } Utility.Log("航班数:" + AirlineDic.Count + " 联程数:" + CombinedVoyageList.Count); if (File.Exists(Utility.TyphoonCSV)) { Utility.Log("读取台风场景文件:" + Utility.TyphoonCSV); reader = new StreamReader(Utility.TyphoonCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { var typhoon = new Typhoon(reader.ReadLine()); CheckCondition.TyphoonList.Add(typhoon); if (!CheckCondition.TyphoonAirport.Contains(typhoon.AirPort)) { CheckCondition.TyphoonAirport.Add(typhoon.AirPort); } if (typhoon.TroubleType == "停机") { CheckCondition.TyphoonAirportRemain.Add(typhoon.AirPort, typhoon.StayCnt); } Utility.Log(typhoon.ToString()); } reader.Close(); Utility.Log("台风场景数:" + CheckCondition.TyphoonList.Count); } if (File.Exists(Utility.AirportProhibitCSV)) { Utility.Log("读取机场限制文件:" + Utility.AirportProhibitCSV); reader = new StreamReader(Utility.AirportProhibitCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { CheckCondition.AirPortProhibitList.Add(new AirPortProhibit(reader.ReadLine())); } reader.Close(); Utility.Log("机场限制数:" + CheckCondition.AirPortProhibitList.Count); } if (File.Exists(Utility.PlaneProhibitCSV)) { Utility.Log("读取航线-飞机限制文件:" + Utility.PlaneProhibitCSV); reader = new StreamReader(Utility.PlaneProhibitCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { CheckCondition.PlaneProhibitList.Add(new PlaneProhibit(reader.ReadLine())); } reader.Close(); Utility.Log("航线-飞机限制数:" + CheckCondition.AirPortProhibitList.Count); } if (File.Exists(Utility.TransTimeCSV)) { Utility.Log("读取旅客中转时间限制表文件:" + Utility.TransTimeCSV); reader = new StreamReader(Utility.TransTimeCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { TransTimeList.Add(new TransTime(reader.ReadLine())); } reader.Close(); Utility.Log("旅客中转时间限制数:" + TransTimeList.Count); } if (File.Exists(Utility.AirportCSV)) { Utility.Log("读取机场表文件:" + Utility.AirportCSV); reader = new StreamReader(Utility.AirportCSV); //去除标题 reader.ReadLine(); while (!reader.EndOfStream) { var temp = reader.ReadLine().Split(",".ToCharArray()); if (temp[1] == "1") { DomaticAirport.Add(temp[0]); } } reader.Close(); Utility.Log("国际机场数:" + DomaticAirport.Count); } Utility.Log("执飞表建立:"); GetAirlineDicByPlaneId(); Utility.Log("飞机数量:" + PlaneIdAirlineDic.Count()); }
//调整航班的起飞时间 //返回值表示是否能成功 public static bool FixByChangeTakeOffTime(Airline airline) { if (airline.Problem.DetailType == ProblemType.TyphoonStay) { return(false); } //这里的Early是这样考虑的,起飞时间选取早的那种,但是,这种早有一个前提条件,就是和原计划相比是延迟的。 bool CanEarly = true; var TakeOffTime = airline.Problem.TakeOffBeforeThisTime; var LandTime = TakeOffTime.Add(airline.FlightSpan); if (TakeOffTime > airline.StartTime) { //是否影响上一个航班的过站时间 CanEarly = TakeOffTime.Subtract(airline.PreviousAirline.ModifiedEndTime).TotalMinutes >= Utility.StayAtAirPortMinutes; if (CanEarly) { //延迟:国内24小时,国际36小时 if (airline.InterKbn == "国内") { CanEarly = TakeOffTime.Subtract(airline.StartTime).TotalMinutes <= Utility.DelayDemasticMaxMinute; } else { CanEarly = TakeOffTime.Subtract(airline.StartTime).TotalMinutes <= Utility.DelayInternationalMaxMinute; } } } else { CanEarly = false; } if (CanEarly) { var TempStartTime = airline.ModifiedStartTime; airline.ModifiedStartTime = airline.Problem.TakeOffBeforeThisTime; Utility.Log("[起飞(机场限制)]调整完毕航班:航班ID:" + airline.ID + " 修改起飞时间:" + TempStartTime + "->" + airline.ModifiedStartTime); return(true); } //尝试延迟起飞 bool CanLate = true; if (airline.Problem.IsNotEnoughStayAirportTime) { TakeOffTime = airline.Problem.GetTakeOffTime(); } else { TakeOffTime = airline.Problem.TakeoffAfterThisTime; } if (TakeOffTime == DateTime.MaxValue) { CanLate = false; } else { LandTime = TakeOffTime.Add(airline.FlightSpan); //是否影响上一班的过站时间(这里的延迟只是相对于计划时间来说的,可能上一个步骤修改过时间了) if (airline.PreviousAirline != null) { CanLate = TakeOffTime.Subtract(airline.PreviousAirline.ModifiedEndTime).TotalMinutes >= Utility.StayAtAirPortMinutes; } //是否影响下一班的过站时间 if (airline.NextAirLine != null && CanLate) { CanLate = airline.NextAirLine.ModifiedStartTime.Subtract(LandTime).TotalMinutes >= Utility.StayAtAirPortMinutes; } if (CanLate) { //延迟:国内24小时,国际36小时 CanLate = IsLatable(airline, TakeOffTime); } } if (CanLate) { var TempStartTime = airline.ModifiedStartTime; airline.ModifiedStartTime = TakeOffTime; Utility.Log("[起飞(机场限制)]调整完毕航班:航班ID:" + airline.ID + " 修改起飞时间:" + TempStartTime + "->" + airline.ModifiedStartTime); return(true); } return(false); }
private static bool FixAirportProblemByChangeTakeOffTime(List <Airline> PlaneAirlineList, int index, Airline airline) { var ProblemDescript = string.Empty; if (PlaneAirlineList[index].Problem == null) { return(false); } switch (PlaneAirlineList[index].Problem.DetailType) { case ProblemType.TyphoonLand: ProblemDescript = "[台风:降落]"; break; case ProblemType.TyphoonTakeOff: ProblemDescript = "[台风:起飞]"; break; case ProblemType.TyphoonStay: ProblemDescript = "[台风:停机]"; if (CheckCondition.TyphoonAirportRemain[PlaneAirlineList[index].StartAirPort] != 0 && Utility.IsUseTyphoonStayRoom) { CheckCondition.TyphoonAirportRemain[PlaneAirlineList[index].StartAirPort]--; PlaneAirlineList[index].IsUseTyphoonRoom = true; return(true); } else { Utility.Log("[无法修复]航班ID:" + PlaneAirlineList[index].ID); return(false); } default: break; } var StandardScore = Statistics.WriteResult(PlaneAirlineList); Utility.Log("调整前基准分数:" + StandardScore); //调整独立的 Utility.Log(ProblemDescript + "尝试调整航班(独立):航班ID:" + airline.ID); var CloneAirline_SingleChange = Utility.DeepCopy(PlaneAirlineList); var SingleResult = FixByChangeTakeOffTime(CloneAirline_SingleChange[index]); Utility.Log((SingleResult ? "[成功]" : "[失败]") + "调整航班(独立)增加分数:" + (Statistics.WriteResult(CloneAirline_SingleChange) - StandardScore)); if (SingleResult) { FixByChangeTakeOffTime(PlaneAirlineList[index]); StandardScore = Statistics.WriteResult(PlaneAirlineList); Utility.Log("调整后基准分数:" + StandardScore); return(true); } //延迟单个航班可能无法解决问题,则考虑顺延所有航班(温和的) Utility.Log(ProblemDescript + "尝试调整航班(温和的链式):航班ID:" + airline.ID); var CloneAirline_ChainChange = Utility.DeepCopy(PlaneAirlineList); var ChainResult = FixByChangeTakeOffTime(CloneAirline_ChainChange, index); Utility.Log((ChainResult ? "[成功]" : "[失败]") + "调整航班(温和的链式)增加分数:" + (Statistics.WriteResult(CloneAirline_ChainChange) - StandardScore)); if (ChainResult) { FixByChangeTakeOffTime(PlaneAirlineList, index); StandardScore = Statistics.WriteResult(PlaneAirlineList); Utility.Log("调整后基准分数:" + StandardScore); return(true); } //延迟单个航班可能无法解决问题,则考虑顺延所有航班(强制的) Utility.Log(ProblemDescript + "尝试调整航班(强制的链式):航班ID:" + airline.ID); var CloneAirline_ChainChange_Force = Utility.DeepCopy(PlaneAirlineList); var ChainForceResult = FixChainByChangeTakeOffTime_Force(CloneAirline_ChainChange_Force, index); Utility.Log((ChainForceResult ? "[成功]" : "[失败]") + "调整航班(强制的链式)增加分数:" + (Statistics.WriteResult(CloneAirline_ChainChange_Force) - StandardScore)); if (ChainForceResult) { FixChainByChangeTakeOffTime_Force(PlaneAirlineList, index); StandardScore = Statistics.WriteResult(PlaneAirlineList); Utility.Log("调整后基准分数:" + StandardScore); return(true); } Utility.Log("[失败]通过修改起飞时间来修复错误"); return(false); }
/// <summary> /// 修复台风引发的无法起飞 /// </summary> /// <returns>是否修复成功</returns> /// <remarks> /// 可以提前起飞,但是必须能够满足过站条件 /// </remarks> public static bool FixTyphoonTakeOffByChangeTakeOffTime(Airline airline) { //尝试提早起飞 bool CanEarly = (airline.InterKbn == "国内"); var TakeOffTime = airline.Problem.TakeOffBeforeThisTime; if (CanEarly) { if (airline.PreviousAirline != null) { //是否影响上一班的过站时间 CanEarly = TakeOffTime.Subtract(airline.PreviousAirline.ModifiedEndTime).TotalMinutes >= Utility.StayAtAirPortMinutes; } if (CanEarly) { //提早:过站50分钟,最大时间6小时,国内航班 CanEarly = airline.StartTime.Subtract(TakeOffTime).TotalMinutes <= Utility.EarlyMaxMinute; } } //尝试延迟起飞 bool CanLate = true; TakeOffTime = airline.Problem.IsNotEnoughStayAirportTime ? airline.Problem.GetTakeOffTime() : airline.Problem.TakeoffAfterThisTime; if (TakeOffTime == DateTime.MaxValue) { CanLate = false; } else { var LandTime = TakeOffTime.Add(airline.FlightSpan); //是否影响下一班的过站时间 CanLate = airline.NextAirLine.ModifiedStartTime.Subtract(LandTime).TotalMinutes >= Utility.StayAtAirPortMinutes; if (CanLate) { //延迟:国内24小时,国际36小时 if (airline.InterKbn == "国内") { CanLate = TakeOffTime.Subtract(airline.StartTime).TotalMinutes <= Utility.DelayDemasticMaxMinute; } else { CanLate = TakeOffTime.Subtract(airline.StartTime).TotalMinutes <= Utility.DelayInternationalMaxMinute; } } } //既不能提前,也不能延迟 if (!CanEarly && !CanLate) { return(false); } if (CanEarly && !CanLate) { //提前 airline.ModifiedStartTime = airline.Problem.TakeOffBeforeThisTime; } if (!CanEarly && CanLate) { //延迟 airline.ModifiedStartTime = TakeOffTime; } if (CanEarly && CanLate) { double EarlyMinutePunish = airline.StartTime.Subtract(airline.Problem.TakeOffBeforeThisTime).TotalMinutes *Statistics.TotalEarlyParm; double DelayMinutePunish = TakeOffTime.Subtract(airline.StartTime).TotalMinutes *Statistics.TotalDelayParm; if (EarlyMinutePunish > DelayMinutePunish) { airline.ModifiedStartTime = TakeOffTime; } else { airline.ModifiedStartTime = airline.Problem.TakeOffBeforeThisTime; } } Utility.Log("[起飞(机场限制)]调整完毕航班:航班ID:" + airline.ID + " 修改起飞时间:" + airline.StartTime + "->" + airline.ModifiedStartTime); return(true); }
/// <summary> /// 设定最早(晚)能够起飞(降落)的时间 /// </summary> /// <param name="airline"></param> /// <param name="problem"></param> /// <param name="checkResult"></param> /// <param name="IsTakeOff"></param> public static void SetRecoverInfo(Airline airline, Problem problem, (bool IsAvalible, string CloseTime, string OpenTime) checkResult, bool IsTakeOff)