protected void wzMerge_FinishButtonClick(object sender, WizardNavigationEventArgs e) { List <LogbookEntry> lst = new List <LogbookEntry>(); // Need to use LogbookEntry, not LogbookEntryDisplay, since you can't commit LogbookEntryDisplay // Also need to do ascending so 1st element is target. DBHelper dbh = new DBHelper(LogbookEntry.QueryCommand(Query, -1, -1, true, LogbookEntry.LoadTelemetryOption.LoadAll)); dbh.ReadRows((comm) => { }, (dr) => { LogbookEntry le = new LogbookEntry(dr, Query.UserName, LogbookEntryCore.LoadTelemetryOption.LoadAll); // Note: this has no telemetry le.PopulateImages(); lst.Add(le); }); LogbookEntry target = lst[0]; lst.RemoveAt(0); foreach (LogbookEntry le in lst) { le.PopulateImages(); } target.MergeFrom(lst); Response.Redirect("~/Member/LogbookNew.aspx"); }
/// <summary> /// Gets all routes ever flown, appends them together and INCLUDES any relevant navaids. /// </summary> /// <returns></returns> private static AirportList AllFlightsAndNavaids(FlightQuery fq) { DBHelper dbh = new DBHelper(LogbookEntry.QueryCommand(fq)); StringBuilder sb = new StringBuilder(); dbh.ReadRows((comm) => { }, (dr) => { sb.AppendFormat(CultureInfo.InvariantCulture, "{0} ", util.ReadNullableField(dr, "Route", string.Empty)); }); return(new AirportList(sb.ToString())); }
protected void RefreshData(bool fForceRefresh) { mfbSearchForm1.Restriction.UserName = User.Identity.Name; mfbSearchForm1.Restriction.Refresh(); if (fForceRefresh || CurrentVisitedAirports == null) { CurrentVisitedAirports = VisitedAirport.VisitedAirportsForQuery(mfbSearchForm1.Restriction); } gvAirports.DataSource = CurrentVisitedAirports; gvAirports.DataBind(); IEnumerable <VisitedRegion> d = VisitedAirport.VisitedCountriesAndAdmins(CurrentVisitedAirports); rptRegions.DataSource = d; rptRegions.DataBind(); lblNone.Visible = !d.Any(); mfbGoogleMapManager1.Visible = CurrentVisitedAirports.Length > 0; // Avoid excessive map loads. AirportList alMatches = new AirportList(CurrentVisitedAirports); // get an airport list of the airports mfbGoogleMapManager1.Map.SetAirportList(alMatches); bool fIncludeRoutes = util.GetIntParam(Request, "path", 0) != 0; if (mfbGoogleMapManager1.Map.Options.fShowRoute = fIncludeRoutes) { List <AirportList> lst = new List <AirportList>(); DBHelper dbh = new DBHelper(LogbookEntry.QueryCommand(mfbSearchForm1.Restriction, lto: LogbookEntry.LoadTelemetryOption.None)); dbh.ReadRows((comm) => { }, (dr) => { object o = dr["Route"]; string szRoute = (string)(o == System.DBNull.Value ? string.Empty : o); if (!String.IsNullOrEmpty(szRoute)) { lst.Add(alMatches.CloneSubset(szRoute)); } }); mfbGoogleMapManager1.Map.Airports = lst; } lnkZoomOut.NavigateUrl = mfbGoogleMapManager1.ZoomToFitScript; lnkZoomOut.Visible = (CurrentVisitedAirports.Length > 0); lblNumAirports.Text = String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.VisitedAirportsNumAirports, CurrentVisitedAirports.Length); }
/// <summary> /// Examines all of the relevant flights for the specified query. /// </summary> /// <param name="dbh">Query that returns the relevant flights</param> /// <param name="action">Action that takes flight data, route, date, and comments. DO NOT dispose of the FlightData - it's owned by THIS.</param> /// <returns>Any error string, empty or null for no error</returns> private static string LookAtAllFlights(FlightQuery fq, LogbookEntryCore.LoadTelemetryOption lto, Action <LogbookEntry> action, bool fForceLoad = false) { if (fq == null) { throw new ArgumentNullException(nameof(fq)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } DBHelper dbh = new DBHelper(LogbookEntry.QueryCommand(fq, lto: lto)); dbh.ReadRows( (comm) => { }, (dr) => { LogbookEntry le = new LogbookEntry(dr, fForceLoad ? (string)dr["username"] : fq.UserName, lto); action(le); }); return(dbh.LastError); }
private static void WriteFlightImagesForUser(HtmlTextWriter tw, string szUserFullName, string szUser, ZipArchive zip) { tw.RenderBeginTag(HtmlTextWriterTag.H1); tw.Write(HttpUtility.HtmlEncode(String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.ImagesBackupFlightsHeader, szUserFullName))); tw.RenderEndTag(); // H1 // We'll get images from the DB rather than slamming the disk // this is a bit of a hack, but limits our queries const string szQ = @"SELECT f.idflight, img.* FROM Images img INNER JOIN flights f ON f.idflight=img.ImageKey WHERE f.username=?user AND img.VirtPathID=0 ORDER BY f.Date desc, f.idFlight desc"; DBHelper dbhImages = new DBHelper(szQ); Dictionary <int, Collection <MFBImageInfo> > dImages = new Dictionary <int, Collection <MFBImageInfo> >(); dbhImages.ReadRows((comm) => { comm.Parameters.AddWithValue("user", szUser); }, (dr) => { int idFlight = Convert.ToInt32(dr["idflight"], CultureInfo.InvariantCulture); Collection <MFBImageInfo> lstMFBii; if (dImages.ContainsKey(idFlight)) { lstMFBii = dImages[idFlight]; } else { dImages[idFlight] = lstMFBii = new Collection <MFBImageInfo>(); } lstMFBii.Add(MFBImageInfo.ImageFromDBRow(dr)); }); // Get all of the user's flights, including telemetry const int PageSize = 200; // get 200 flights at a time. int offset = 0; int iRow = 0; bool fCouldBeMore = true; while (fCouldBeMore) { FlightQuery fq = new FlightQuery(szUser); DBHelper dbhFlights = new DBHelper(LogbookEntry.QueryCommand(fq, offset, PageSize, true, LogbookEntry.LoadTelemetryOption.LoadAll)); dbhFlights.ReadRows((comm) => { }, (dr) => { LogbookEntry le = new LogbookEntry(dr, szUser, LogbookEntry.LoadTelemetryOption.LoadAll); le.FlightImages.Clear(); IEnumerable <MFBImageInfo> rgmfbii = (dImages.ContainsKey(le.FlightID)) ? dImages[le.FlightID] : new Collection <MFBImageInfo>(); foreach (MFBImageInfo mfbii in rgmfbii) { le.FlightImages.Add(mfbii); } // skip any flights here that don't have images, videos, or telemetry if (le.FlightImages.Count > 0 || le.Videos.Any() || le.HasFlightData) { WriteFlightInfo(tw, zip, le); } iRow++; }); if (fCouldBeMore = (iRow == offset + PageSize)) { offset += PageSize; } } }
public void DataBind() { if (Username.Length == 0 || Restriction == null) { return; } // get the base command with all of the relevant parameters using (MySqlCommand comm = new MySqlCommand()) { DBHelper.InitCommandObject(comm, LogbookEntry.QueryCommand(Restriction)); string szInnerQuery = comm.CommandText; // this got set above; cache it away for a moment or two string szTempTableName = "flightsForUserWithQuery"; Profile pf = Profile.GetUser(Username); string szGroupField = string.Empty; switch (pf.TotalsGroupingMode) { case TotalsGrouping.CatClass: szGroupField = "CatClassDisplay"; break; case TotalsGrouping.Model: szGroupField = "CatClassDisplay, ModelDisplay"; break; case TotalsGrouping.Family: szGroupField = "CatClassDisplay, FamilyDisplay"; break; } // All three queries below use the innerquery above to find the matching flights; they then find totals from that subset of flights. string szQTotalTimes = pf.DisplayTimesByDefault ? ConfigurationManager.AppSettings["TotalTimesSubQuery"].ToString() : string.Empty; string szQTotalsByCatClass = String.Format(CultureInfo.InvariantCulture, ConfigurationManager.AppSettings["TotalsQuery"].ToString(), szQTotalTimes, szTempTableName, szGroupField); string szQTotals = String.Format(CultureInfo.InvariantCulture, ConfigurationManager.AppSettings["TotalsQuery"].ToString(), szQTotalTimes, szTempTableName, "username"); // Note: this username is the "Group By" field, not a restriction. string szQCustomPropTotals = String.Format(CultureInfo.InvariantCulture, ConfigurationManager.AppSettings["TotalsCustomProperties"].ToString(), szTempTableName); alTotals.Clear(); try { // Set up temporary table: comm.Connection.Open(); comm.Parameters.AddWithValue("lang", System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName); // Create the temp table comm.CommandText = String.Format(CultureInfo.InvariantCulture, "DROP TEMPORARY TABLE IF EXISTS {0}", szTempTableName); comm.ExecuteScalar(); try { comm.CommandText = String.Format(CultureInfo.InvariantCulture, "CREATE TEMPORARY TABLE {0} AS {1}", szTempTableName, szInnerQuery); comm.ExecuteScalar(); } catch (MySqlException ex) { throw new MyFlightbookException(String.Format(CultureInfo.InvariantCulture, "Exception creating temporary table:\r\n{0}\r\n{1}\r\n{2}", ex.Message, szTempTableName, szInnerQuery), ex, pf.UserName); } // Get totals by category class int cTotalsSoFar = alTotals.Count; // should always be 0, but safer this way comm.CommandText = szQTotalsByCatClass; ComputeTotalsByCatClass(comm, pf); bool fShowOverallSubtotals = ((alTotals.Count - cTotalsSoFar) > 1); // if we had multiple totals from above, then we want to show overall subtotals of approaches/landings. // Sort what we have so far. alTotals.Sort(); // now get the custom property totals comm.CommandText = szQCustomPropTotals; ComputeTotalsForCustomProperties(comm, pf); // Get model-based time (retract, complex, etc.) if (!pf.SuppressModelFeatureTotals) { ComputeTotalsForModelFeature(comm, szTempTableName, pf); } // Now get full totals comm.CommandText = szQTotals; ComputeTotalsOverall(comm, pf, fShowOverallSubtotals); // Drop the temp table comm.CommandText = String.Format(CultureInfo.InvariantCulture, "DROP TEMPORARY TABLE {0};", szTempTableName); comm.ExecuteScalar(); } catch (MySqlException ex) { throw new MyFlightbookException("Exception in UserTotals DataBind - setup", ex, pf.UserName); } finally { if (comm.Connection != null && comm.Connection.State != ConnectionState.Closed) { comm.Connection.Close(); } } } }
public void UpdateData() { if (User.Length > 0) { // See whether or not to show catclassoverride column bool fShowAltCatClass = false; DBHelper dbh = new DBHelper("SELECT COALESCE(MAX(idCatClassOverride), 0) AS useAltCatClass FROM flights f WHERE f.username=?user"); dbh.ReadRow( (comm) => { comm.Parameters.AddWithValue("user", User); }, (dr) => { fShowAltCatClass = Convert.ToInt32(dr["useAltCatClass"], CultureInfo.InvariantCulture) > 0; }); if (!fShowAltCatClass) { foreach (DataControlField dcf in gvFlightLogs.Columns) { if (dcf.HeaderText.CompareCurrentCultureIgnoreCase("Alternate Cat/Class") == 0) { gvFlightLogs.Columns.Remove(dcf); break; } } } using (MySqlCommand comm = new MySqlCommand()) { DBHelper.InitCommandObject(comm, LogbookEntry.QueryCommand(Restriction)); comm.CommandTimeout = 80; // use a longer timeout - this could be slow. try { using (MySqlDataAdapter da = new MySqlDataAdapter(comm)) { using (DataSet dsFlights = new DataSet()) { dsFlights.Locale = CultureInfo.CurrentCulture; da.Fill(dsFlights); gvFlightLogs.DataSource = dsFlights; // Get the list of property types used by this user to create additional columns comm.CommandText = "SELECT DISTINCT cpt.Title FROM custompropertytypes cpt INNER JOIN flightproperties fp ON fp.idPropType=cpt.idPropType INNER JOIN flights f ON f.idFlight=fp.idFlight WHERE f.username=?uName"; // parameters should still be valid Hashtable htProps = new Hashtable(); // maps titles to the relevant column in the gridview int cColumns = gvFlightLogs.Columns.Count; using (DataSet dsProps = new DataSet()) { dsProps.Locale = CultureInfo.CurrentCulture; da.Fill(dsProps); // add a new column for each property and store the column number in the hashtable (keyed by title) foreach (DataRow dr in dsProps.Tables[0].Rows) { htProps[dr.ItemArray[0]] = cColumns++; BoundField bf = new BoundField() { HeaderText = dr.ItemArray[0].ToString(), HtmlEncode = false, DataField = "", DataFormatString = "" }; gvFlightLogs.Columns.Add(bf); } } if (OrderString != null && OrderString.Length > 0) { char[] delimit = { ',' }; string[] rgszCols = OrderString.Split(delimit); ArrayList alCols = new ArrayList(); // identify the requested front columns foreach (string szcol in rgszCols) { int col = 0; if (int.TryParse(szcol, NumberStyles.Integer, CultureInfo.InvariantCulture, out col)) { if (col < gvFlightLogs.Columns.Count) { alCols.Add(col); } } } int[] rgCols = (int[])alCols.ToArray(typeof(int)); // pull those columns to the left; this creates a duplicate column and shifts everything right by one... int iCol = 0; for (iCol = 0; iCol < rgCols.Length; iCol++) { gvFlightLogs.Columns.Insert(iCol, gvFlightLogs.Columns[rgCols[iCol] + iCol]); } // And then remove the duplicates, from right to left Array.Sort(rgCols); for (int i = rgCols.Length - 1; i >= 0; i--) { gvFlightLogs.Columns.RemoveAt(rgCols[i] + iCol); } } gvFlightLogs.DataBind(); // now splice in all of the properties above // ?localecode and ?shortDate are already in the parameters, from above. comm.CommandText = "SELECT ELT(cpt.type + 1, cast(fdc.intValue as char), cast(FORMAT(fdc.decValue, 2, ?localecode) as char), if(fdc.intValue = 0, 'No', 'Yes'), DATE_FORMAT(fdc.DateValue, ?shortDate), cast(DateValue as char), StringValue, cast(fdc.decValue AS char)) AS PropVal, fdc.idFlight AS idFlight, cpt.title AS Title FROM flightproperties fdc INNER JOIN custompropertytypes cpt ON fdc.idPropType=cpt.idPropType INNER JOIN flights f ON f.idflight=fdc.idFlight WHERE username=?uName"; // and parameters should still be valid! using (DataSet dsPropValues = new DataSet()) { dsPropValues.Locale = CultureInfo.CurrentCulture; da.Fill(dsPropValues); foreach (GridViewRow gvr in gvFlightLogs.Rows) { int idFlight = Convert.ToInt32(dsFlights.Tables[0].Rows[gvr.RowIndex]["idFlight"], CultureInfo.CurrentCulture); foreach (DataRow dr in dsPropValues.Tables[0].Rows) { if (idFlight == Convert.ToInt32(dr["idFlight"], CultureInfo.CurrentCulture)) { gvr.Cells[Convert.ToInt32(htProps[dr["Title"]], CultureInfo.CurrentCulture)].Text = dr["PropVal"].ToString(); } } } } } } } finally { if (comm.Connection != null && comm.Connection.State != ConnectionState.Closed) { comm.Connection.Close(); } } } } }
/// <summary> /// Creates/returns a memory stream containing a zip of a) an HTML file of images, and b) the thumbnails of the images, linked to Amazon. /// THE STREAM MUST BE CLOSED BY THE CALLER! /// </summary> /// <param name="activeBrand">The brand to use - null for current brand</param> /// <returns>A memory stream of flight images followed by any profile images</returns> public MemoryStream ZipOfImagesForUser(Brand activeBrand) { if (activeBrand == null) { activeBrand = Branding.CurrentBrand; } MemoryStream ms = new MemoryStream(); using (ZipFile zip = new ZipFile()) { System.IO.StringWriter sw = new System.IO.StringWriter(); HtmlTextWriter tw = new HtmlTextWriter(sw); tw.RenderBeginTag(HtmlTextWriterTag.Html); tw.RenderBeginTag(HtmlTextWriterTag.Head); tw.AddAttribute("href", Branding.ReBrand("http://%APP_URL%%APP_ROOT%/public/stylesheet.css", activeBrand)); tw.AddAttribute("rel", "stylesheet"); tw.AddAttribute("type", "text/css"); tw.RenderBeginTag(HtmlTextWriterTag.Link); tw.RenderEndTag(); // Link tw.RenderBeginTag(HtmlTextWriterTag.Title); tw.Write(HttpUtility.HtmlEncode(String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.ImagesBackupTitle, User.UserFullName))); tw.RenderEndTag(); // Head tw.RenderBeginTag(HtmlTextWriterTag.Body); // Write out profile images tw.RenderBeginTag(HtmlTextWriterTag.H1); tw.Write(HttpUtility.HtmlEncode(String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.ImagesBackupEndorsementsHeader, User.UserFullName))); tw.RenderEndTag(); // h1 ImageList il = new ImageList(MFBImageInfo.ImageClass.Endorsement, User.UserName); il.Refresh(true); foreach (MFBImageInfo mfbii in il.ImageArray) { zip.AddFile(System.Web.Hosting.HostingEnvironment.MapPath(mfbii.PathThumbnail), szThumbFolder); mfbii.ToHtml(tw); mfbii.UnCache(); } // Write out any digital endorsements too IEnumerable <Endorsement> rgEndorsements = Endorsement.EndorsementsForUser(User.UserName, null); if (rgEndorsements.Count() > 0) { Page p = new FormlessPage(); p.Controls.Add(new HtmlForm()); IEndorsementListUpdate el = (IEndorsementListUpdate)p.LoadControl("~/Controls/mfbEndorsement.ascx"); foreach (Endorsement en in rgEndorsements) { el.SetEndorsement(en); try { ((UserControl)el).RenderControl(tw); } catch { } // don't write bogus or incomplete HTML } } // And any BasicMed stuff IEnumerable <BasicMedEvent> lstBMed = BasicMedEvent.EventsForUser(User.UserName); foreach (BasicMedEvent bme in lstBMed) { ImageList ilBasicMed = new ImageList(MFBImageInfo.ImageClass.BasicMed, bme.ImageKey); ilBasicMed.Refresh(true); foreach (MFBImageInfo mfbii in ilBasicMed.ImageArray) { zip.AddFile(System.Web.Hosting.HostingEnvironment.MapPath(mfbii.PathThumbnail), szThumbFolder); mfbii.ToHtml(tw); mfbii.UnCache(); } } // Write out flight images tw.RenderBeginTag(HtmlTextWriterTag.H1); tw.Write(HttpUtility.HtmlEncode(String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.ImagesBackupFlightsHeader, User.UserFullName))); tw.RenderEndTag(); // H1 // We'll get images from the DB rather than slamming the disk // this is a bit of a hack, but limits our queries const string szQ = @"SELECT f.idflight, img.* FROM Images img INNER JOIN flights f ON f.idflight=img.ImageKey WHERE f.username=?user AND img.VirtPathID=0 ORDER BY f.Date desc, f.idFlight desc"; DBHelper dbhImages = new DBHelper(szQ); Dictionary <int, List <MFBImageInfo> > dImages = new Dictionary <int, List <MFBImageInfo> >(); dbhImages.ReadRows((comm) => { comm.Parameters.AddWithValue("user", User.UserName); }, (dr) => { int idFlight = Convert.ToInt32(dr["idflight"], CultureInfo.InvariantCulture); List <MFBImageInfo> lstMFBii; if (dImages.ContainsKey(idFlight)) { lstMFBii = dImages[idFlight]; } else { dImages[idFlight] = lstMFBii = new List <MFBImageInfo>(); } lstMFBii.Add(MFBImageInfo.ImageFromDBRow(dr)); }); // Get all of the user's flights, including telemetry const int PageSize = 200; // get 200 flights at a time. int offset = 0; int iRow = 0; bool fCouldBeMore = true; while (fCouldBeMore) { FlightQuery fq = new FlightQuery(User.UserName); DBHelper dbhFlights = new DBHelper(LogbookEntry.QueryCommand(fq, offset, PageSize, true, LogbookEntry.LoadTelemetryOption.LoadAll)); dbhFlights.ReadRows((comm) => { }, (dr) => { LogbookEntry le = new LogbookEntry(dr, User.UserName, LogbookEntry.LoadTelemetryOption.LoadAll); le.FlightImages = (dImages.ContainsKey(le.FlightID)) ? dImages[le.FlightID].ToArray() : new MFBImageInfo[0]; // skip any flights here that don't have images, videos, or telemetry if (le.FlightImages.Length > 0 || le.Videos.Count > 0 || le.HasFlightData) { WriteFlightInfo(tw, zip, le); } iRow++; }); if (fCouldBeMore = (iRow == offset + PageSize)) { offset += PageSize; } } tw.RenderEndTag(); // Body tw.RenderEndTag(); // Html zip.AddEntry(Branding.ReBrand(String.Format(CultureInfo.InvariantCulture, "{0}.htm", Resources.LocalizedText.ImagesBackupFilename), activeBrand), sw.ToString()); zip.Save(ms); } return(ms); }
protected void RefreshLogbookData() { mvLayouts.ActiveViewIndex = (int)PrintOptions1.Options.Layout; pnlResults.Visible = true; lblCoverDate.Text = String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.PrintViewCoverSheetDateTemplate, DateTime.Now); PrintingOptions po = PrintOptions1.Options; // Set any global font appropriately. pnlResults.Style["font-size"] = po.Size == PrintingOptions.FontSize.Normal ? "9pt" : String.Format(CultureInfo.InvariantCulture, po.Size == PrintingOptions.FontSize.Small ? "7pt" : "11pt"); // Make sure that any PDF and section information is up-to-date, and that the PrintOptions property is set up correctly po.Sections = printingSections; po.PDFSettings = pdfOptions; PrintOptions = po; // Make sure copy link is up-to-date lnkPermalink.NavigateUrl = PermaLink(po, mfbSearchForm1.Restriction); mvLayouts.Visible = po.Sections.IncludeFlights; pnlEndorsements.Visible = po.Sections.Endorsements != PrintingSections.EndorsementsLevel.None; rptImages.Visible = po.Sections.Endorsements == PrintingSections.EndorsementsLevel.DigitalAndPhotos; pnlTotals.Visible = po.Sections.IncludeTotals; pnlCover.Visible = po.Sections.IncludeCoverPage; IList <LogbookEntryDisplay> lstFlights = LogbookEntryDisplay.GetFlightsForQuery(LogbookEntry.QueryCommand(mfbSearchForm1.Restriction, fAsc: true), CurrentUser.UserName, string.Empty, SortDirection.Ascending, CurrentUser.UsesHHMM, CurrentUser.UsesUTCDateOfFlight); PrintLayout pl = LogbookPrintedPage.LayoutLogbook(CurrentUser, lstFlights, ActiveTemplate, po, SuppressFooter); Master.PrintingCSS = pl.CSSPath.ToAbsoluteURL(Request).ToString(); }
protected void RefreshLogbookData() { mvLayouts.ActiveViewIndex = (int)PrintOptions1.Options.Layout; pnlResults.Visible = true; lblCoverDate.Text = String.Format(CultureInfo.CurrentCulture, Resources.LocalizedText.PrintViewCoverSheetDateTemplate, DateTime.Now); IList <LogbookEntryDisplay> lstFlights = LogbookEntryDisplay.GetFlightsForQuery(LogbookEntry.QueryCommand(mfbSearchForm1.Restriction, fAsc: true), CurrentUser.UserName, string.Empty, SortDirection.Ascending, CurrentUser.UsesHHMM, CurrentUser.UsesUTCDateOfFlight); PrintLayout pl = LogbookPrintedPage.LayoutLogbook(CurrentUser, lstFlights, ActiveTemplate, PrintOptions1.Options, SuppressFooter); Master.PrintingCSS = pl.CSSPath.ToAbsoluteURL(Request).ToString(); }
/// <summary> /// Returns a set of visited airports matching the specified flight query /// </summary> /// <param name="fq">The flight query</param> /// <returns>A set of visited airports</returns> public static VisitedAirport[] VisitedAirportsForQuery(FlightQuery fq) { if (fq == null) { throw new ArgumentNullException(nameof(fq)); } if (String.IsNullOrEmpty(fq.UserName)) { throw new ArgumentNullException(nameof(fq)); } Dictionary <string, VisitedAirport> dictVA = PopulateAirports(LogbookEntry.QueryCommand(fq, 0, -1, true)); // We now have a hashtable of visited airports. We need to initialize the airport element in each of these. string[] rgCodes = new string[dictVA.Keys.Count]; dictVA.Keys.CopyTo(rgCodes, 0); string szAll = String.Join(" ", rgCodes); // do a single db hit to get all of the airport information // Rebuild the airport list based on ONLY those airports that returned a result // Build a dictionary of found airports from which we can build our visited airports Dictionary <string, airport> dictAirportResults = new Dictionary <string, airport>(); Array.ForEach <airport>(new AirportList(szAll).GetAirportList(), (ap) => { if (ap.IsPort) { dictAirportResults[ap.Code] = ap; } }); // We now have a list of all visited airports as the user typed them (in dictVA), and of all airports (in dictAirportResults) // We need to match the two up. // Initialize any airports we found MatchUpVisitedAirports(dictVA, dictAirportResults); /* * Need to de-dupe by location: * - AST example: AST is in the DB but KAST is not. So if KAST has a null airport but the AST version exists, merge KAST->AST * - KNZC: KNZC is in the DB, but NZC is not. Merge in the other direction (towards KNZC) * - KSFO/SFO are both in the DB. Merge to the naked (SFO) version, if only because when we search for flights SFO will hit airports more liberally. * - OGG/PHOG or CHC/NZCH - go to the longer one; we'll do this AFTER the K-hack ones because the K-hack may be dealing with non-existent airports, but non-K-hack ALWAYS has real airports. * */ foreach (string key in dictVA.Keys) { if (airport.IsUSAirport(key)) // if this is the Kxxx version... { string szKUnhack = airport.USPrefixConvenienceAlias(key); VisitedAirport vaKPrefix = dictVA.ContainsKey(key) ? dictVA[key] : null; // should never be null by definition - it's in "keys" collection. VisitedAirport vaNoPrefix = dictVA.ContainsKey(szKUnhack) ? dictVA[szKUnhack] : null; if (vaNoPrefix != null) { // KNZC example: this is KNZC, but "NZC" doesn't have an airport: Merge NZC into KNZC and keep KNZC; NZC will be discarded below. if (vaNoPrefix.Airport == null) { vaKPrefix.MergeWith(vaKPrefix); } // AST/KAST example: this is KAST and has no airport, but the convenience alias did: Merge KAST into AST; KAST will be discarded below. if (vaKPrefix.Airport == null && vaNoPrefix.Airport != null) { vaNoPrefix.MergeWith(vaKPrefix); } // SFO/KSFO exmaple: this is KSFO and has an airport, but so does SFO. // But only if the airports are essentially the same location // Merge KSFO into SFO and nullify KSFO; it will be discarded below. if (vaKPrefix.Airport != null && vaNoPrefix.Airport != null && vaKPrefix.Airport.LatLong.IsSameLocation(vaNoPrefix.Airport.LatLong)) { vaKPrefix.MergeWith(vaNoPrefix); vaNoPrefix.Airport = null; // we've merged; don't return the K version. } } } } // Now need to merge any remaining airports with multiple codes but the same location. E.g., OGG and PHOG or CHC and NZCH Dictionary <string, VisitedAirport> dDedupe = new Dictionary <string, VisitedAirport>(); foreach (VisitedAirport va in dictVA.Values) { if (va.Airport == null) { continue; } string szLocKey = va.Airport.GeoHashKey; // If the code is already present AND it has a longer code than this one, then merge them if (dDedupe.ContainsKey(szLocKey)) { VisitedAirport vaDupe = dDedupe[szLocKey]; if (vaDupe.Code.Length > va.Code.Length) { vaDupe.MergeWith(va); va.Airport = null; // we've merged, don't return this one. continue; } else { va.MergeWith(vaDupe); // we'll replace vadupe with va below. vaDupe.Airport = null; } } // Otherwise, store this one. dDedupe[szLocKey] = va; } // copy the ones with matching airports into an array list List <VisitedAirport> lstResults = new List <VisitedAirport>(dDedupe.Values); lstResults.Sort(); return(lstResults.ToArray()); }
protected void RefreshLogbookData() { MyFlightbook.Profile pf = MyFlightbook.Profile.GetUser(Page.User.Identity.Name); PrintingOptions printingOptions = PrintOptions1.Options; mvLayouts.ActiveViewIndex = (int)printingOptions.Layout; List <LogbookEntryDisplay> lstFlights = LogbookEntryDisplay.GetFlightsForQuery(LogbookEntry.QueryCommand(mfbSearchForm1.Restriction, fAsc: true), pf.UserName, string.Empty, SortDirection.Ascending, pf.UsesHHMM, pf.UsesUTCDateOfFlight); IPrintingTemplate pt = ActiveTemplate; PrintLayout pl = PrintLayout.LayoutForType(printingOptions.Layout, CurrentUser); bool fCanIncludeImages = pl.SupportsImages; // Exclude both excluded properties and properties that have been moved to their own columns HashSet <int> lstPropsToExclude = new HashSet <int>(printingOptions.ExcludedPropertyIDs); HashSet <int> lstPropsInOwnColumns = new HashSet <int>(); foreach (OptionalColumn oc in printingOptions.OptionalColumns) { if (oc.ColumnType == OptionalColumnType.CustomProp) { lstPropsInOwnColumns.Add(oc.IDPropType); } } string szPropSeparator = printingOptions.PropertySeparatorText; // set up properties per flight, and compute rough lineheight foreach (LogbookEntryDisplay led in lstFlights) { // Fix up properties according to the printing options List <CustomFlightProperty> lstProps = new List <CustomFlightProperty>(led.CustomProperties); // And fix up model as well. switch (printingOptions.DisplayMode) { case PrintingOptions.ModelDisplayMode.Full: break; case PrintingOptions.ModelDisplayMode.Short: led.ModelDisplay = led.ShortModelName; break; case PrintingOptions.ModelDisplayMode.ICAO: led.ModelDisplay = led.FamilyName; break; } // Remove from the total property set all explicitly excluded properties... lstProps.RemoveAll(cfp => lstPropsToExclude.Contains(cfp.PropTypeID)); // ...and then additionally exclude from the display any that's in its own column to avoid redundancy. lstProps.RemoveAll(cfp => lstPropsInOwnColumns.Contains(cfp.PropTypeID)); led.CustPropertyDisplay = CustomFlightProperty.PropListDisplay(lstProps, pf.UsesHHMM, szPropSeparator); if (printingOptions.IncludeImages) { led.PopulateImages(true); } if (!printingOptions.IncludeSignatures) { led.CFISignatureState = LogbookEntryBase.SignatureState.None; } led.RowHeight = pl.RowHeight(led); } Master.PrintingCSS = pl.CSSPath.ToAbsoluteURL(Request).ToString(); pt.BindPages(LogbookPrintedPage.Paginate(lstFlights, printingOptions), CurrentUser, printingOptions, !SuppressFooter); pnlResults.Visible = true; }
protected void RefreshLogbookData() { MyFlightbook.Profile pf = MyFlightbook.Profile.GetUser(Page.User.Identity.Name); PrintingOptions printingOptions = PrintOptions1.Options; mvLayouts.ActiveViewIndex = (int)printingOptions.Layout; List <LogbookEntryDisplay> lstFlights = LogbookEntryDisplay.GetFlightsForQuery(LogbookEntry.QueryCommand(mfbSearchForm1.Restriction, fAsc: true), pf.UserName, string.Empty, SortDirection.Ascending, pf.UsesHHMM, pf.UsesUTCDateOfFlight); IPrintingTemplate pt = ActiveTemplate; PrintLayout pl = PrintLayout.LayoutForType(printingOptions.Layout, CurrentUser); bool fCanIncludeImages = pl.SupportsImages; List <int> lstPropsToExclude = new List <int>(printingOptions.ExcludedPropertyIDs); string szPropSeparator = printingOptions.PropertySeparatorText; // set up properties per flight, and compute rough lineheight foreach (LogbookEntryDisplay led in lstFlights) { // Fix up properties according to the printing options List <CustomFlightProperty> lstProps = new List <CustomFlightProperty>(led.CustomProperties); lstProps.RemoveAll(cfp => lstPropsToExclude.Contains(cfp.PropTypeID)); led.CustomProperties = lstProps.ToArray(); led.CustPropertyDisplay = CustomFlightProperty.PropListDisplay(lstProps, pf.UsesHHMM, szPropSeparator); if (printingOptions.IncludeImages) { led.PopulateImages(true); } led.RowHeight = pl.RowHeight(led); } Master.PrintingCSS = pl.CSSPath.ToAbsoluteURL(Request).ToString(); pt.BindPages(LogbookPrintedPage.Paginate(lstFlights, printingOptions.FlightsPerPage, printingOptions.OptionalColumns), CurrentUser, printingOptions.IncludeImages, !SuppressFooter, printingOptions.OptionalColumns); pnlResults.Visible = true; }