/// <summary>
 /// Displays a "Sign and review next" button if:
 /// a) the instructor is specified
 /// b) the specified instructor is the signed-in user.
 /// c) the flight to sign is specified
 /// d) there are multiple flights pending signature for that user
 /// </summary>
 public void PrepSignAndNext()
 {
     btnSignAndNext.Visible = CFIProfile != null &&
                              CFIProfile.UserName.CompareCurrentCultureIgnoreCase(Page.User.Identity.Name) == 0 &&
                              m_le != null &&
                              LogbookEntryBase.PendingSignaturesForStudent(CFIProfile, Profile.GetUser(m_le.User)).Count() > 1;
 }
示例#2
0
        private void CheckTimeIssues(LogbookEntryBase le)
        {
            if (currentAircraft.InstanceType != AircraftInstanceTypes.RealAircraft)
            {
                return;
            }

            int totalMinutes = le.TotalFlightTime.ToMinutes();

            AddConditionalIssue(le.CrossCountry.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesXCGreaterThanTotal);
            AddConditionalIssue(le.Nighttime.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesNightGreaterThanTotal);
            AddConditionalIssue(le.SimulatedIFR.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSimIFRGreaterThanTotal);
            AddConditionalIssue(le.IMC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesIMCGreaterThanTotal);
            AddConditionalIssue(le.IMC.ToMinutes() + le.SimulatedIFR.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSimPlusIMCGreaterThanTotal);
            AddConditionalIssue(le.Dual.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesDualGreaterThanTotal);
            AddConditionalIssue(le.CFI.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesCFIGreaterThanTotal);
            AddConditionalIssue(le.SIC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSICGreaterThanTotal);
            AddConditionalIssue(le.PIC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesPICGreaterThanTotal);

            foreach (CustomFlightProperty cfp in le.CustomProperties)
            {
                AddConditionalIssue(cfp.PropertyType.Type == CFPPropertyType.cfpDecimal && !cfp.PropertyType.IsBasicDecimal && !cfp.PropertyType.IsNoSum && !hsExcludedTimeProps.Contains(cfp.PropTypeID) &&
                                    cfp.DecValue.ToMinutes() > totalMinutes,
                                    LintOptions.TimeIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningPropertyGreaterThanTotal, cfp.PropertyType.Title));
            }
        }
    /// <summary>
    /// Updates the starting flight with the specified value in the specified column
    /// </summary>
    /// <param name="sfc">The column to read</param>
    /// <param name="sf">The target starting flight</param>
    /// <param name="value">The value</param>
    protected void SetValueForColumn(StartingFlightColumn sfc, LogbookEntryBase sf, Decimal value)
    {
        if (sf == null)
        {
            throw new ArgumentNullException("sf");
        }
        switch (sfc)
        {
        case StartingFlightColumn.CFI:
            sf.CFI = value;
            break;

        case StartingFlightColumn.SIC:
            sf.SIC = value;
            break;

        case StartingFlightColumn.PIC:
            sf.PIC = value;
            break;

        case StartingFlightColumn.Total:
            sf.TotalFlightTime = value;
            break;
        }
    }
示例#4
0
        /// <summary>
        /// Performs the computation on the milestones to see what progress has been made for each.  We MUST use LogbookEntryDisplays, so we override the base class (which uses ExaminerFlightRow)
        /// </summary>
        /// <returns>The resulting milestones.</returns>
        /// <exception cref="MyFlightbookException"></exception>
        public override Collection <MilestoneItem> Refresh()
        {
            if (String.IsNullOrEmpty(Username))
            {
                throw new MyFlightbookException("Cannot compute milestones on an empty user!");
            }

            StringBuilder sbRoutes = new StringBuilder();
            Profile       pf       = Profile.GetUser(Username);

            IList <LogbookEntryDisplay> lst = LogbookEntryDisplay.GetFlightsForQuery(LogbookEntryBase.QueryCommand(new FlightQuery(Username)), Username, string.Empty, System.Web.UI.WebControls.SortDirection.Descending, pf.UsesHHMM, pf.UsesUTCDateOfFlight);

            // Set up the airport list once for DB efficiency
            foreach (LogbookEntryDisplay led in lst)
            {
                sbRoutes.AppendFormat(CultureInfo.InvariantCulture, "{0} ", led.Route);
            }
            AirportListOfRoutes = new AirportList(sbRoutes.ToString());

            IDictionary <string, CannedQuery> d = UserQueries;

            foreach (LogbookEntryDisplay led in lst)
            {
                foreach (CustomRatingProgressItem cpi in ProgressItems)
                {
                    cpi.ExamineFlight(led, d);
                }
            }
            ;

            return(Milestones);
        }
示例#5
0
        protected void btnCheckAll_Click(object sender, EventArgs e)
        {
            UInt32 selectedOptions = SelectedOptions;

            if (selectedOptions == 0)
            {
                lblErr.Text = Resources.FlightLint.errNoOptionsSelected;
                return;
            }

            FlightQuery fq = new FlightQuery(Page.User.Identity.Name);

            if (mfbDateLastCheck.Date.HasValue())
            {
                fq.DateRange = FlightQuery.DateRanges.Custom;
                fq.DateMin   = mfbDateLastCheck.Date;
            }
            DBHelperCommandArgs            dbhq = LogbookEntryBase.QueryCommand(fq, fAsc: true);
            IEnumerable <LogbookEntryBase> rgle = LogbookEntryDisplay.GetFlightsForQuery(dbhq, Page.User.Identity.Name, "Date", SortDirection.Ascending, false, false);

            BindFlights(new FlightLint().CheckFlights(rgle, Page.User.Identity.Name, selectedOptions, mfbDateLastCheck.Date), rgle.Count());

            Response.Cookies[szCookieLastCheck].Value   = DateTime.Now.YMDString();
            Response.Cookies[szCookieLastCheck].Expires = DateTime.Now.AddYears(5);
        }
