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(nameof(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.FlightProps.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, true); 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"); } // we are not counting training device time. if (!cfr.fIsRealAircraft) { return; } bool IsInMatchingCategory = CatClassMatchesRatingSought(cfr.idCatClassOverride); decimal XCPICTime = Math.Min(cfr.PIC, cfr.XC); decimal IMCTime = cfr.IMC + cfr.IMCSim; decimal IMCXCTime = Math.Min(IMCTime, cfr.XC); // 61.65(def)(1) - Look for cross-country time as PIC miMinXCTime.AddEvent(XCPICTime); if (IsInMatchingCategory) { miMinTimeInCategory.AddEvent(XCPICTime); } // 61.65(def)(2) - IMC time (total) miMinIMCTime.AddEvent(IMCTime); // 61.65(def)(2)(i) - recent test prep if (IsInMatchingCategory) { if (DateTime.Now.AddCalendarMonths(-2).CompareTo(cfr.dtFlight) <= 0) { miMinIMCTestPrep.AddEvent(Math.Min(cfr.Dual, IMCTime)); } if (cfr.cApproaches >= 3 && IMCXCTime > 0.0M) { AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route); if (al.DistanceForRoute() >= MinXCDistance) { miIMCXC.AddEvent(1.0M); miIMCXC.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.MilestoneProgress.MatchingXCFlightTemplate, cfr.dtFlight.ToShortDateString(), cfr.Route); miIMCXC.MatchingEventID = cfr.flightID; } } } }
public override void ExamineFlight(ExaminerFlightRow cfr) { if (cfr == null) { throw new ArgumentNullException(nameof(cfr)); } bool fIsMatch = CatClassMatchesRatingSought(cfr.idCatClassOverride); if (!fIsMatch || !cfr.fIsCertifiedIFR) { return; } // 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)); decimal soloTime = cfr.FlightProps.TotalTimeForPredicate(cfp => cfp.PropertyType.IsSolo); decimal nightTakeoffs = cfr.FlightProps.TotalCountForPredicate(cfp => cfp.PropertyType.IsNightTakeOff); if (soloTime > 0) { miNightSoloTakeoffs.AddEvent(nightTakeoffs); miNightSoloLandings.AddEvent(cfr.cFullStopNightLandings); } if (nightDual > 0) { AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route, true); if (al == null) { al = AirportListOfRoutes.CloneSubset(cfr.Route, true); } if (al.DistanceForRoute() > (double)JAALongNightXCDistanceAirplane) { miNightLongXC.MatchFlightEvent(cfr); } } } }
public override void ExamineFlight(ExaminerFlightRow cfr) { base.ExamineFlight(cfr); if (cfr == null) { throw new ArgumentNullException(nameof(cfr)); } if (!cfr.fIsRealAircraft) { return; } switch (cfr.idCatClassOverride) { case CategoryClass.CatClassID.Helicopter: case CategoryClass.CatClassID.ASEL: case CategoryClass.CatClassID.ASES: case CategoryClass.CatClassID.AMEL: case CategoryClass.CatClassID.AMES: miXCPIC.AddEvent(Math.Min(cfr.PIC, cfr.XC)); break; default: break; } if (cfr.IMC + cfr.IMCSim > 0 && cfr.Dual > 0 && CatClassMatchesRatingSought(cfr.idCatClassOverride)) { miIFRTrainingInCategory.AddEvent(Math.Min(cfr.Dual, cfr.IMC + cfr.IMCSim)); } if (cfr.cApproaches >= 2 && cfr.Dual > 0 && cfr.IMC + cfr.IMCSim > 0) { AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route); if (al.DistanceForRoute() >= MinXCDistance) { miXCDualXC.AddEvent(1.0M); miXCDualXC.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.MilestoneProgress.MatchingXCFlightTemplate, cfr.dtFlight.ToShortDateString(), cfr.Route); miXCDualXC.MatchingEventID = cfr.flightID; } } }
public override void ExamineFlight(ExaminerFlightRow cfr) { if (cfr == null) { throw new ArgumentNullException(nameof(cfr)); } decimal IMCTime = cfr.IMC + cfr.IMCSim; decimal imcTimeInSim = Math.Min(IMCTime, SimTimeRemaining); if (cfr.fIsFTD) { decimal FTDTimeToApply = Math.Min(imcTimeInSim, FTDTimeRemaining); miMinIMCTime.AddEvent(FTDTimeToApply); FTDTimeRemaining -= FTDTimeToApply; } else if (cfr.fIsATD) { miMinIMCTime.AddTrainingEvent(imcTimeInSim, MaxATDTime, true); } // Everything past this point only applies to real aircraft if (!cfr.fIsRealAircraft) { SimTimeRemaining = Math.Max(0, SimTimeRemaining - imcTimeInSim); return; } bool IsInMatchingCategory = CatClassMatchesRatingSought(cfr.idCatClassOverride); decimal XCPICTime = Math.Min(cfr.PIC, cfr.XC); decimal IMCXCTime = Math.Min(IMCTime, cfr.XC); // 61.65(def)(1) - Look for cross-country time as PIC miMinXCTime.AddEvent(XCPICTime); if (IsInMatchingCategory) { miMinTimeInCategory.AddEvent(XCPICTime); } // 61.65(def)(2) - IMC time (total) miMinIMCTime.AddEvent(IMCTime); decimal instTrainingTime = Math.Min(cfr.Dual, IMCTime); miInstrumentTraining.AddEvent(instTrainingTime); // 61.65(def)(2)(i) - recent test prep if (IsInMatchingCategory) { miMinIMCTestPrep.AddDecayableEvent(cfr.dtFlight, instTrainingTime, DateTime.Now.AddCalendarMonths(-2).CompareTo(cfr.dtFlight) <= 0); if (cfr.cApproaches >= 3 && IMCXCTime > 0.0M && instTrainingTime > 0) { AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route); if (al.DistanceForRoute() >= MinXCDistance) { miIMCXC.AddEvent(1.0M); miIMCXC.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.MilestoneProgress.MatchingXCFlightTemplate, cfr.dtFlight.ToShortDateString(), cfr.Route); miIMCXC.MatchingEventID = cfr.flightID; } } } }
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); } } }
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); } } } } }
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); } } } }
public override void ExamineFlight(ExaminerFlightRow cfr) { if (cfr == null) { throw new ArgumentNullException("cfr"); } DateTime dtFlight = cfr.dtFlight.Date; if (AutoDateRange) { StartDate = StartDate.EarlierDate(dtFlight); EndDate = EndDate.LaterDate(dtFlight); } // ignore anything not in a real aircraft or outside of our date range if (!cfr.fIsRealAircraft || dtFlight.CompareTo(StartDate) < 0 || dtFlight.CompareTo(EndDate) > 0) { return; } miFlightCount.AddEvent(1); string szDateKey = dtFlight.YMDString(); // Initialize the current streak, if needed if (FirstDayOfCurrentStreak == null || LastDayOfCurrentStreak == null) { FirstDayOfCurrentStreak = LastDayOfCurrentStreak = dtFlight; } // Extend the current streak if this flight is either on the first date or on a day before the first date; if it isn't one of those, then end the current streak if (dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.Date) == 0 || dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.AddDays(-1).Date) == 0) { FirstDayOfCurrentStreak = dtFlight; } else { FirstDayOfCurrentStreak = LastDayOfCurrentStreak = dtFlight; } int cDaysCurrentStreak = CurrentFlyingDayStreak; if (cDaysCurrentStreak > 1 && cDaysCurrentStreak > FlyingDayStreak) { FirstFlyingDayOfStreak = FirstDayOfCurrentStreak; LastFlyingDayOfStreak = LastDayOfCurrentStreak; } // Distinct flights on dates if (FlightDates.ContainsKey(szDateKey)) { FlightDates[szDateKey] = FlightDates[szDateKey] + 1; } else { FlightDates[szDateKey] = 1; } if (FlightDates[szDateKey] > MaxFlightsPerDay) { int cFlights = FlightDates[szDateKey]; MaxFlightsPerDay = cFlights; miMostFlightsInDay.Progress = cFlights; miMostFlightsInDay.MatchingEventText = String.Format(CultureInfo.InvariantCulture, Resources.Achievements.RecentAchievementMostFlightsInDay, cFlights, cfr.dtFlight); miMostFlightsInDay.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMin = cfr.dtFlight, DateMax = cfr.dtFlight }; } // Longest flight if (cfr.Total > LongestFlightLength) { LongestFlightLength = cfr.Total; miLongestFlight.Progress = 1; miLongestFlight.MatchingEventID = cfr.flightID; miLongestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsLongestFlight, cfr.Total, dtFlight); } // Distinct aircraft/models DistinctAircraft.Add(cfr.idAircraft); DistinctModels.Add(cfr.idModel); DistinctICAO.Add(cfr.szFamily); // Furthest Flight & airport computations. AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route, true); double distance = al.DistanceForRoute(); if (distance > FurthestFlightDistance) { FurthestFlightDistance = distance; miFurthestFlight.Progress = 1; miFurthestFlight.MatchingEventID = cfr.flightID; miFurthestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsFurthestFlight, distance, dtFlight); } int cUniqueAirports = 0; HashSet <string> hsThisFlight = new HashSet <string>(); foreach (airport ap in al.UniqueAirports) { // Dedupe as we go based on latitude/longitude, ignoring non-ports. // We don't actually need the facility name here - so we can just round off the latitude/longitude and distinguish by type code. // Note: this can differ slightly from Visited Airports counts because for achievements, we're ignoring flights in training devices; visited airports doesn't ignore them. if (ap.IsPort) { string szHash = ap.GeoHashKey; if (!Airports.Contains(szHash)) { Airports.Add(ap.GeoHashKey); cUniqueAirports++; } hsThisFlight.Add(szHash); } } int cAirportsThisFlight = hsThisFlight.Count; if (cAirportsThisFlight > MostAirportsFlightCount) { MostAirportsFlightCount = cAirportsThisFlight; miMostAirportsFlight.MatchingEventID = cfr.flightID; miMostAirportsFlight.Progress = 1; miMostAirportsFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsAirportsOnFlight, cAirportsThisFlight, dtFlight.ToShortDateString()); miMostAirportsFlight.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMax = dtFlight, DateMin = dtFlight }; } }
public override void ExamineFlight(ExaminerFlightRow cfr) { if (cfr == null) { throw new ArgumentNullException("cfr"); } DateTime dtFlight = cfr.dtFlight.Date; // ignore anything not in a real aircraft or outside of our date range if (!cfr.fIsRealAircraft || dtFlight.CompareTo(StartDate) < 0 || dtFlight.CompareTo(EndDate) > 0) { return; } string szDateKey = dtFlight.YMDString(); // Initialize the current streak, if needed if (FirstDayOfCurrentStreak == null || LastDayOfCurrentStreak == null) { FirstDayOfCurrentStreak = LastDayOfCurrentStreak = dtFlight; } // Extend the current streak if this flight is either on the first date or on a day before the first date; if it isn't one of those, then end the current streak if (dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.Date) == 0 || dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.AddDays(-1).Date) == 0) { FirstDayOfCurrentStreak = dtFlight; } else { FirstDayOfCurrentStreak = LastDayOfCurrentStreak = dtFlight; } int cDaysCurrentStreak = CurrentFlyingDayStreak; if (cDaysCurrentStreak > 1 && cDaysCurrentStreak > FlyingDayStreak) { FirstFlyingDayOfStreak = FirstDayOfCurrentStreak; LastFlyingDayOfStreak = LastDayOfCurrentStreak; } // Distinct flights on dates if (FlightDates.ContainsKey(szDateKey)) { FlightDates[szDateKey] = FlightDates[szDateKey] + 1; } else { FlightDates[szDateKey] = 1; } if (FlightDates[szDateKey] > MaxFlightsPerDay) { int cFlights = FlightDates[szDateKey]; MaxFlightsPerDay = cFlights; miMostFlightsInDay.Progress = cFlights; miMostFlightsInDay.MatchingEventText = String.Format(CultureInfo.InvariantCulture, Resources.Achievements.RecentAchievementMostFlightsInDay, cFlights, cfr.dtFlight); miMostFlightsInDay.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMin = cfr.dtFlight, DateMax = cfr.dtFlight }; } // Longest flight if (cfr.Total > LongestFlightLength) { LongestFlightLength = cfr.Total; miLongestFlight.Progress = 1; miLongestFlight.MatchingEventID = cfr.flightID; miLongestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsLongestFlight, cfr.Total, dtFlight); } // Distinct aircraft/models DistinctAircraft.Add(cfr.idAircraft); DistinctModels.Add(cfr.idModel); DistinctICAO.Add(cfr.szFamily); // Furthest Flight & airport computations. AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route); double distance = al.DistanceForRoute(); if (distance > FurthestFlightDistance) { FurthestFlightDistance = distance; miFurthestFlight.Progress = 1; miFurthestFlight.MatchingEventID = cfr.flightID; miFurthestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsFurthestFlight, distance, dtFlight); } int cUniqueAirports = al.UniqueAirports.Count(); foreach (airport ap in al.UniqueAirports) { if (ap.IsPort) { // Dedupe as we go - do the K-hack check; if the K version is in the AirportListOfRoutes, use that. I.e., just pre-pend a "K" to ANY three-letter airport code. if (ap.Code.Length == 3) { Airports.Add("K" + ap.Code); } else { Airports.Add(ap.Code); } } } if (cUniqueAirports > MostAirportsFlightCount) { MostAirportsFlightCount = cUniqueAirports; miMostAirportsFlight.Progress = 1; miMostAirportsFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsAirportsOnFlight, cUniqueAirports, dtFlight.ToShortDateString()); miMostAirportsFlight.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMax = dtFlight, DateMin = dtFlight }; } }
public override void ExamineFlight(ExaminerFlightRow cfr) { if (cfr == null) { throw new ArgumentNullException(nameof(cfr)); } DateTime dtFlight = cfr.dtFlight.Date; if (AutoDateRange) { StartDate = StartDate.EarlierDate(dtFlight); EndDate = EndDate.LaterDate(dtFlight); } // ignore anything not in a real aircraft or outside of our date range if (!cfr.fIsRealAircraft || dtFlight.CompareTo(StartDate) < 0 || dtFlight.CompareTo(EndDate) > 0) { return; } miFlightCount.AddEvent(1); string szDateKey = dtFlight.YMDString(); // Initialize the current streak, if needed if (FirstDayOfCurrentStreak == null || LastDayOfCurrentStreak == null) { FirstDayOfCurrentStreak = LastDayOfCurrentStreak = dtFlight; } // Extend the current streak if this flight is either on the first date or on a day before the first date; if it isn't one of those, then end the current streak FirstDayOfCurrentStreak = dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.Date) == 0 || dtFlight.CompareTo(FirstDayOfCurrentStreak.Value.AddDays(-1).Date) == 0 ? (DateTime?)dtFlight : (LastDayOfCurrentStreak = dtFlight); int cDaysCurrentStreak = CurrentFlyingDayStreak; if (cDaysCurrentStreak > 1 && cDaysCurrentStreak > FlyingDayStreak) { FirstFlyingDayOfStreak = FirstDayOfCurrentStreak; LastFlyingDayOfStreak = LastDayOfCurrentStreak; } // Distinct flights on dates FlightDates[szDateKey] = FlightDates.ContainsKey(szDateKey) ? FlightDates[szDateKey] + 1 : 1; if (FlightDates[szDateKey] > MaxFlightsPerDay) { int cFlights = FlightDates[szDateKey]; MaxFlightsPerDay = cFlights; miMostFlightsInDay.Progress = cFlights; miMostFlightsInDay.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementMostFlightsInDay, cFlights, cfr.dtFlight); miMostFlightsInDay.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMin = cfr.dtFlight, DateMax = cfr.dtFlight }; } FlightLandings[szDateKey] = FlightLandings.ContainsKey(szDateKey) ? FlightLandings[szDateKey] + cfr.cLandingsThisFlight : cfr.cLandingsThisFlight; if (FlightLandings[szDateKey] > MaxLandingsPerDay) { int cLandings = FlightLandings[szDateKey]; MaxLandingsPerDay = cLandings; miMostLandingsInDay.Progress = cLandings; miMostLandingsInDay.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementMostLandingsInDay, cLandings, cfr.dtFlight); miMostLandingsInDay.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMin = cfr.dtFlight, DateMax = cfr.dtFlight }; } // Longest flight if (cfr.Total > LongestFlightLength) { LongestFlightLength = cfr.Total; miLongestFlight.Progress = 1; miLongestFlight.MatchingEventID = cfr.flightID; miLongestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsLongestFlight, cfr.Total, dtFlight); } // Distinct aircraft/models DistinctAircraft.Add(cfr.idAircraft); DistinctModels.Add(cfr.idModel); DistinctICAO.Add(cfr.szFamily); // Furthest Flight & airport computations. AirportList al = AirportListOfRoutes.CloneSubset(cfr.Route, true); double distance = al.DistanceForRoute(); if (distance > FurthestFlightDistance) { FurthestFlightDistance = distance; miFurthestFlight.Progress = 1; miFurthestFlight.MatchingEventID = cfr.flightID; miFurthestFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsFurthestFlight, distance, dtFlight); } int cAirportsThisFlight = MatchAirports(al.UniqueAirports); if (cAirportsThisFlight > MostAirportsFlightCount) { MostAirportsFlightCount = cAirportsThisFlight; miMostAirportsFlight.MatchingEventID = cfr.flightID; miMostAirportsFlight.Progress = 1; miMostAirportsFlight.MatchingEventText = String.Format(CultureInfo.CurrentCulture, Resources.Achievements.RecentAchievementsAirportsOnFlight, cAirportsThisFlight, dtFlight.ToShortDateString()); miMostAirportsFlight.Query = new FlightQuery(Username) { DateRange = FlightQuery.DateRanges.Custom, DateMax = dtFlight, DateMin = dtFlight }; } fs100.ExamineFlight(cfr); fs1000.ExamineFlight(cfr); }