Exemple #1
0
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            bool fIsAirplane = CategoryClass.IsAirplane(cfr.idCatClassOverride);
            bool fIsIFRSim   = (fIsAirplane && cfr.fIsFTD);

            if (fIsAirplane || cfr.fIsRealAircraft)
            {
                miMinInstrumentTime.AddTrainingEvent(cfr.IMC + cfr.IMCSim, ATPMaxIFRSimulator, fIsIFRSim);
            }

            if (fIsAirplane && cfr.idCatClassOverride == requiredCatClassID)
            {
                bool fIsFullSim = !cfr.fIsRealAircraft && cfr.fIsCertifiedLanding;
                if (fIsAirplane && (cfr.fIsRealAircraft || fIsFullSim))
                {
                    miMinTimeInClass.AddTrainingEvent(cfr.Total, ATPMinTimeInClassFullSimulator, fIsFullSim);
                }
            }

            // Above are the only things to which we will alow training devices.
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            miTotal.AddEvent(Math.Max(CanCreditSICAndFlightEngineer ? cfr.SIC : 0, cfr.Total));
            miMinXCTime.AddEvent(cfr.XC);
            miMinNightTime.AddEvent(cfr.Night);

            if (CanCreditSICAndFlightEngineer)
            {
                decimal flightEngineerTime = 0.0M;
                cfr.ForEachEvent((pe) => { if (pe.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropFlightEngineerTime)
                                           {
                                               flightEngineerTime += pe.DecValue;
                                           }
                                 });

                if (flightEngineerTime > 0)
                {
                    miTotal.AddTrainingEvent(flightEngineerTime / 3.0M, ATPMaxFlightEngineer, true);
                }
            }

            // Remainder must be done in a real aircraft and it must be in an airplane.
            // Not clear if the night takeoffs/landings need to be in a real aircraft / airplane, but I'll require it to be safe.
            if (fIsAirplane)
            {
                miMinPIC.AddEvent(cfr.PIC);
                miMinPICXC.AddEvent(Math.Min(cfr.PIC, cfr.XC));
                miMinPICNight.AddEvent(Math.Min(cfr.PIC, cfr.Night));
                cfr.ForEachEvent((pe) => { if (pe.PropertyType.IsNightTakeOff)
                                           {
                                               miNightTO.AddEvent(pe.IntValue);
                                           }
                                 });
                miNightLanding.AddEvent(cfr.cFullStopNightLandings);
            }
        }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }
            m_fCacheValid = false;

            // 401.05(3)(a) - IPC or equivalent
            cfr.ForEachEvent((pfe) =>
            {
                // add any IPC or IPC equivalents
                if (pfe.PropertyType.IsIPC)
                {
                    fc401_05_3_a.AddRecentFlightEvents(cfr.dtFlight, 1.0M);
                }
            });

            decimal IFRTime    = cfr.IMC + cfr.IMCSim;
            decimal IFRCFITime = Math.Min(IFRTime, cfr.CFI);

            // 401.05(3)(b) - flight in a real aircraft or sim
            fc401_05_3_bTime.AddRecentFlightEvents(cfr.dtFlight, Math.Max(0, IFRTime - IFRCFITime));
            fc401_05_3_bApproaches.AddRecentFlightEvents(cfr.dtFlight, cfr.cApproaches);

            // 401.05(3)(c) - IFR instruction in a real aircraft
            if (cfr.fIsRealAircraft)
            {
                fc401_05_3_cTime.AddRecentFlightEvents(cfr.dtFlight, IFRCFITime);
                fc401_05_3_cApproaches.AddRecentFlightEvents(cfr.dtFlight, cfr.CFI > 0 ? cfr.cApproaches : 0);
            }
        }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }

            // No training devices for sport pilots
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            // Keep track of heavier-than-air time, reduce minimums if achieved
            if (CategoryClass.IsHeavierThanAir(cfr.idCatClassOverride))
            {
                TotalHeavierThanAir += cfr.Total;
                if (!QualifiesByHeavierThanAir && TotalHeavierThanAir >= 20)
                {
                    QualifiesByHeavierThanAir      = true;
                    miMinTime.Threshold            = 3;
                    miMinTrainingFlights.Threshold = 5;
                    miMinSolo.Threshold            = 1;
                    miMinSolo.Threshold            = 3;
                }
            }

            // now reject anything not in a glider
            if (CatClassID != cfr.idCatClassOverride)
            {
                return;
            }

            miMinTime.AddEvent(cfr.Total);
            if (cfr.Dual > 0)
            {
                miMinTrainingFlights.AddEvent(Math.Max(1, cfr.cLandingsThisFlight));
                if (DateTime.Now.AddCalendarMonths(-2).CompareTo(cfr.dtFlight) <= 0)
                {
                    miTestPrep.AddEvent(cfr.Dual);
                }
            }

            decimal soloTime = 0.0M;

            cfr.ForEachEvent(pf => { if (pf.PropertyType.IsSolo)
                                     {
                                         soloTime += pf.DecValue;
                                     }
                             });
            if (soloTime > 0)
            {
                miMinSolo.AddEvent(soloTime);
                miMinSoloFlights.AddEvent(cfr.cLandingsThisFlight); // assuming no touch-and-go in a glider!
            }
        }