示例#6
0
        private void CheckDutyIssues(LogbookEntryBase le, CustomFlightProperty cfpBlockIn, CustomFlightProperty cfpBlockOut)
        {
            // Look for a new duty start when a prior period is still open or a duty end when a prior period is NOT open
            CustomFlightProperty cfpDutyStart       = le.CustomProperties[CustomPropertyType.KnownProperties.IDPropDutyStart];
            CustomFlightProperty cfpFlightDutyStart = le.CustomProperties[CustomPropertyType.KnownProperties.IDPropFlightDutyTimeStart];
            CustomFlightProperty cfpDutyEnd         = le.CustomProperties[CustomPropertyType.KnownProperties.IDPropDutyEnd];
            CustomFlightProperty cfpFlightDutyEnd   = le.CustomProperties[CustomPropertyType.KnownProperties.IDPropFlightDutyTimeEnd];

            // Starting a new duty period or flight duty period while a prior duty period is open
            AddConditionalIssue(dutyStart != null && dutyStart.HasValue && cfpDutyStart != null, LintOptions.DateTimeIssues, Resources.FlightLint.warningNewDutyStart);
            AddConditionalIssue(flightDutyStart != null && flightDutyStart.HasValue && cfpFlightDutyStart != null, LintOptions.DateTimeIssues, Resources.FlightLint.warningNewFlightDutyStart);

            // Starting a new duty period or flight duty period prior to the close of the prior one.
            AddConditionalIssue(dutyEnd != null && dutyEnd.HasValue && cfpDutyStart != null && cfpDutyStart.DateValue.CompareTo(dutyEnd.Value) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDutyStartPriorToPreviousDutyEnd);
            AddConditionalIssue(flightDutyEnd != null && flightDutyEnd.HasValue && cfpFlightDutyStart != null && cfpFlightDutyStart.DateValue.CompareTo(flightDutyEnd.Value) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightDutyStartPriorToPreviousFlightDutyEnd);

            // Ending a duty period or flight duty period that has no corresponding start.
            AddConditionalIssue(dutyStart == null && cfpDutyStart == null && cfpDutyEnd != null, LintOptions.DateTimeIssues, Resources.FlightLint.warningNewDutyEndNoStart);
            AddConditionalIssue(flightDutyStart == null && cfpFlightDutyStart == null && cfpFlightDutyEnd != null, LintOptions.DateTimeIssues, Resources.FlightLint.warningNewFlightDutyEndNoStart);

            DateTime bogusDate = le.FlightStart.LaterDate(le.FlightEnd)
                                 .LaterDate(le.EngineStart).LaterDate(le.EngineEnd)
                                 .LaterDate(cfpBlockIn == null ? DateTime.MinValue : cfpBlockIn.DateValue).LaterDate(cfpBlockOut == null ? DateTime.MinValue : cfpBlockOut.DateValue)
                                 .LaterDate(cfpDutyStart == null ? DateTime.MinValue : cfpDutyStart.DateValue).LaterDate(cfpDutyEnd == null ? DateTime.MinValue : cfpDutyEnd.DateValue)
                                 .LaterDate(cfpFlightDutyStart == null ? DateTime.MinValue : cfpFlightDutyStart.DateValue).LaterDate(cfpFlightDutyEnd == null ? DateTime.MinValue : cfpFlightDutyEnd.DateValue);

            AddConditionalIssue(bogusDate.CompareTo(DateTime.UtcNow.AddDays(5)) > 0, LintOptions.DateTimeIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningTimesSuspectTime, bogusDate.UTCDateFormatString()));

            UpdateDutyPeriods(cfpDutyStart, cfpFlightDutyStart, cfpDutyEnd, cfpFlightDutyEnd);
        }
