Thursday, November 7, 2019

Local Time part II

In an earlier blog post, I discussed the challenges of supporting local times on the MyFlightbook website. 

The short summary of the problem is that it's critical that all underlying times be UTC, in order to enable any math or computation determining length of flight or duty periods or similar.  The blog post described why I don't support import/export using anything other than UTC, and why I don't store local times in the database.

However, it is possible to provide support for data entry and editing in a local time zone, just as the mobile apps do.  The idea (as the mobile apps do) is that you convert any UTC time to local time when putting it into an editable field, and then convert back to UTC when committing the edit (i.e., when saving or updating the flight). 

iOS and Android always know their current offset from UTC - i.e., the offset at the time and place where you are making the edit.  This is fine, as the iOS and Android apps are generally optimized for data entry in-the-moment (e.g., during or shortly after your flight) rather than bulk entry of historical flights.

Web browsers, sadly do not provide time zone information.  I can get the current offset from UTC for the user's browser (and only after the first request - too late for the first page that is requested!), but I cannot get a name for the timezone (thus enabling, for example, "EDT" for "Eastern Daylight Time"), nor any rules around daylight saving time

But all is not lost, and today I released a new feature that allows you, if you like, to declare a preferred time zone.  (Go to Profile->Preferences->Flight Entry).  This applies on the web only, and will allow you to enter/edit times in the specified time zone.

If you enable anything other than "UTC", then all of the time fields that usually have a "UTC" label or description will change to say "Custom TZ"; you can hover over this to see which time zone is in use; doing this will show you the standard offset from UTC, even if you are in daylight time, but any conversion should correctly account for standard/daylight time. 

As an aside: I use "Custom" rather than "Local" because "Local" is inherently ambiguous: e.g., if you live in Chicago, but you have a flight from LA to New York, is the "local time" Pacific, Central, or East Coast?  "Custom" here at least clarifies that it's one you've specified.  Why not use a 3-letter acronym like "EDT"?  Two reasons: (a) the acronyms don't span daylight/standard time.  E.g., EDT is specifically daylight time, but in August you probably would want EST, so you'd have to use the more ambiguous "ET" and (b) more practically, the system doesn't provide a set of acronyms for the ~139 timezones in the system.

There's actually an additional benefit here that goes one better than the iOS/Android apps: by specifying a timezone, the daylight time rules are encapsulated.  So if it is August 8 and I'm transcribing a flight from February that was at 1pm Pacific time, that will be correctly converted to 9PM UTC (Pacific Time in February is Pacific Standard Time, which is UTC-8) but a similar flight from May would be 8PM UTC. 