Exemple #4
0
 public override void ExamineFlight(ExaminerFlightRow cfr)
 {
     cfr.ForEachEvent((pfe) =>
     {
         if (pfe.PropertyType.IsIPC)
         {
             AddRecentFlightEvents(cfr.dtFlight, 1);
         }
     });
 }
Exemple #5
0
 public override void ExamineFlight(ExaminerFlightRow cfr)
 {
     cfr.ForEachEvent((pfe) =>
     {
         if (pfe.PropTypeID == (int)CustomPropertyType.KnownProperties.IDProp135293Competency || pfe.PropertyType.IsIPC)
         {
             AddRecentFlightEvents(cfr.dtFlight, 1);
         }
     });
 }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }

            // No training devices for sport pilots
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            // Minimum time can be in anything
            miMinTime.AddEvent(cfr.Total);

            // Everything else must be in matching category/class
            // allow perfect match or ASEL->ASES match
            if (CatClassID != cfr.idCatClassOverride && !(CatClassID == CategoryClass.CatClassID.ASEL && cfr.idCatClassOverride == CategoryClass.CatClassID.ASES))
            {
                return;
            }

            miMinInstruction.AddEvent(cfr.Dual);
            decimal soloTime = 0.0M;

            cfr.ForEachEvent(pf => { if (pf.PropertyType.IsSolo)
                                     {
                                         soloTime += pf.DecValue;
                                     }
                             });
            miMinSolo.AddEvent(soloTime);

            int cFSLandings = cfr.cFullStopLandings + cfr.cFullStopNightLandings;

            miMinCrossCountry.AddEvent(Math.Min(cfr.XC, cfr.Dual));
            miMinLandings.AddEvent(cFSLandings);
            if (soloTime > 0 && cFSLandings > 1)
            {
                AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route, true);

                if (al.DistanceForRoute() > MinXCDistance && al.MaxSegmentForRoute() > 25)
                {
                    miSoloXCFlight.AddEvent(1);
                    miSoloXCFlight.MatchingEventID   = cfr.flightID;
                    miSoloXCFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.MilestoneProgress.MatchingXCFlightTemplate, cfr.dtFlight.ToShortDateString(), cfr.Route);
                }
            }

            if (DateTime.Now.AddCalendarMonths(-2).CompareTo(cfr.dtFlight) <= 0)
            {
                miTestPrep.AddEvent(cfr.Dual);
            }
        }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }

            decimal ifrTraining = Math.Min(cfr.Dual, cfr.IMC + cfr.IMCSim);

            // Aeronautical experience - can be in any aircraft or certified sim
            if (cfr.fIsCertifiedIFR)    // includes real aircraft
            {
                miAeronauticalExperience.AddEvent(Math.Max(cfr.GroundSim, cfr.Total));
            }

            // total pilot time and IFR time can both be in any real aircraft
            if (miPilotTime != null && cfr.fIsRealAircraft)
            {
                miPilotTime.AddEvent(cfr.Total);
            }
            miDualInstrumentTime.AddEvent((cfr.fIsRealAircraft || cfr.fIsCertifiedIFR) ? ifrTraining : 0);

            // everything else must be in a matching category AND must be in a real aircraft
            if (IsMatchingCategory(cfr.idCatClassOverride) && cfr.fIsRealAircraft)
            {
                decimal soloTime = 0.0M;
                cfr.ForEachEvent(pf =>
                {
                    if (pf.PropertyType.IsSolo)
                    {
                        soloTime += pf.DecValue;
                    }
                });

                miTimeInCategory.AddEvent(cfr.Total);
                miSoloTimeInCategory.AddEvent(soloTime);
                miSoloXCTimeInCategory.AddEvent(Math.Min(soloTime, cfr.XC));
                miDualInstrumentTimeInCategory.AddEvent(ifrTraining);

                bool fAllowLongXC = (soloTime > 0 || (!fLongCrossCountryMustBeSolo && cfr.PIC > 0));    // solo is always OK for cross country, otherwise need PIC.
                if (fAllowLongXC && !miSoloLongCrossCountry.IsSatisfied)
                {
                    AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route);

                    int cRequiredLandings = fXCLandingsMustBeFullStop ? cfr.cFullStopLandings + cfr.cFullStopNightLandings : cfr.cLandingsThisFlight;

                    if (al.DistanceForRoute() >= reqXCDistance && al.GetAirportList().Length >= 3 && cRequiredLandings >= 2)
                    {
                        miSoloLongCrossCountry.MatchFlightEvent(cfr);
                    }
                }
            }
        }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }
            // Normal currency
            fcPIC.AddRecentFlightEvents(cfr.dtFlight, cfr.PIC);
            if (cfr.PIC > 0)
            {
                fcLandings.AddRecentFlightEvents(cfr.dtFlight, cfr.cLandingsThisFlight);
            }

            fcDual.AddRecentFlightEvents(cfr.dtFlight, cfr.Dual);

            // If we aren't current above, we still want to count any landings or time spent as dual, solo, or DPIC with an Instructor on board.
            bool    fHasProficiencyCheck = false;
            decimal dPIC = 0.0M;
            bool    fInstructorOnBoard = false;

            cfr.ForEachEvent((cfp) =>
            {
                if (cfp.PropertyType.IsPICProficiencyCheck6158)
                {
                    fHasProficiencyCheck = true;
                }
                if (cfp.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropInstructorOnBoard && !cfp.IsDefaultValue)
                {
                    fInstructorOnBoard = true;    // instructor-on-board time only counts if you are acting as PIC
                }
                if (cfp.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropDutiesOfPIC && !cfp.IsDefaultValue)
                {
                    dPIC += cfp.DecValue;
                }
            });

            if (fHasProficiencyCheck)
            {
                fcProficiencyCheck.AddRecentFlightEvents(cfr.dtFlight, 1);
            }

            if (!fInstructorOnBoard)
            {
                dPIC = 0.0M;        // only counts if instructor on board.
            }
            if (cfr.Dual + dPIC > 0)
            {
                fcAlternateLandings.AddRecentFlightEvents(cfr.dtFlight, cfr.cLandingsThisFlight);
                fcAlternatePIC.AddRecentFlightEvents(cfr.dtFlight, Math.Min(cfr.Total, cfr.Dual + dPIC));
            }
        }
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            // 61.99
            miMinTime.AddEvent(cfr.Total);

            // 61.99(a)
            miMinInstruction.AddEvent(cfr.Dual);

            // 61.99(a)(1)
            if (cfr.cLandingsThisFlight >= 4 && cfr.Dual > 0)
            {
                AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route, true);
                if (al.MaxDistanceForRoute() >= 25.0)
                {
                    miXCFlight.AddEvent(cfr.Dual);
                }
            }

            if (cfr.idCatClassOverride == CatClassID)
            {
                // 61.99(a)(2)
                if (DateTime.Now.AddCalendarMonths(-2).CompareTo(cfr.dtFlight) <= 0)
                {
                    miTestPrep.AddEvent(cfr.Dual);
                }

                // 61.99(b)
                decimal soloTime = 0.0M;
                cfr.ForEachEvent(pf => { if (pf.PropertyType.IsSolo)
                                         {
                                             soloTime += pf.DecValue;
                                         }
                                 });
                miMinSolo.AddEvent(soloTime);
            }
        }