示例#7
0
        private void CheckDateTimeIssues(LogbookEntryBase le)
        {
            CustomFlightProperty cfpBlockOut = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockOut);
            CustomFlightProperty cfpBlockIn  = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockIn);

            // Block out after block in
            AddConditionalIssue(cfpBlockIn != null && cfpBlockOut != null && cfpBlockOut.DateValue.CompareTo(cfpBlockIn.DateValue) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateTimeInvalidBlock);

            bool fHasEngineStart = le.EngineStart.HasValue();
            bool fHasEngineEnd   = le.EngineEnd.HasValue();
            bool fHasFlightStart = le.FlightStart.HasValue();
            bool fHasFlightEnd   = le.FlightEnd.HasValue();

            // Engine start must be before flight.  Can be after block out, but not before block in
            AddConditionalIssue(fHasEngineStart && fHasFlightStart && le.FlightStart.CompareTo(le.EngineStart) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateEngineAfterFlight);
            AddConditionalIssue(fHasEngineStart && fHasFlightEnd && le.FlightEnd.CompareTo(le.EngineStart) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndBeforeEngineStart);

            AddConditionalIssue(fHasEngineStart && cfpBlockIn != null && cfpBlockIn.DateValue.CompareTo(le.EngineStart) <= 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineStartAfterBlockIn);

            // Flight start must be after engine start (checked above) and after block out
            AddConditionalIssue(fHasFlightStart && cfpBlockOut != null && le.FlightStart.CompareTo(cfpBlockOut.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateBlockAfterFlight);

            // Flight end must be after engine/flight start (checked in regular validation), after block out, and before block in
            AddConditionalIssue(fHasFlightEnd && cfpBlockOut != null && le.FlightEnd.CompareTo(cfpBlockOut.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndBeforeBlockOut);
            AddConditionalIssue(fHasFlightEnd && cfpBlockIn != null && le.FlightEnd.CompareTo(cfpBlockIn.DateValue) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndAfterBlockIn);
            AddConditionalIssue(fHasFlightEnd && fHasEngineEnd && le.FlightEnd.CompareTo(le.EngineEnd) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndAfterEngineEnd);

            AddConditionalIssue(fHasEngineEnd && cfpBlockIn != null && le.EngineEnd.CompareTo(cfpBlockIn.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineEndBeforeBlockIn);

            CheckFlightLengthIssues(le);

            // Look for issues with sequential flights
            CheckSequentialFlightIssues(le);
        }
示例#8
0
        private void CheckMiscIssues(LogbookEntryBase le)
        {
            foreach (CustomFlightProperty cfp in le.CustomProperties)
            {
                if (cfp.PropertyType.IsExcludedFromMRU)
                {
                    AddConditionalIssue(seenCheckrides.Contains(cfp.PropTypeID), LintOptions.MiscIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningMiscMultipleRedundantCheckrides, cfp.PropertyType.Title));
                    seenCheckrides.Add(cfp.PropTypeID);
                }
            }

            int maxDescribedLandings = 0;

            le.CustomProperties.ForEachEvent((cfp) => { if (cfp.PropertyType.IsLanding)
                                                        {
                                                            maxDescribedLandings = Math.Max(maxDescribedLandings, cfp.IntValue);
                                                        }
                                             });
            AddConditionalIssue(maxDescribedLandings > le.Landings, LintOptions.MiscIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningMoreDescribedLandingsThanTotal, le.Landings));

            AddConditionalIssue(le.Dual > 0 && !le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropInstructorName) && le.CFISignatureState == LogbookEntryBase.SignatureState.None, LintOptions.MiscIssues, Resources.FlightLint.warningDualLoggedButNoCFIName);

            LogbookEntryBase leDefault = new LogbookEntry()
            {
                Date = le.Date, AircraftID = le.AircraftID, User = le.User
            };

            AddConditionalIssue(le.IsEqualTo(leDefault), LintOptions.MiscIssues, Resources.FlightLint.warningFlightHasNoData);

            AddConditionalIssue(previousFlight != null && le.IsEqualTo(previousFlight), LintOptions.MiscIssues, Resources.FlightLint.warningMiscDuplicateFlight);
        }
        protected void CropInRange(LogbookEntryBase le, string clipMin, string clipMax)
        {
            if (le == null)
            {
                throw new ArgumentNullException(nameof(le));
            }
            int dataStart = (int)Math.Truncate((Convert.ToDouble(clipMin, CultureInfo.InvariantCulture) / DataCropRange) * Math.Max(DataPointCount - 1, 0));
            int dataEnd   = (int)Math.Truncate((Convert.ToDouble(clipMax, CultureInfo.InvariantCulture) / DataCropRange) * Math.Max(DataPointCount - 1, 0));

            if (dataEnd <= dataStart)
            {
                dataEnd = dataStart + 1;
            }

            if ((dataStart == 0 && dataEnd == 0) || dataEnd >= DataPointCount)
            {
                ResetCrop(le);
                return;
            }
            TelemetryReference tr = le.Telemetry;

            tr.MetaData.DataStart = dataStart;
            tr.MetaData.DataEnd   = dataEnd;
            using (FlightData fd = new FlightData())
            {
                fd.ParseFlightData(le);
                tr.RecalcGoogleData(fd);
            }
            tr.Commit();
            Response.Redirect(Request.RawUrl);
        }
示例#10
0
 /// <summary>
 /// Returns the Uri to view a flight (useful for FB/Twitter/Etc.)
 /// </summary>
 /// <param name="le">The flight to be shared</param>
 /// <param name="szHost">Hostname (if not provided, uses current brand)</param>
 /// <returns></returns>
 public static Uri ShareFlightUri(LogbookEntryBase le, string szHost = null)
 {
     if (le == null)
     {
         throw new ArgumentNullException("le");
     }
     return(String.Format(CultureInfo.InvariantCulture, "~/Public/ViewPublicFlight.aspx/{0}?v={1}", le.FlightID, (new Random()).Next(10000)).ToAbsoluteURL("https", szHost ?? Branding.CurrentBrand.HostName));
 }
