Esempio n. 1
0
        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);
        }
Esempio n. 3
0
 //两个航班生成联程
 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
     };
 }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
 //进行签转
 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;
         }
     }
 }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
 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());
 }
Esempio n. 11
0
 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());
 }
Esempio n. 12
0
        /// <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]);
        }
Esempio n. 13
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);
        }
Esempio n. 17
0
 /// <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)