Exemple #10
0
 public void ExamineFlight(ExaminerFlightRow cfr)
 {
     cfr.ForEachEvent((cfp) =>
     {
         if (cfp.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropUASKnowledgeTest10773)
         {
             KnowledgeTest.AddRecentFlightEvents(cfr.dtFlight, 1);
         }
         if (cfp.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropUASTrainingCourse10774)
         {
             TrainingCourse.AddRecentFlightEvents(cfr.dtFlight, 1);
         }
         if (cfp.PropertyType.IsBFR && cfr.fIsRealAircraft)
         {
             BFR.AddRecentFlightEvents(cfr.dtFlight, 1);
         }
     });
 }
        public void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr.dtFlight.CompareTo(DateTime.Now.AddYears(-5)) < 0)
            {
                return;
            }

            fHasPICExperience = fHasPICExperience || (cfr.PIC + cfr.SIC > 0);

            // Alternative to having PIC experience is having a flight review in the prior year
            if (cfr.dtFlight.CompareTo(DateTime.Now.AddYears(-1)) > 0)
            {
                cfr.ForEachEvent((pe) =>
                {
                    if (pe.PropertyType.IsBFR)
                    {
                        fHasFlightReview = true;
                    }
                });
            }
        }
Exemple #12
0
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }

            // no provision for training devices.
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            // Must be a glider; motorgliders ("powered sailplanes") are subsets of gliders
            if (cfr.idCatClassOverride != CategoryClass.CatClassID.Glider)
            {
                return;
            }

            // Treat TMG time as if it were a training device.
            miTotal.AddTrainingEvent(cfr.Total, maxTMGTime, cfr.fMotorGlider);

            miDual.AddEvent(cfr.Dual);

            decimal soloTime           = 0.0M;
            bool    fInstructorOnBoard = false;
            decimal dutiesOfPICTime    = 0.0M;

            cfr.ForEachEvent(pf =>
            {
                if (pf.PropertyType.IsSolo)
                {
                    soloTime += pf.DecValue;
                }

                if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropInstructorOnBoard && !pf.IsDefaultValue)
                {
                    fInstructorOnBoard = true;    // instructor-on-board time only counts if you are acting as PIC
                }
                if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropDutiesOfPIC && !pf.IsDefaultValue)
                {
                    dutiesOfPICTime += pf.DecValue;
                }
            });

            if (fInstructorOnBoard)
            {
                soloTime += Math.Max(Math.Min(dutiesOfPICTime, cfr.Total - cfr.Dual), 0);    // dual received does NOT count as duties of PIC time here
            }
            miSolo.AddEvent(soloTime);
            miLandings.AddEvent(cfr.cLandingsThisFlight);

            if (!miCrossCountry.IsSatisfied)
            {
                AirportList al       = AirportListOfRoutes.CloneSubset(cfr.Route);
                double      distance = al.GetAirportList().Length > 1 ? al.DistanceForRoute() : 0.0;
                if ((soloTime > 0.0M && distance > minSoloXC) || (cfr.Dual > 0 && distance > minDualXC))
                {
                    miCrossCountry.MatchFlightEvent(cfr);
                }
            }
        }