示例#11
0
        private void CheckTimeIssues(LogbookEntryBase le)
        {
            if (currentAircraft.InstanceType != AircraftInstanceTypes.RealAircraft)
            {
                return;
            }

            int totalMinutes = le.TotalFlightTime.ToMinutes();

            AddConditionalIssue(le.CrossCountry.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesXCGreaterThanTotal);
            AddConditionalIssue(le.Nighttime.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesNightGreaterThanTotal);
            AddConditionalIssue(le.SimulatedIFR.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSimIFRGreaterThanTotal);
            AddConditionalIssue(le.IMC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesIMCGreaterThanTotal);
            AddConditionalIssue(le.IMC.ToMinutes() + le.SimulatedIFR.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSimPlusIMCGreaterThanTotal);
            AddConditionalIssue(le.Dual.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesDualGreaterThanTotal);
            AddConditionalIssue(le.CFI.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesCFIGreaterThanTotal);
            AddConditionalIssue(le.SIC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesSICGreaterThanTotal);
            AddConditionalIssue(le.PIC.ToMinutes() > totalMinutes, LintOptions.TimeIssues, Resources.FlightLint.warningTimesPICGreaterThanTotal);
            AddConditionalIssue(le.PIC.ToMinutes() + le.SIC.ToMinutes() + le.CFI.ToMinutes() + le.Dual.ToMinutes() == 0 && totalMinutes > 0, LintOptions.TimeIssues, Resources.FlightLint.warningTotalTimeButNoOtherTime);

            CustomFlightProperty cfpSolo = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDPropSolo);

            if (cfpSolo != null)
            {
                int soloMinutes = cfpSolo.DecValue.ToMinutes();
                AddConditionalIssue(soloMinutes > le.PIC.ToMinutes(), LintOptions.TimeIssues, Resources.FlightLint.warningSoloTimeExceedsPICTime);
                AddConditionalIssue(soloMinutes > totalMinutes - le.SIC.ToMinutes() - le.CFI.ToMinutes() - le.Dual.ToMinutes(), LintOptions.TimeIssues, Resources.FlightLint.warningSoloTimeWithNonSoloTime);
            }

            foreach (CustomFlightProperty cfp in le.CustomProperties)
            {
                AddConditionalIssue(cfp.PropertyType.Type == CFPPropertyType.cfpDecimal && !cfp.PropertyType.IsBasicDecimal && !cfp.PropertyType.IsNoSum && !hsExcludedTimeProps.Contains(cfp.PropTypeID) &&
                                    cfp.DecValue.ToMinutes() > totalMinutes,
                                    LintOptions.TimeIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningPropertyGreaterThanTotal, cfp.PropertyType.Title));
            }


            CustomFlightProperty cfpTachStart = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDPropTachStart);
            CustomFlightProperty cfpTachEnd   = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDPropTachEnd);

            AddConditionalIssue(cfpTachStart != null && cfpTachEnd != null && cfpTachEnd.DecValue < cfpTachStart.DecValue, LintOptions.TimeIssues, Resources.FlightLint.warningTachEndBeforeTachStart);

            if (le.TotalFlightTime > 0)
            {
                // Look for block time or engine time that varies significantly from total time UNLESS hobbs is present; if so, compare hobbs to that.  Ditto tach, if tach is of by more than 30%.
                const decimal maxHobbsVariation = 0.2M;
                const decimal maxBlockVariation = 0.1M;

                CustomFlightProperty cfpBlockOut = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockOut);
                CustomFlightProperty cfpBlockIn  = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockIn);

                bool    fHasHobbs          = le.HobbsEnd > 0 && le.HobbsStart > 0 && le.HobbsEnd > le.HobbsStart;
                decimal hobbsVariation     = Math.Abs(le.HobbsEnd - le.HobbsStart - le.TotalFlightTime);
                decimal blockTimeVariation = (cfpBlockIn != null && cfpBlockOut != null) ? Math.Abs((decimal)cfpBlockIn.DateValue.Subtract(cfpBlockOut.DateValue).TotalHours - le.TotalFlightTime) : 0;
                AddConditionalIssue(fHasHobbs && hobbsVariation > maxHobbsVariation, LintOptions.TimeIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningHobbsAndTotalsDiffer, hobbsVariation.ToHHMM()));
                AddConditionalIssue(!fHasHobbs && blockTimeVariation > maxBlockVariation, LintOptions.TimeIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningBlockAndTotalsDiffer, blockTimeVariation.ToHHMM()));
            }
        }
示例#12
0
        /// <summary>
        /// Updates recent flights for the specified flight, removing it if it is no longer public
        /// </summary>
        /// <param name="le"></param>
        public static void RefreshForFlight(LogbookEntryBase le)
        {
            FlightStats fs = CachedStats();

            if (fs != null && fs.RecentPublicFlights != null && !le.fIsPublic)
            {
                fs.m_lstFlights.RemoveAll(l => l.FlightID == le.FlightID);
            }
        }