I am only doing this for editing times; I am still sticking with UTC for all display purposes, such as printing or displaying details of a flight in the logbook list.  Not only does it avoid ambiguity to do so, but it also removes the need to display the timezone (and as mentioned above, the system doesn't provide me with a short abbreviation for the time zone names, so it would literally have to display something horrendously long like "Pacific Time (US & Canada)" (i.e., the name of the timezone) next to each time.

Sunday, October 6, 2019

"Total Time" and "Total Flight Time"

I have a confession to make.  I use the term "Total Time" liberally throughout MyFlightbook for the "bottom-line" time of a flight entry.  The problem is, that phrase is not really defined, and could be used by a given pilot to refer to either Pilot Time or Total Flight Time.

These are not quite the same thing.  Per 61.51(j), (in the US at least), Flight Time is in "an aircraft".  No training devices are listed here.  Pilot Time, on the other hand, is what contributes to total aeronautical experience (per 61.1(b)), and it is a superset of Flight Time and appropriate Sim time.

That is to say, if you have 100 hours in an actual flying machine aircraft, 20 hours in a certified level-D full-motion simulator, and 30 hours playing Microsoft Flight Simulator, then you properly have a Total Flight Time of 100 hours, and a total Pilot Time of 120 hours.

When MyFlightbook reports a "Total Time", it is a straight-line sum of that field (constrained by any search criteria you specify); it is not distinguishing sim time from real aircraft; it's not even excluding any time you logged there in uncertified sims like Microsoft Flight Sim.  (MyFlightbook does, however, separate these all out in the 8710 form) So if you log time in a sim in the "Total Time" field, you are adding to your Pilot Time, not to your Flight Time.

As I mentioned in a previous post regarding sims, my best advice here is to leave the "Total Time" field blank when not recording time in an actual flying machine; instead, put any sim time into the "Ground Sim" field (or ground instruction into the "Ground Instruction" property, using any aircraft you like).

So if it's a bad idea, then why do I allow people to put time into the "Total Time" field for sims?  Three reasons:
  • Some pilots are using this to count Pilot Time.  
  • Under other non-FAA regulatory environments, it can sometimes be counted towards flight time.
  • Many pilots do catch-up flights to carry-forward time from paper or other logbooks; as this would be a mix of sim and actual aircraft time, I allow people to mix these.

But there's a third reason people will log this: credit towards aeronautical experience.  For example, a requirement for an ATP rating (61.159) in the US is 1,500 hours of aeronautical experience.  But 61.159(a)(6) allows up to 100 hours of this 1,500 hours to be acquired in an appropriate training device, so many pilots view this as allowing them to "count" up to 100 hours in sims towards their total time.


If you do this, then you are following the "Pilot Time" rule - that's OK, but if someone asks you for your total Flight Time, you need to back out your sim time.

I think, however, that the "correct" (can I use "correct" and "I think" in the same sentence?  Sure, I'll allow it...) way to interpret the aeronautical experience requirement in 61.159 here is "The sum of your Flight Time and MIN(100, time in an FTD or FFS under appropriate rules) is at least 1,500 hours". 

MyFlightbook does know about this substitution and applies it to FTDs and FFSs (under the assumption that you're doing it under a part 121/135/141/142 training course) when reporting your progress towards the ATP rating, so it is not necessary to explicitly add total time for these sim sessions in order to receive credit.  And, in fact, to avoid double-counting, a given flight actually credits MAX(Ground Sim, Total Time), in case you logged both.

So I'll repeat my advice: to keep things clean, only log "Total Time" for flights that are in an actual aircraft.

Thursday, October 3, 2019

Local time

What time is it?  Generally, there are two answers to that question: what time is it where I am, and what time is it in UTC (Zulu).

All times in MyFlightbook are in Zulu (UTC) time, for a pretty obvious reason: it's the only way to do computations.  If you depart at 4PM EST and land at 7PM PST, you're flight was 6 hours long, not 3, after all; as with all math, you need to use common units.  And in order to compute things like night flight, one needs to know the position of the sun relative to the horizon at a given latitude/longitude and time - and thus the time needs to also be in a common unit system.

The iOS and Android apps on MyFlightbook have an option to use local time.  When this is selected, all the times are still in UTC.  The only difference is in the display.  So in the example above, if you enter "4PM" while you are in New York (EST = UTC-4), that goes into the database as 8PM UTC (2000Z).  When you land at 7PM in LA (PST=UTC-7), that 7PM goes into the database as 2AM (0200Z) the next day.

What's interesting is that if you go and look at your New York departure time after your landing in LA, it will no longer say 4PM - it will say 1PM.  Why?  Because you're now in LA, and it's displaying the unmodified 2000Z departure time in PST, (2000Z-0700=1300PST).  Note that the underlying time is invariant; only the display has changed.

That works well on the device, which typically always knows its location and its timezone offset.  It also works for times that are either entered in UTC, or which are entered relative to your current time zone offset.

But the key thing is that the local time option always works based on *where you are* *right now*.  I.e., it's not based on the time or location of the flight data, it's based on your time and location as the viewer of that data.

Unfortunately, converting from local time to UTC - especially for other than the "right here, right now" case - is a significantly more complicated problem.

E.g., if you are going through old flights and want to log something that departed ABC at 4PM local and arrived at DEF at 7PM local on Oct 23, 1997, you need to know the timezone offset for ABC and for DEF on those dates, including if/when Daylight Saving time is observed (and, if it is observed, when the cut-over dates are)

This is absolutely a solvable problem, but requires a lot of data and it requires maintenance of that data.  Specifically, it requires:
  • A database of geographic boundaries of each time zone, including changes over time.
  • A database of daylight saving time rules, including changes in those rules over time.
So to compute, say, total time for a flight with local departure/arrival times specified:
  • Look up the latitude/longitude of the departure or arrival airport on the date of departure/arrival
  • Find the appropriate time zone based on those coordinates
  • Determine whether or not to apply daylight saving time based on the date of flight, taking care of the time of arrival (since a flight can span the typical 2am-local transition to/from daylight saving time)
  • Adjust the local times based on the offsets computed above.
MyFlightbook does not do the above conversions.  Why?  Money.  There are services which can do precisely the computations above, but because of the large data set and the maintenance required to keep up with ever changing timezone rules, these are not free.  As a free service, it's dangerous for me to offer functionality that could result in unbounded potential expense.

For this reason, my suggestion is to convert local time to UTC before entering historical flights.

Monday, September 2, 2019

EASA currency and license revalidation

I did some updates over the past few days to better support EASA currency rules.

For a while, I've supported EASA LAPL (FCL.140) rules, which can be turned on in preferences on the website. 

If you turn this option on, I also default to EASA PPL rules where appropriate rather than FAA rules for regular passenger currency.  The EASA PPL rules (FCL.060) for carrying passengers are basically the same as the FAA rules (3 takeoffs+landings within 90 days), but they differ for night:
  • Whereas FAA rules require 3 takeoffs and landings to a full-stop between 1 hour after sunset and 1 hour before sunrise, the EASA rules require only one takeoff/landing, and it doesn't have to be to a full stop.
  • If you have an instrument rating, EASA imposes no particular night requirement.
The way that I've implemented this is that I look for a night takeoff and either a full-stop night night landing or a night touch-and-go landing within the past 90 days.  But if I see any evidence that you have an instrument rating, such as an instrument checkride, an IPC, or one of a few other things that qualify as an IPC, then I don't bother reporting night currency because it is then identical to (and thus redundant with) your regular FCL.060 passenger-carrying currency.

Note that I said "if you hold an instrument rating", not "if you have a valid instrument rating", or "if you have an instrument rating for the category or class".  The regulation is worded thusly:

(b) Aeroplanes, helicopters, powered-lift, airships and sailplanes. A pilot shall not operate an aircraft in commercial air transport or carrying passengers:
(1) …; and
(2) as PIC at night unless he/she:
(i) has carried out in the preceding 90 days at least 1 take-off, approach and landing at night as a pilot flying in an aircraft of the same type or class or an FFS representing that type or class; or
(ii) holds an IR;
(b)(2)(ii) above simply says "holds an IR", with no other qualifier, so I am treating that as being unqualified.

Another key difference in EASA land vs. FAA rules is that FAA ratings don't expire, but EASA ratings do need to be re-validated periodically.  This is like the FAA requirement to have a flight review.  But EASA adds a wrinkle to this: you need to do the validation within the 3 calendar months prior to the expiration of your rating. 

So, for example: suppose your rating expires Sept 30 2019 and is good for a year.  If you did your validation flight on July 15, 2019, then your rating is now good until Sept 30 2020; in effect, you can have as long as 15 calendar months as a result.  But if you did your validation flight on May 15, 2019, then your rating is now extended only until May 31 2020.

As a result, it is impossible to predict when a validation is required without knowing when your rating expires, which means that there is no way to escape having you enter those expiration dates somewhere.  And since the number of possible ratings is unbounded (due to type ratings), I can't enumerate the set of due dates that you need.

So here is my recommendation for dealing with re-validation of EASA ratings:
  • For each rating that you hold that requires re-validation, create a custom deadline (Profile->Preferences->Deadlines) that reflects the date by which the validation is due.  This will then show up in your currency.  Set it up to automatically extend by 12 or 24 calendar months, as appropriate.
  • When you do the re-validation, update the deadline to reflect the new date.  This will allow you to handle the 3 month window for performing the validation.
  • If you like, you can also set up a custom currency rule that looks for a flight review or IPC (to indicate revalidation) in an appropriate set of category, class, or model.  This will use a date extending by 12/24 calendar months, where you might actually be entitled to more, but at least this will give you a conservative date.
  • Note that re-validation of simple SEP ratings can be accomplished essentially by remaining current via LAPL rules, so you can track that simply by tracking your LAPL currency.

Friday, July 19, 2019

Rounding and totals

Minutes and decimals don't always play nicely together, since minutes are a denominator of 60 when converted to decimal.

As a result, someone will occasionally catch what appears to be a math error.

Consider these totals, and the three flights that make it up that a pilot sent me this past week:

At first glance, this looks incorrect, since 1.37+1.70+1.32=4.39, not 4.38.  But it's actually the best math that I can do, given that I want to keep per-minute accuracy.
In this case, both 4.38 hours (=262.8 minutes) and 4.39 hours (=263.4 minutes) both round to 263 minutes, which then converts to 4.383333333 hours, which displays as 4.38 since I round to two decimal places.

So the good news is that the rounding is only ever off by a hundredth of an hour here or there, and it cancels out statistically.  

Actually, I can make a stronger statement: I deliberately maintain to-the-minute accuracy at all stages - including in totals - but I don't promise to maintain sub-minute accuracy.

Here's where it's worth getting into some of the esoterica, but the important thing is that I'm actually optimizing for the math to always work in the hours:minutes space over the decimal space.

In order to do this, I convert the decimal to hours/minutes before adding. So, for example, 1.32 hours is 79.2 minutes.  I round that to 79 (nearest minute) and then divide back by 60 to get the hours input to the totals, which is 1.31666667 hours.

So in the example above,

Flight, As Logged    Flight, rounded to nearest minute
1.37 1.366666667
1.7 1.7
1.32 1.316666667
Total, Logged:   Total, rounded:
4.39 4.383333333


The left column above is raw addition of the values as entered.  The right column has each of those numbers multiplied by 60 (to get minutes), rounded, and then converted back to hours.  That sums up to 4.38333, or 4.38 hours.  Because each of the numbers in the right column represents a precise minute count, the sum represents a precise minute count, so no minutes are lost or added; this is why I can make the claim that all values are accurate to-the-minute.

Doing it this way keeps the math working regardless of whether you use hh:mm (hours:minutes) or decimal hours. 

It's worth noting that if you're using decimal and only use one decimal place (which is 6 minutes), then there's no rounding issue whatsoever, since 6 minutes precisely equals 0.1 hour.  In hh:mm format, though, you need at least two decimal places to capture all 60 possible minutes in an hour.  But conversely, 2 digits actually gives you 100, not just 60, possible slices of an hour, so there's inevitably some rounding that happens somewhere.

Computers and databases only store so many digits of precision - I chose 2 digits because it's enough to accurately handle minutes in hh:mm.   The conversion I do above (multiplying by 60 and then rounding to get whole minutes) restores as many digits of precision as the computer can handle, which will always be enough for any actual logbook to not have any rounding errors.

Some logbooks store all times under-the-covers as minutes and divide by 60 in the display; that works fine (it's exactly the same as doing the right-hand column above without the division by 60), but it too would have rounding issues.  After all, imagine if you entered 1.31 hours (=78.6 minutes which becomes 79 if you're storing minutes in the database).  When reading from the database and converting for decimal display, that would display as 79 / 60 = 1.3166667 = 1.32 hours.

Yet another alternative is to store lots of digits of precision in the database, but that has its own problems: the math works fine, but putting long decimals into fields you can edit can be cumbersome for you, the user, and leads to other problems as well.  E.g., that 1.316666667 number above is too large to fit in many fields on a screen so it would need to get truncated to, say,
1.3167 - and if you then read that field back (for example, when updating a flight) then presto, you've lost the very precision you were trying to preserve.

So it's an interesting anomaly of decimal display that sometimes the hundredth's-place digit in totals appears to be off.  But yes: since I can promise that all numbers - both at the individual flight level and in totals - are accurate to the minute, then I can also promise that any accumulated rounding error - using to-the-minute flights - is also less than one-sixtieth of an hour.  And since .02 is more than one-sixtieth, and I only have two decimal places, any such rounding discrepancy (I shouldn't even call it "error") should thus actually be limited to 0.01.  And in hh:mm display, there will be no such rounding discrepancy.

Tuesday, June 18, 2019

Flight Templates

MyFlightbook has over 640 different "flight properties" (with new ones added all the time!), which are attributes that you can add to a flight, describing everything from Aircraft Carrier landings to Zero-visibility Takeoffs.  The idea is that any given pilot, on any given flight, uses only a tiny subset of these properties.  This, of course, presents a clutter problem: how do you manage such a large set of potential options?  Historically, I've done this automatically, showing you those properties that you've used before, with an option to explicitly exclude ones you no longer need.

Today, I'm adding new "template" functionality.  The idea is that you can define templates for various sorts of flights, and choose the template that is appropriate for a given entry.  E.g., if you fly for the airlines during the week, but fly gliders on the weekend, you can load up one template for each kind of flight, optimized with the fields you need most of the time.

A template is really nothing more than a collection of flight properties.  You can define your own templates, or choose from a library of templates authored by other pilots.  There are also a few "automatic" templates that the system makes available and applies automatically (discussed below):

Creating Templates

You can define templates by going to "Preferences" under the Profile tab on the website and expanding the "Flight Properties" section.  You'll see a list of your current templates:



Possibly the easiest way to get going with templates is to choose one from a library of templates shared by other pilots.  If you click "Brows available templates", you can browse this library and copy any that you like into your account.

If nothing in the library suits your needs, you can create a new template:

You can give your template a name, a description, and a category.  Then you'll see two lists.  On the left are the set of available properties; on the right are the properties in your template.  Drag-and-drop from left to right to select the properties you want (or from right to left to remove a property you no longer want).  You can also type in the search box to quickly filter properties by name.

The "Category" of a template is just a grouping mechanism.  At the moment, there are 5 categories, though I may add more over time if it makes sense.  Current categories are:
  • Automatic - These are implemented by the system; you can't create these.
  • Training - Flights where you are honing specific skills, such as performing aerobatic maneuvers or instrument approaches, go here.
  • Lesson Plans - Use for flights that are following a specific lesson of a syllabus.
  • Checkrides and Reviews - checkrides and other periodic flights to ensure proficiency like a regulatory/company/club-mandated periodic review of flight skills
  • Missions - Specific purposes for a flight might go here.  E.g., fire fighting, search-and-rescue, charity flights, and so forth.
  • Roles - These are for templates that vary based on your role in a given flight - e.g., are you PIC or SIC? Instructor or student?

Once you save the template, it is available for use.
The two checkboxes in the image above warrant additional explanation:
  • Checking the "Shared" checkbox makes the template available for other pilots; unchecking it removes it from the library of templates.  If you have made a template that works well for your scenario and might work for others, then I strongly encourage you to please check this box!
  • "Use by default" tells the system that you want that template's properties to appear by default for new flights.

Using Templates

Great, you've defined some templates.  So how do you use them?

On the website, you'll see a downward-facing arrow to the right of where you can select properties today:

When you click that arrow, you'll see the set of templates from which you can choose.  As you turn templates on or off, you'll see the set of properties displayed for editing change accordingly.  (Note: if you have any property that has a non-empty value, it will always be displayed, regardless of template selection.

You can choose from the set of templates that you've defined, plus the automatic templates I mentioned earlier.  At the moment, there are three of these:
  • Previously Used - This matches the pre-template functionality.  It contains all of the properties that you've used on prior flights, minus the ones you've explicitly excluded (in Preferences).  This is what is used if you don't check the "Use by default" box for any other templates.
  • Simulator / Training Device (Basic) - this is automatically selected whenever you choose a simulator as the aircraft for a flight.  It (currently) adds two properties ("Ground Instruction Received" and "Simulator/Training Device Identifier") to whatever other properties you are using.
  • Anonymous Aircraft (Basic) - this is automatically selected whenever you choose an anonymous aircraft, and adds a property ("Aircraft Registration") where you can record the specific aircraft used for a flight.
The iOS and Android apps are now updated as well to include template functionality.  On the iOS app, tap the information icon on the right side of the Properties header to view available templates (you may need to refresh your property list for this).  On Android, there is a "View Flight Templates" menu item.  The apps respect default templates, but to create/edit templates you do need to use the website.

"Power template tips"

  • Templates are not mutually exclusive - you can use more than one at a time, or specify that more than one should be used by default.  E.g., if you're a CFII, you might create an "Instrument Flight" template and an "Instructor" template and use them both at the same time.
  • You can attach a template to an aircraft.  Tap on the downward-facing arrow to the right of the aircraft (on the website) and you'll see any templates you've defined.  Whenever you select that aircraft for a flight, the specified template(s) will be used.  For example, if you fly aerobatics in one plane, but not in others, you might define an aerobatic template and use it for flights in that aircraft, but not clutter up flights with aerobatic maneuvers you won't perform in other aircraft:

  • The mobile apps refresh templates from the website when they download properties, which happens periodically.  You can force a refresh, though, by doing pull-to-refresh (try to scroll past the top of the screen) while viewing templates or properties.
Please send me any feedback about templates, and please share any useful ones that you create!

Tuesday, May 28, 2019

What constitutes a "valid" flight entry?

With any data system, one must be prepared to do validation on the data that goes in.  A logbook is no exception to that rule.

It turns out, though, that there are surprisingly few validation checks that can be universally applied to a flight - there are a lot of things that look like an error in some scenarios, but which are perfectly valid in others.

An example that I am asked about frequently is that the system does not flag flights where Dual plus PIC plus SIC does not equal Total time.  For much of flying in much of the world, that equation is satisfied, but (in particular) it is not here in the US, where you can simultaneously log Dual and PIC if you're appropriately rated for the aircraft yet receiving instruction.

Probably the most common scenario where a flight frustrates data validation is "catch-up" flights, where you make one or more entries in your logbook to represent totals from prior (typically paper) logbooks.  Such flights typically include large numbers (larger than any single flight could actually have), and a mix of things that might be difficult or impossible to do in a typical actual wheels-up-to-wheels-down scenario.

Over the years, it seems that whenever I put in a validation check, I soon find counter examples of perfectly acceptable flight entries that violate my rule.

So in an evolutionary process of "survival of the fittest", here are the checks that have withstood the test of time:

  • Valid aircraft - every flight must be associated with an aircraft (even if no actual flying was done; you can generally use any aircraft you like for ground sessions - since the times are zero, any aircraft will work).  This is because the aircraft's model determines all sorts of attributes about the flight, such as the category/class, whether it was complex or high performance or turbine, etc.
  • No negative numbers.  I've yet to find a scenario where negative numbers are allowed.
  • Hobbs start after hobbs end.  (I don't currently validate tach time because I don't currently perform any computations on tach time).
  • Flight start after flight end or engine start after engine end (I don’t currently validate block time) 
  • Full-stop night landings + full stop day landings greater than the total landings (unless total landings is 0, in which case I auto-fill it)
  • Full-stop Night landings indicated without any night flight.
  • Night takeoffs at towered airports + night takeoffs at non-towered airport (which, kinda by definition, is all of the possible night takeoffs) is greater than total night takeoffs
  • More described approaches (e.g., a property indicating two ILS approaches) than logged approaches
  • Comments or Route field too long (13K and 128 characters, respectively)
  • Date before 1900 or more than 2 days from "right now" in Pacific time

Wednesday, May 15, 2019

International functionality Part 3: Functionality

In my previous two posts, I discussed how internationalization affects languages and regional conventions; in this third and final post, I will discuss actual functional changes that vary based on different jurisdictions.

While most software functionality does not vary worldwide (think Microsoft Office or the Chrome browser, which do the exact same things wherever they are), other software must be responsive to local markets and the rules, regulations or conventions therein, which means actual changes in functionality depending on where you are.  While aviation is largely harmonized across the world, it is nevertheless governed by each country and that results in a wide variety of rules.

At one level, simple logging of data is not really dependent on local rules.  After all, what you did on a flight is what you did regardless of where you are. The complexities tend to arise when performing things computations or reports on that data.

A challenge here compared to the language or regional conventions discussed in the prior two posts is that those can typically be determined automatically.  But functional rules generally need to be declared explicitly, because it is not uncommon for someone in one jurisdiction to follow the rules from another jurisdiction.  As a result, all of the functionality I'll describe here are things that are configured explicitly (generally in Profile->Preferences on the website)

Probably the most important (or visible) functionality that can vary is currency rules. By default, MyFlightbook implements US (FAA) rules.  MyFlightbook does also support Canada currency and EASA LAPL (European Light Plane) currency rules.

The FAA "groups" currency by category/class/type, so if you do your takeoffs and landings in a Piper Archer, you're current in a Cessna 172 as well, and vice versa.  But some countries require currency to be specific in a model: you need to have performed your takeoffs and landings in that model in order to be current in that model.  MyFlightbook supports either model.  You can also choose to view your totals grouped by category/class/total, or by model.

Different countries have different certification rules for pilots.  In addition to FAA rules, MyFlightbook supports some EASA, Canadian, and Australian ratings.  Adding new ratings is generally pretty straightforward, so if you can point me to a reference document, send it my way and I'll see what I can do.

Another visible place where different regional conventions are on display is in printing formats.  Some regions, like the US, specify what you should record, but make no particular recommendation on the form or layout in which it is displayed.  Others (Europe) can be very prescriptive (see prior posts about printing here and here).  MyFlightbook currently supports layouts that approximate the EASA standard, as well as layouts that conform to typical layouts in South Africa, Canada, and New Zealand.  If you have an additional layout, send it to me; it's generally pretty easy to add.

There are a few other bits of functionality that, while not strictly international or regulatory, do tend to correlate with region:
  • Input or display of times in decimal vs. hour:minute (HH:MM) format.  You can turn this setting off/on in Profile->Preferences on the website, or in settings on the mobile apps.
  • How night flight and night landings are computed.  You can set this on the web site next to the "autofill" button, or in settings on the mobile apps.  Night can be computed based on sunrise/sunset, or an offset from the start/end of civil twilight.  Night landings can either be anything at night, or 1 hour offset from sunrise/sunset.
  • On the mobile apps, you can also adjust how total flight time is computed from flight/block/engine times.

I'm a US-based pilot and fly on FAA conventions, so that's what I know best, but my goal is for MyFlightbook to be useful to pilots worldwide.  I hope this series of posts help explain MyFlightbook's international support, and I hope you'll contact me if there's any functionality you'd like to see (or bugs I need to fix!)

International functionality Part 2: Local conventions

In my last post I discussed how MyFlightbook handles different languages.  In this one, I will discuss how MyFlightbook handles regional differences.

Language and Region are independent variables.  E.g., English is spoken in both the US and the UK, but we express our dates differently.  I am writing this on May 15, 2019.  In the US, the short form of that date would be written 5/15/2019 (i.e., month/day/year), but in the UK, it would be 15/5/2019 (day/month/year).

Besides dates, there are several other conventions that vary based on locale:
  • Times.  E.g., by default is 4:15pm expressed  as "4:15 PM" or as "16:15"?
  • Decimal points and thousands separators.  E.g., one-thousand two-hundred fifty-two and a half would be "1,252.5" in the US or "1 252,5" in France.
  • List separators: typically a comma or a semicolon.  This is particularly important for CSV
  • Currency symbols.  Obviously, the US uses $, but Europe uses €
All modern operating systems provide services that software like MyFlightbook can use that makes all of this automatic and transparent.  MyFlightbook uses those services, so all conventions should be followed appropriately.

The trick is to ensure that MyFlightbook knows which region should be used.

For the apps on iOS or Android, you can set your device's region by going into the device's settings app.  There's a language and region area where you can set both the preferred language (as discussed in the last post, the iOS and Android apps are translated into French as well as English) and your preferred region.  Most people do not need to do anything here because their device comes pre-configured for their language and region.

The website gets slightly more complicated because it is one instance of the software that is running on a machine in the US (in the cloud somewhere; I actually have no idea where), so it is using US conventions, but it needs to service people from all over the world.  How to solve this?

Whenever your browser requests a page, it sends a list of language-region codes along with the request.  A language region code looks like "en-us": the "en" part means it is requesting English language, and the "us" part means it wants to use US conventions.

The list of these codes is in priority order.  So a request might include the following list: "en-us", "en-gb", "fr-ca", "fr-fr".  This tells the server that English is preferred, then French.  And that the preferred regions are US if possible, then UK ("gb" = "Great Britain"), followed by Canada, then France.

Note that this is sent by the browser, so if you are using a Windows or Mac OS with, say, French Canadian conventions, but your browser is set up for English/US, then you will get English.  The MyFlightbook server can't see your OS's settings, it can only see what the browser sends.

This can be set in various ways, depending on the browser.  In Chrome, you'd go to settings (using the menu or the URL chrome://settings/), then go to advanced, and you can specify language/region there:

In Firefox, you'd go to Options (or about:preferences) and find Languages from there:



In my next post, I'll talk about regional functionality.

International functionality Part 1: Languages

In the software world from which I come (I'm an alum of Microsoft and Expedia), we would think of internationalization along three dimensions: translation into a local language, localization to use local conventions, and functionality that varies by locale.  I figured it might be worth a discussion of how MyFlightbook breaks down along these dimensions.

I'll talk about each of these in successive blog posts, starting here with the first: translation.

Translation is pretty straightforward, albeit very lightly implemented.  While I know varying degrees of several languages, I'm essentially monolingual.  The fact that English is the world-wide language of aviation certainly makes it easier for MyFlightbook to get away with being all English than for other software programs, but nevertheless I am rigorous about ensuring that all of the code - whether on the website or in the mobile apps - can be localized and is not tied to English, even if much of the time English happens to be the only available language. 

In fact, thanks to a French-speaking user who did the initial translation (and Google Translate, which helped with subsequent translations, which might be humorous, but I wouldn't know...), the iOS and Android apps are entirely bi-lingual.  If you set your iOS or Android device to use French, the MyFlightbook UI will appear in French.

It's not seamless, however: much of the text used in display does come from the server, and the server is only lightly translated.  So if you are using French settings, you may still see English inserted in numerous places because that text derives from the database or from the web site (which only has a few pages translated.)

The key thing, though, is that the code is structured to be easily translated.  Specifically, this means that all text is kept outside of the code and loaded (based on language) as it is needed.  Keeping the text separate from the code makes translation easier, since a linguist can take a file with text in it and just go through and translate each item, without having to have any coding capabilities.  And it means that new languages can be added simply by adding appropriate translated text files.

If anybody is interested in helping to translate the website, all of the text is separate from the code, so it's pretty straightforward to do.  (It's just a lot of text...)

Supporting different languages actually goes beyond just translation, though, particularly since MyFlightbook *pilots* speak and use a huge variety of languages.  Most of this is pretty transparent - the system uses Unicode so it can handle data in Kanji, Hindi, Hebrew, Arabic, etc. without any issues.  The main thing that the code needs to handle here is right-to-left languages like Hebrew or Arabic and ensuring that the appropriate alignment occurs based on language (i.e., not hardcoding left or right alignment, but instead keying off of the language).


In my next post, I'll talk about localization.

Wednesday, May 1, 2019

Drones and MyFlightbook

Probably the fastest growing area in aviation these days is in the unmanned aerial system ("UAS", aka "unmanned aerial vehicle" or "UAV", or more colloquially, "drone") space.  And many UAS pilots are using MyFlightbook to record their flights.

MyFlightbook supports UAS as a psuedo-category/class.  E.g., as a peer to AMEL or Helicopter.  You can create UAS aircraft using one of many UAS models on the system, and include drone flights next to manned flights.  Since they are separate category/class, flights in one should not pollute things like currency or totals in the other.

Of course, since these are flights in your logbook, any times you record will accrue in your totals.  But alas, it's also easy to back these out, if you like, by using the search functionality.

There are a variety of flight properties that are in the system today that are focused on UAS scenarios.  As of this writing (more are added all the time!), the system has the following:

Property NameDescription
UAS - AutonomousIndicates that the flight was an autonomous UAS flight
UAS - Hand-held TransmitterIndicates that the UAS flight was controlled by a hand-held transmitter
UAS - Lost Link ReturnIndicates that the UAS executed return procedures after a loss of communication
UAS LaunchesNumber of times that a UAS (drone) was launched
UAS RecoveriesNumber of times that a UAS (drone) was recovered
UAS: Air Vehicle Operator TimeTime spent operating a drone
UAS: Mission Payload Operator TimeTime spent managing the paylod in a drone
UAS: Ground Control Station TimeTime spent in ground control for a drone
UAS: Maritime Flight HoursTime spent flying a drone (UAS) over water
UAS: Electro-Optical Sensor TimeTime spent using an electro-optical sensor (drone/UAS)
UAS: Infrared Sensor TimeTime spent using an infrared sensor (drone/UAS)
UAS: Short Wave Infrared Sensor TimeTime spent using a short-wave infrared sensor (drone/UAS)
UAS: Medium Wave Infrared Sensor TimeTime spent using a medium-wave infrared sensor (drone/UAS)
UAS: Synthetic Aperture Radar Sensor TimeTime spent using a synthetic aperture operations with a drone (UAS)
UAS: Hyperspectral Imaging Sensor TimeTime spent doing imaging (hyperspectral) with a drone (UAS)
UAS: Multispectral Imaging Sensor TimeTime spent doing imaging (multispectral) with a drone (UAS)
UAS: Signals Intelligence TimeTime spent doing signals intelligence with a drone (UAS)
UAS - 107.73 - Aeronautical Knowledge TestIndicates that the pilot took and passed a knowledge test (initial or recurrent) covering the areas specified in 107.73
UAS - 107.74 - Training CourseIndicates that the pilot successfully passed a training course (initial or recurrent) covering the areas specified in 107.74


As part of ensuring that unmanned aircraft are utilized safely - and don't conflict with manned aircraft! - the FAA introduced part 14CFR107, governing unmanned systems. 107.65, in particular, defines recent experience required to operate a UAS under many circumstances.  It works like currency, except that it focuses on recent knowledge training rather than flight experience.

To be current per 107.65, you must have done one of the following three things in the preceding 24-calendar months:
  • Pass an initial knowledge test, 
  • Pass a recurrent knowledge test, or 
  • Have a valid flight review (of the manned flight variety, per 61.56) and take a knowledge course.

To indicate that you have done either of the first items above, add an entry into your logbook with the "UAS - 107.73 - Aeronautical Knowledge Test" property; if you take the appropriate course, add an entry with the "UAS - 107.74 Training Course" property.  And, of course, if you are a licensed pilot of manned aircraft, you'll want to show that you have a valid flight review anyhow; you can do this by adding a property to the appropriate flight: "Flight Review," "BFR", or one or the various checkrides that qualify.


MyFlightbook will show (and update) 107 currency once you have met any of the requirements above.

Tuesday, April 23, 2019

Adding and editing aircraft - Update

A few months ago, I discussed how models get assigned to aircraft when you add a new aircraft, or when you edit an existing one.  This bit of code has always been surprisingly complex and convoluted, but over this past weekend I went in to add some new intelligence to it and was able to clean it up in the process.

The whole complexity here arises from the fact that MyFlightbook tries hard to share aircraft among pilots (for reasons discussed here).  That is, if two or more pilots fly N12345, I want there to be only one instance of N12345 in the system, used by each of those pilots.

This leads to some interesting scenarios, so I thought I'd geek out a bit and describe them here, including the enhancements I just made.

The key to the new enhancement is the notion of finding a "close" or a "perfect" match for an aircraft within a set of aircraft that share a tailnumber: 
  • A "perfect" match means that the model of one aircraft is exactly the same as the model for the other.  E.g., a Cessna C-172N is a perfect match for a C-172N, but not a perfect match for a C-172S.  
  • A "close" match is one where the category/class of two aircraft is the same AND they have the same non-empty ICAO identifier.  E.g., a C-172N and a C-172S both have the ICAO identifier "C172", so they are a close match.
  • The "best" match out of a set of aircraft is a perfect match, if one exists, otherwise a close match, if one exists.  There is not always a "best" match.
OK, so what happens when you *add* an aircraft to your account?  There are now four possible outcomes:
  • If there is no aircraft in the system with that tail number, it is simply added and the model you specified is used.  Piece of cake, very simple, exactly as you'd expect.
  • If there are already one or more aircraft with the same tail number in the system, then I try to find a perfect or close match.  
    • If a perfect match is found, then that aircraft is added to your account.  Just like above, and as you'd expect, but you might acquire some images, notes, and maintenance in the process.
    • Otherwise, if a close match is found, then that aircraft is added to your account, but I send you an email telling you of the substitution (e.g., you added a PA28-161 but it's actually a PA28-181.)
    • Otherwise, I create a new version of the aircraft using the model you specified.  E.g., if you specified N12345 is a Boeing 737 but N12345 is already in the system as a C-172, then the C-172 is left alone and a new Boeing with tail N12345 is created and added to your account.  This is the new enhancement; previously, you'd have picked up the C-172 and received an email; you'd then have to edit N12345 to be the Boeing 737.
Now you have an aircraft in your account - what happens if you try to edit it?

Simple edits like adding notes, pictures, or maintenance events are straightforward - the underlying aircraft is edited.

But things get complicated in two additional scenarios: modifying the model of the aircraft, and/or modifying the tail number of the aircraft.

I discussed editing the model of the aircraft in my earlier blog post; this is essentially unchanged (and indeed used the notion of perfect/close match described above).  So if you edit a Super Cub to be on floats, or edit a Cirrus SR22 to be an Airbus A-320, the system will automatically clone the aircraft for you, with two minor qualifiers/exceptions:
  • If the alternative version already exists, then instead of cloning the aircraft, it will just re-use the existing clone.
  • If you're the only pilot using the aircraft, then no clone is created; I just edit the underlying aircraft, unless there is already an alternative that meets the "best match" criteria above, in which case that match is used.
There had been a corner case here that my enhancement has mitigated: suppose you owned an aircraft with vanity registration NABC, but then bought a new aircraft that isn't the same model, and carried NABC over to the new aircraft.  If you were the only pilot using NABC, there had been no way to get both versions of NABC into the system side by side without contacting me (I have an admin tool to do this).  But with the enhancement above, you can now just add the new version of NABC to your account, and the cloning should occur automatically (assuming there's no "best" match).

A similar issue arises when you edit the tail number of an aircraft in your account.  Usually, there is no reason to edit an aircraft's tail.  (After all, if an airframe gets a new registration, it generally makes the most sense to treat it in MyFlightbook as a new aircraft.)  So the primary reason for doing this is to handle a typo.

There are a few scenarios here, so let's assume you're editing N12345 to be N54321.
  • If you're the only one flying N12345:
    • If N54321 is not in the system, the existing aircraft simply has its tail changed.  Because the existing aircraft is changed, all of your flights in N12345 magically become flights in N54321, not because the flights themselves are changed (they aren't), but because the underlying aircraft they use has changed.
    • If one or more versions of N54321 are in the system, then the best match (as described above) is simply added to your account, or else a clone is created (if there is no best match).  No flights are modified, so in this scenario your flights do NOT reflect a change.
  • If other pilots are flying N12345, then I explicitly do NOT want to modify N12345 in the database (thereby changing their logbooks).  Therefore, I treat this as the creation of a new aircraft and it follows all of the rules for adding a new aircraft above.  Assuming that this is most likely due to a typo, though, the system detects this scenario and modifies your flights to be in the newly added/created aircraft.
Phew.  Who would have thought that adding/editing of aircraft would be so complicated?

Wednesday, March 20, 2019

Telemetry and units for altitude and speed

A pilot contacted me the other day to ask this:

Using the exact same GPX file generated from Bad Elf. If I create a flight from it on the iPhone app, by sharing it from the Bad Elf app, or as a file from Files app, the Altitude of meters and Speed of m/s both get converted properly to feet and knots when viewed on the web site. Using the exact same file on the web page will not cause the conversion to feet and knots to take place, and we get altitudes that are 1/3 the correct, and speeds about 1/2 correct. What is going on?


For the most part, Telemetry on MyFlightbook is unitless.  This helps in some areas but can be a bit  confusing in others.

Here is where it is important to distinguish a format from a schema.  A format is simply the way that data is represented in a file.  CSV and XML are both formats (and both text-file based).  CSV is a simple table with each line of text represents a row in a table, and columns within a row are separated by a comma (hence "Comma Separated Values", or CSV).  XML uses start and end tags (e.g., "<altitude>48.3</altitude>") to delimit data.  But note that while a format tells you how to read the data, it doesn't say anything about how the data should be interpreted.  It could be literally anything, as long as it's correctly formatted.

A schema is a convention for how data is interpreted.  E.g., declaring that an altitude is labeled "altitude" and is represented in meters.  GPX and KML are two common ways to represent telemetry, and these are both XML-based schemas.  That is, their format is XML, but the data is arranged in a specified manner that allows you to interpret it correctly.

GPX and KML use meters for altitude and meters/second for speed, and MyFlightbook (both web and iOS/Android) knows this when importing; it can thus infer reasonable speeds to use for takeoff or for landing.

CSV is a significantly more compact and extensible format than XML, but there is no "CSV Schema"; the data can be whatever you want in whatever units you want.  Because it is compact and can include MyFlightbook specific data (such as noting when a takeoff or landing occurs), the MyFlightbook mobile apps generate CSV.  And, since feet and knots are generally what aviators around the world are familiar with, those are the units that MyFlightbook uses in its CSV file. 

But since you can upload CSV from any number of sources (engine monitors, GPS logs, etc.), MyFlightbook can’t make any assumption about the units used; I just have a dictionary of column headings that have some semantic meaning to me (“Heading”, “Altitude”, “Speed”, “Oil Temp”), where I can at least determine the type of the data (number, date, time, latitude/longitude, etc.), but I can’t assume units. (OK, I suppose “Heading” is only in degrees, but my other examples here are inherently ambiguous).  Any data with a column heading that is not in the dictionary is simply ignored.

You may notice that when viewing telemetry on MyFlightbook, units are not displayed, and this is why.  It is also why MyFlightbook's default units in the CSV it generates are feet and kts; that way the numbers “look right” (even in the metric world, where people can work with altitudes in meters just fine, most people don’t think in terms of meters/second).

Both the iOS and Android apps can import GPX/KML (or even NMEA, on iOS, which is yet another schema) and create a flight from it.  So why do the units convert to ft/kts when doing this?

The iOS/Android apps import by treating the data that as an alternative GPS source.  So they're not directly attaching the data to the flight. Instead, the architecture is more like this:
I.e., the system for detecting takeoffs/landings receives data in real-time from the physical GPS (typical) OR from a fake GPS data stream that derives from a file; it doesn’t (in fact, can’t) distinguish the source.  Since the input file has a schema, the system knows which units to use and can convert as appropriate to determine takeoffs/landings/etc. 

As it is fed the data and detecting the flight, it is also optionally recording the flight, which as I described above, it does using CSV and using feet and knots; this is what is submitted up to the server when the flight is saved.  

So the original GPX/KML/NMEA used for import is lost; it’s a data source, but think of it not as a data source for your flight, but rather as a data source for the GPS emulator. 

On the web, the process is similar, but there are three key differences: 
  • There isn't an actual GPS (it’s always from a file)
  • You’re always attaching the file and optionally detecting, which is the reverse of the mobile apps (which always detect and only optionally recording the result)
  • You can attach/autofill from CSV
This has a couple of implications.  One is that the web does not generate a telemetry file and instead attaches what you submit directly and with no translation.  

And while the input units for GPX/KML are specified, that's not true for CSV.  MyFlightbook's graphing system (which is web only) needs to work with all of these formats, so it has a layer of abstraction built in which converts whatever underlying the data format is into a simple table (rows/columns) of data, where each column has a label (e.g., “Speed”, “Oil Temperature”) and a data type (“number”, “timestamp”, etc.).  The graphing system at that point has no idea about semantics or units; it just graphs the raw data.  So a GPX file will graph in meters and meters/second, while a CSV file would (probably) graph in feet and knots, but the only way you'd be able to distinguish is to look at the values: if you see "35,000" in the altitude, it's probably feet.

(I have had a request to allow you to apply a conversion factor at display time, so that if you know the data is in metric you can convert to ft/kts at display time, but I haven’t gotten around to that.)

This works just fine until you go to download the data from the website.  Downloading in the original format is easy: no translation is required; if it was GPX, it is still GPX.  

But what if you want a KML version of your data (to display in Google Earth, for example) and the original data was CSV?  The problem is that KML has to be in meters and meters/second, but the CSV may have been feet and knots.  For this reason, when you download your data in a format that has a schema, you are asked to declare the units for speed/altitude in the original data. It will then load the data into a table (as described above), apply the conversions, and then render into the correct output. 

So, for example, if you initialized a flight on your iPhone from Bad Elf data and saved it, that should have saved in CSV format with ft/kts (which you can verify this by downloading in original format).  If you want a GPX version of that flight, you would download GPX and declare that the original units were knots and feet; that tells the system which conversion factor to apply to the CSV data to produce valid GPX.