Exemple #13
0
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            if (cfr == null)
            {
                throw new ArgumentNullException("cfr");
            }

            // no provision for training devices.
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            if (MatchesClassDual(cfr))
            {
                miMinDualInClass.AddEvent(cfr.Dual);
            }

            if (MatchesSoloOrTotalDual(cfr))
            {
                miMinTime.AddEvent(cfr.Total);

                decimal soloTime           = 0.0M;
                bool    fInstructorOnBoard = false;
                decimal dutiesOfPICTime    = 0.0M;
                cfr.ForEachEvent(pf => {
                    if (pf.PropertyType.IsSolo)
                    {
                        soloTime += pf.DecValue;
                    }

                    if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropInstructorOnBoard && !pf.IsDefaultValue)
                    {
                        fInstructorOnBoard = true;    // instructor-on-board time only counts if you are acting as PIC
                    }
                    if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropDutiesOfPIC && !pf.IsDefaultValue)
                    {
                        dutiesOfPICTime += pf.DecValue;
                    }
                });

                if (fInstructorOnBoard)
                {
                    soloTime += Math.Max(Math.Min(dutiesOfPICTime, cfr.Total - cfr.Dual), 0);    // dual received does NOT count as duties of PIC time here
                }
                if (soloTime > 0.0M)
                {
                    miMinSolo.AddEvent(soloTime);
                    miMinSoloXC.AddEvent(Math.Min(soloTime, cfr.XC));

                    if (cfr.cFullStopLandings >= 1 && !miMinSoloXCMinDist.IsSatisfied)
                    {
                        AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route);
                        if (al.GetAirportList().Length > 1 && al.DistanceForRoute() >= MinSoloDistance)
                        {
                            miMinSoloXCMinDist.MatchFlightEvent(cfr);
                        }
                    }
                }
            }
        }