示例#13
0
        private void CheckIFRIssues(LogbookEntryBase le)
        {
            AddConditionalIssue(le.Approaches > 0 && !le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropApproachName) && !ApproachDescription.ExtractApproaches(le.Comment).Any(), LintOptions.IFRIssues, Resources.FlightLint.warningIFRNoApproachDescription);

            AddConditionalIssue(le.SimulatedIFR > 0 && le.Dual == 0 && currentAircraft.InstanceType == AircraftInstanceTypes.RealAircraft &&
                                !le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropSafetyPilotName) &&
                                !le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropNameOfExaminer), LintOptions.IFRIssues, Resources.FlightLint.warningIFRNoSafetyPilot);
            AddConditionalIssue((le.Approaches > 0 || le.fHoldingProcedures) && le.SimulatedIFR + le.IMC == 0, LintOptions.IFRIssues, Resources.FlightLint.warningIFRApproachesButNoIFR);
        }
 protected void btnSignAndNext_Click(object sender, EventArgs e)
 {
     if (SignFlight())
     {
         List <LogbookEntryBase> lst = new List <LogbookEntryBase>(LogbookEntryBase.PendingSignaturesForStudent(CFIProfile, Profile.GetUser(m_le.User)));
         lst.RemoveAll(leb => leb.FlightID == m_le.FlightID);
         SigningFinished?.Invoke(this, new LogbookEventArgs(m_le.FlightID, lst.Any() ? lst[0].FlightID : LogbookEntryCore.idFlightNone));
     }
 }
示例#15
0
        private void CheckAirportIssues(LogbookEntryBase le)
        {
            IEnumerable <string> rgCodes = airport.SplitCodes(le.Route);

            foreach (string szCode in rgCodes)
            {
                if (szCode.StartsWith(airport.ForceNavaidPrefix, StringComparison.CurrentCultureIgnoreCase))
                {
                    continue;
                }

                if (szCode.CompareCurrentCultureIgnoreCase("LOCAL") == 0 || szCode.CompareCurrentCultureIgnoreCase("LCL") == 0)
                {
                    AddIssue(LintOptions.AirportIssues, Resources.FlightLint.warningAirportLocal);
                    continue;
                }

                airport ap = alSubset.GetAirportByCode(szCode);

                if (ap == null)
                {
                    AddIssue(LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportNotFound, szCode));
                }
                else
                {
                    AddConditionalIssue((currentCatClassID == CategoryClass.CatClassID.AMEL || currentCatClassID == CategoryClass.CatClassID.ASEL) && ap.IsSeaport, LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportLandPlaneAtSeaport, szCode));
                    AddConditionalIssue(CategoryClass.IsAirplane(currentCatClassID) && ap.FacilityTypeCode == "H", LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportAirplaneAtHeliport, szCode));
                }
            }

            // Sanity check for speed
            if (le.TotalFlightTime > 0)
            {
                double dist  = alSubset.DistanceForRoute();
                double speed = dist / (double)le.TotalFlightTime;

                AddConditionalIssue(speed > (currentModel.EngineType == MakeModel.TurbineLevel.Piston ? 500 : 1000), LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportUnlikelyImpliedSpeed, speed));
            }

            // Look for missing night takeoffs or landings
            if (rgCodes.Any())
            {
                airport apDep = alSubset.GetAirportByCode(rgCodes.ElementAt(0));
                airport apArr = alSubset.GetAirportByCode(rgCodes.ElementAt(rgCodes.Count() - 1));
                if (apDep != null)
                {
                    AddConditionalIssue(le.FlightStart.HasValue() && !le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropNightTakeoff) &&
                                        new SolarTools.SunriseSunsetTimes(le.FlightStart, apDep.LatLong.Latitude, apDep.LatLong.Longitude).IsFAANight, LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportMissingNightTakeoff, apDep.Code, le.FlightStart.UTCFormattedStringOrEmpty(false)));
                }
                if (apArr != null)
                {
                    AddConditionalIssue(le.FlightEnd.HasValue() && le.NightLandings == 0 &&
                                        new SolarTools.SunriseSunsetTimes(le.FlightEnd, apArr.LatLong.Latitude, apArr.LatLong.Longitude).IsFAANight, LintOptions.AirportIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningAirportMissingNightLanding, apArr.Code, le.FlightEnd.UTCFormattedStringOrEmpty(false)));
                }
            }
        }
示例#16
0
        public CloudAhoyPostFileMetaData(LogbookEntryBase le) : this()
        {
            if (le == null)
            {
                throw new ArgumentNullException("le");
            }

            tail    = le.TailNumDisplay;
            remarks = le.Comment;
        }
        protected void mfbFlightContextMenu_DeleteFlight(object sender, LogbookEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException(nameof(e));
            }

            LogbookEntryBase.FDeleteEntry(e.FlightID, Page.User.Identity.Name);
            Response.Redirect(TargetPage);
        }
    /// <summary>
    /// Initializes the specified starting flight with the values of the decimal edits in the row
    /// </summary>
    /// <param name="sf">The starting flight</param>
    /// <param name="iRow">The row</param>
    protected void FromRow(LogbookEntryBase sf, int iRow)
    {
        int iCol = 0;

        foreach (StartingFlightColumn sfc in Enum.GetValues(typeof(StartingFlightColumn)))
        {
            Controls_mfbDecimalEdit de = (Controls_mfbDecimalEdit)tblStartingFlights.Rows[iRow].FindControl(IDForCell(iRow, iCol));
            SetValueForColumn(sfc, sf, de.Value);
            iCol++;
        }
    }