Exemple #14
0
        public override void ExamineFlight(ExaminerFlightRow cfr)
        {
            bool fIsMatch = CatClassMatchesRatingSought(cfr.idCatClassOverride);
            bool fIsSim   = cfr.fIsCertifiedIFR && !cfr.fIsRealAircraft;

            if (!fIsMatch || !cfr.fIsCertifiedIFR)
            {
                return;
            }

            miTotal.AddTrainingEvent(Math.Min(cfr.Dual, cfr.fIsRealAircraft ? cfr.Total : cfr.GroundSim), JAASimSub, fIsSim);

            // Everything below here must be done in a real aircraft
            if (!cfr.fIsRealAircraft)
            {
                return;
            }

            miDual.AddEvent(cfr.Dual);
            miInstrumentDual.AddEvent(Math.Min(cfr.Dual, cfr.IMC + cfr.IMCSim));

            // Get solo time
            decimal soloTime = 0.0M;
            decimal instructorOnBoardTime = 0.0M;
            bool    fInstructorOnBoard    = false;
            decimal dutiesOfPICTime       = 0.0M;
            int     nightTakeoffs         = 0;

            cfr.ForEachEvent(pf =>
            {
                if (pf.PropertyType.IsSolo)
                {
                    soloTime += pf.DecValue;
                }
                if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropInstructorOnBoard && !pf.IsDefaultValue)
                {
                    fInstructorOnBoard = true;    // instructor-on-board time only counts if you are acting as PIC
                }
                if (pf.PropTypeID == (int)CustomPropertyType.KnownProperties.IDPropDutiesOfPIC && !pf.IsDefaultValue)
                {
                    dutiesOfPICTime += pf.DecValue;
                }
                if (pf.PropertyType.IsNightTakeOff)
                {
                    nightTakeoffs += pf.IntValue;
                }
            });

            if (fInstructorOnBoard)
            {
                instructorOnBoardTime = Math.Max(Math.Min(dutiesOfPICTime, cfr.Total - cfr.Dual), 0);    // dual received does NOT count as duties of PIC time here
            }
            decimal supervisedSolo = soloTime + Math.Min(instructorOnBoardTime, dutiesOfPICTime);

            miSolo.AddEvent(supervisedSolo);
            miSoloXC.AddEvent(Math.Min(supervisedSolo, cfr.XC));

            AirportList al = null;

            if (!miSoloLongXC.IsSatisfied && supervisedSolo > 0)
            {
                al = AirportListOfRoutes.CloneSubset(cfr.Route);

                if (al.DistanceForRoute() >= (double)miSoloLongXC.Threshold && al.GetAirportList().Length >= 3 && (cfr.cFullStopLandings + cfr.cFullStopNightLandings) >= 2)
                {
                    miSoloLongXC.MatchFlightEvent(cfr);
                }
            }

            // Night - optional
            if (cfr.Night > 0)
            {
                miNightTime.AddEvent(cfr.Night);
                decimal nightDual = Math.Min(cfr.Night, cfr.Dual);
                miNightDual.AddEvent(nightDual);
                miNightXC.AddEvent(Math.Min(nightDual, cfr.XC));
                if (soloTime > 0)
                {
                    miNightSoloTakeoffs.AddEvent(nightTakeoffs);
                    miNightSoloLandings.AddEvent(cfr.cFullStopNightLandings);
                }

                if (nightDual > 0)
                {
                    if (al == null)
                    {
                        al = AirportListOfRoutes.CloneSubset(cfr.Route);
                    }
                    if (al.DistanceForRoute() > (double)JAALongNightXCDistanceAirplane)
                    {
                        miNightLongXC.MatchFlightEvent(cfr);
                    }
                }
            }
        }