示例#19
0
        private void CheckDateTimeIssues(LogbookEntryBase le)
        {
            CustomFlightProperty cfpBlockOut = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockOut);
            CustomFlightProperty cfpBlockIn  = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockIn);

            // Block out after block in
            AddConditionalIssue(cfpBlockIn != null && cfpBlockOut != null && cfpBlockOut.DateValue.CompareTo(cfpBlockIn.DateValue) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateTimeInvalidBlock);

            if (le.EngineStart.HasValue())
            {
                // Engine start must be before flight.  Can be after block out, but not before block in
                AddConditionalIssue(le.FlightStart.HasValue() && le.FlightStart.CompareTo(le.EngineStart) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateEngineAfterFlight);
                AddConditionalIssue(le.FlightEnd.HasValue() && le.FlightEnd.CompareTo(le.EngineStart) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndBeforeEngineStart);

                AddConditionalIssue(cfpBlockIn != null && cfpBlockIn.DateValue.CompareTo(le.EngineStart) <= 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineStartAfterBlockIn);
            }

            // Flight start must be after engine start (checked above) and after block out
            AddConditionalIssue(le.FlightStart.HasValue() && cfpBlockOut != null && le.FlightStart.CompareTo(cfpBlockOut.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningDateBlockAfterFlight);

            // Flight end must be after engine/flight start (checked in regular validation), after block out, and before block in
            if (le.FlightEnd.HasValue())
            {
                AddConditionalIssue(cfpBlockOut != null && le.FlightEnd.CompareTo(cfpBlockOut.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndBeforeBlockOut);
                AddConditionalIssue(cfpBlockIn != null && le.FlightEnd.CompareTo(cfpBlockIn.DateValue) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndAfterBlockIn);
                AddConditionalIssue(le.EngineEnd.HasValue() && le.FlightEnd.CompareTo(le.EngineEnd) > 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightEndAfterEngineEnd);
            }

            if (le.EngineEnd.HasValue())
            {
                AddConditionalIssue(cfpBlockIn != null && le.EngineEnd.CompareTo(cfpBlockIn.DateValue) < 0, LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineEndBeforeBlockIn);
            }

            const int MaxHoursDifference = 48;

            // Check that engine, flight, and block times are all roughly equal to date-of-flight
            AddConditionalIssue((le.EngineStart.HasValue() && Math.Abs(le.EngineStart.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (le.EngineEnd.HasValue() && Math.Abs(le.EngineEnd.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineTimeDiffersDate);

            AddConditionalIssue((le.FlightStart.HasValue() && Math.Abs(le.FlightStart.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (le.FlightEnd.HasValue() && Math.Abs(le.FlightEnd.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightTimeDiffersDate);

            AddConditionalIssue((cfpBlockOut != null && Math.Abs(cfpBlockOut.DateValue.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (cfpBlockIn != null && Math.Abs(cfpBlockIn.DateValue.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningBlockTimeDiffersDate);

            // Look for issues with sequential flights
            CheckSequentialFlightIssues(le);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            this.Master.SelectedTab = tabID.tabHome;
            PageSize = 15;

            // figure out who to show
            if (!IsPostBack)
            {
                IEnumerable <LogbookEntry> rgle = Array.Empty <LogbookEntry>();

                string szUserEnc = util.GetStringParam(Request, "uid");
                UserName = string.Empty;

                if (!String.IsNullOrEmpty(szUserEnc))
                {
                    SharedDataEncryptor enc = new SharedDataEncryptor(MFBConstants.keyEncryptMyFlights);
                    UserName = enc.Decrypt(szUserEnc);
                }

                if (String.IsNullOrEmpty(UserName))
                {
                    FlightStats         fs  = FlightStats.GetFlightStats();
                    List <LogbookEntry> lst = new List <LogbookEntry>(fs.RecentPublicFlights);
                    if (lst.Count > PageSize)
                    {
                        lst.RemoveRange(PageSize, lst.Count - PageSize);
                    }
                    rgle = lst;
                }
                else
                {
                    try
                    {
                        // below can throw argument null exception if it's an invalid username
                        Profile pf = Profile.GetUser(UserName);
                        if (pf.UserFullName.Length > 0)
                        {
                            lblHeader.Text = String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.PublicFlightPageHeader, HttpUtility.HtmlEncode(pf.UserFullName));
                        }
                        rgle = LogbookEntryBase.GetPublicFlightsForUser(UserName, 0, PageSize);
                    }
                    catch (Exception ex) when(ex is NullReferenceException)
                    {
                    }
                }

                gvMyFlights.DataSource = rgle;
                gvMyFlights.DataBind();
            }
        }
示例#21
0
    protected void lnkCheckFlight_Click(object sender, EventArgs e)
    {
        Page.Validate(szValGroupEdit); // catch any actual errors too.
        LogbookEntryBase le = InitLogbookEntryFromForm();

        // See if there are any actual errors, stick those at the top of the list.
        le.IsValid(); // will populate ErrorString.

        if (!le.IsNewFlight)
        {
            le.CFISignatureState = new LogbookEntry(le.FlightID, le.User).CFISignatureState;
        }
        CheckFlight(pnlFlightLint, gvFlightLint, le);
    }
示例#22
0
    protected void AddErrorRow(LogbookEntryBase le, string szContext, int iRow)
    {
        if (le == null)
        {
            throw new ArgumentNullException("le");
        }

        if (IsPendingOnly && le.LastError != LogbookEntryBase.ErrorCode.None)   // ignore errors if the importer is only pending flights and the error is a logbook validation error (no tail, future date, night, etc.)
        {
            return;
        }

        // if we're here, we are *either* not pending only *or* we didn't have a logbookentry validation error (e.g., could be malformed row)
        ErrorContext[iRow] = szContext; // save the context for data bind
        AddTextRow(plcErrorList, String.Format(CultureInfo.CurrentCulture, Resources.LogbookEntry.errImportRowHasError, iRow, le.ErrorString), "error");
    }
示例#23
0
    protected void SetUpDownload(LogbookEntryBase led)
    {
        if (led == null)
        {
            throw new ArgumentNullException(nameof(led));
        }
        if (Viewer.CloudAhoyToken == null || Viewer.CloudAhoyToken.AccessToken == null)
        {
            lnkSendCloudAhoy.Visible = false;
        }

        lblOriginalFormat.Text = FormatNameForTelemetry(led);

        // allow selection of units if units are not implicitly known.
        cmbAltUnits.Enabled = cmbSpeedUnits.Enabled = CanSpecifyUnitsForTelemetry(led);
    }
        protected void ResetCrop(LogbookEntryBase le)
        {
            if (le == null)
            {
                throw new ArgumentNullException(nameof(le));
            }
            TelemetryReference tr = le.Telemetry;

            tr.MetaData.DataEnd = tr.MetaData.DataStart = null;
            using (FlightData fd = new FlightData())
            {
                fd.ParseFlightData(le);
                tr.RecalcGoogleData(fd);
            }
            tr.Commit();
            Response.Redirect(Request.RawUrl);
        }
示例#25
0
    protected static void CheckFlight(Control container, GridView gv, LogbookEntryBase le)
    {
        if (container == null)
        {
            throw new ArgumentNullException(nameof(container));
        }
        if (gv == null)
        {
            throw new ArgumentNullException(nameof(gv));
        }
        if (le == null)
        {
            throw new ArgumentNullException(nameof(le));
        }

        gv.DataSource = new MyFlightbook.Lint.FlightLint().CheckFlights(new LogbookEntryBase[] { le }, le.User, MyFlightbook.Lint.FlightLint.DefaultOptionsForLocale);
        gv.DataBind();
        container.Visible = true;
    }
示例#26
0
        private void CheckSimIssues(LogbookEntryBase le)
        {
            bool hasSimRegistration = le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropSimRegistration);

            if (currentAircraft.InstanceType == AircraftInstanceTypes.RealAircraft)
            {
                AddConditionalIssue(le.GroundSim > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMGroundSimInRealAircraft);
                AddConditionalIssue(hasSimRegistration, LintOptions.SimIssues, Resources.FlightLint.warningSIMDeviceIdentifierOnRealAircraft);
            }
            else
            {
                AddConditionalIssue(le.PIC > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMPICInSim);
                AddConditionalIssue(le.SIC > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMSICInSim);
                AddConditionalIssue(le.TotalFlightTime > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMTotalInSim);
                AddConditionalIssue(le.IMC > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMActualIMC);
                AddConditionalIssue(le.CrossCountry > 0, LintOptions.SimIssues, Resources.FlightLint.warningSIMCrossCountryInSim);
                AddConditionalIssue(!hasSimRegistration, LintOptions.SimIssues, Resources.FlightLint.warningSIMNoDeviceIdentifier);
            }
        }
示例#27
0
        private void CheckSequentialFlightIssues(LogbookEntryBase le)
        {
            if (previousFlight == null)
            {
                return;
            }

            AddConditionalIssue(previousFlight.EngineEnd.HasValue() && le.EngineStart.HasValue() && previousFlight.EngineEnd.CompareTo(le.EngineStart) > 0,
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningPreviousEngineEndsAfterStart);

            AddConditionalIssue(previousFlight.FlightEnd.HasValue() && le.FlightStart.HasValue() && previousFlight.FlightEnd.CompareTo(le.FlightStart) > 0,
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningPreviousFlightEndsAfterStart);

            CustomFlightProperty cfpBlockIn  = le.CustomProperties[CustomPropertyType.KnownProperties.IDBlockIn];
            CustomFlightProperty cfpBlockOut = le.CustomProperties[CustomPropertyType.KnownProperties.IDBlockOut];

            CheckBlockIssues(cfpBlockOut);

            CheckDutyIssues(le, cfpBlockIn, cfpBlockOut);
        }
示例#28
0
        private void CheckFlightLengthIssues(LogbookEntryBase le)
        {
            CustomFlightProperty cfpBlockOut = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockOut);
            CustomFlightProperty cfpBlockIn  = le.CustomProperties.GetEventWithTypeID(CustomPropertyType.KnownProperties.IDBlockIn);

            const int MaxHoursDifference = 48;

            // Check that engine, flight, and block times are all roughly equal to date-of-flight
            AddConditionalIssue((le.EngineStart.HasValue() && Math.Abs(le.EngineStart.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (le.EngineEnd.HasValue() && Math.Abs(le.EngineEnd.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningEngineTimeDiffersDate);

            AddConditionalIssue((le.FlightStart.HasValue() && Math.Abs(le.FlightStart.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (le.FlightEnd.HasValue() && Math.Abs(le.FlightEnd.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningFlightTimeDiffersDate);

            AddConditionalIssue((cfpBlockOut != null && Math.Abs(cfpBlockOut.DateValue.Subtract(le.Date).TotalHours) > MaxHoursDifference) ||
                                (cfpBlockIn != null && Math.Abs(cfpBlockIn.DateValue.Subtract(le.Date).TotalHours) > MaxHoursDifference),
                                LintOptions.DateTimeIssues, Resources.FlightLint.warningBlockTimeDiffersDate);
        }
示例#29
0
    /// <summary>
    /// If we're setting up a new flight and last flight had an ending hobbs, initialize with that
    /// clear the cookie, if present, regardless.
    /// </summary>
    protected void InitializeHobbs(LogbookEntryBase le)
    {
        if (le == null)
        {
            throw new ArgumentNullException(nameof(le));
        }
        HttpCookie c = Request.Cookies[keyCookieLastEndingHobbs];

        if (c != null)
        {
            if (le.IsNewFlight)
            {
                if (decimal.TryParse(c.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal hobbsEnd))
                {
                    le.HobbsStart = hobbsEnd;
                }
            }
            Response.Cookies[keyCookieLastEndingHobbs].Expires = DateTime.Now.AddDays(-1);   // clear it.
        }
    }
示例#30
0
        private void CheckXCIssues(LogbookEntryBase le)
        {
            if (currentAircraft.InstanceType != AircraftInstanceTypes.RealAircraft)
            {
                return;
            }

            AddConditionalIssue(le.CrossCountry > 0 && le.CrossCountry.ToMinutes() < le.TotalFlightTime.ToMinutes(), LintOptions.XCIssues, Resources.FlightLint.warningXCNotWholeFlightXC);
            AddConditionalIssue(le.CrossCountry > 0 && (le.CFI + le.Dual + le.SIC + le.PIC).ToMinutes() == 0, LintOptions.XCIssues, Resources.FlightLint.warningXCTimeFoundButNoRole);

            double distance = alSubset.MaxDistanceFromStartingAirport();

            if (le.CrossCountry == 0)
            {
                int minDistanceXC = (currentCatClassID == CategoryClass.CatClassID.Helicopter ? 25 : 50);
                AddConditionalIssue(distance > minDistanceXC, LintOptions.XCIssues, String.Format(CultureInfo.CurrentCulture, Resources.FlightLint.warningXCMissingXC, minDistanceXC));
            }

            bool fxcLessThan25  = le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropXCLessThan25nm);
            bool fxcLessThan50  = le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropXCLessThan50nm);
            bool fxcMoreThan50  = le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropXCMoreThan50nm);
            bool fxcMoreThan100 = le.CustomProperties.PropertyExistsWithID(CustomPropertyType.KnownProperties.IDPropXCMoreThan100nm);

            AddConditionalIssue(fxcLessThan25 && distance > 25, LintOptions.XCIssues, Resources.FlightLint.warningXCDistanceLessThan25ButFlewMore);
            AddConditionalIssue(fxcLessThan50 && distance > 50, LintOptions.XCIssues, Resources.FlightLint.warningXCDistanceLessThan50ButFlewMore);
            AddConditionalIssue(fxcMoreThan50 && distance < 50, LintOptions.XCIssues, Resources.FlightLint.warningXCDistanceMoreThan50ButFlewLess);
            AddConditionalIssue(fxcMoreThan100 && distance < 100, LintOptions.XCIssues, Resources.FlightLint.warningXCDistanceMoreThan100ButFlewLess);
            AddConditionalIssue((fxcLessThan25 ? 1 : 0) + (fxcLessThan50 ? 1 : 0) + (fxcMoreThan50 ? 1 : 0) + (fxcMoreThan100 ? 1 : 0) > 1, LintOptions.XCIssues, Resources.FlightLint.warningXCInconsistentDistances);

            decimal xcLessThan25  = le.CustomProperties.DecimalValueForProperty(CustomPropertyType.KnownProperties.IDPropXCLessThan25nm);
            decimal xcLessThan50  = le.CustomProperties.DecimalValueForProperty(CustomPropertyType.KnownProperties.IDPropXCLessThan50nm);
            decimal xcMoreThan50  = le.CustomProperties.DecimalValueForProperty(CustomPropertyType.KnownProperties.IDPropXCMoreThan50nm);
            decimal xcMoreThan100 = le.CustomProperties.DecimalValueForProperty(CustomPropertyType.KnownProperties.IDPropXCMoreThan100nm);

            AddConditionalIssue(xcLessThan25 > 0 && xcLessThan25.ToMinutes() != le.CrossCountry.ToMinutes(), LintOptions.XCIssues, Resources.FlightLint.warningXCTimeDistanceNotEqualXC);
            AddConditionalIssue(xcLessThan50 > 0 && xcLessThan50.ToMinutes() != le.CrossCountry.ToMinutes(), LintOptions.XCIssues, Resources.FlightLint.warningXCTimeDistanceNotEqualXC);
            AddConditionalIssue(xcMoreThan50 > 0 && xcMoreThan50.ToMinutes() != le.CrossCountry.ToMinutes(), LintOptions.XCIssues, Resources.FlightLint.warningXCTimeDistanceNotEqualXC);
            AddConditionalIssue(xcMoreThan100 > 0 && xcMoreThan100.ToMinutes() != le.CrossCountry.ToMinutes(), LintOptions.XCIssues, Resources.FlightLint.warningXCTimeDistanceNotEqualXC);
        }