Terrestrial Navigation

Amtrak, B-Movies, Web Development, and other nonsense

Page 7 of 7

Draining the swamp

It’s best to imagine WordPress’s plugin ecosystem as a swamp. Swamps are terrible. You don’t want to be there. You run a constant risk of disease and/or drowning. Anything that sinks into the swamp–it’s not coming back.

Belarus-Peat Mining near Rudzensk-Swamp-2

I’ve been debugging an odd problem on our WordPress installations involving categories. On some sites, posts which are in have multiple categories don’t display more than one category. That would be strange enough, but the category permalinks are coming out in the format SITE_URL/category/foo with the title baz, where foo is one category and baz a different category:

<a href="http://my.wordpress.site/category/category1">Category2</a>

Strange, seemingly non-deterministic behavior? The usual suspects would be database corruption or a theme bug. Yet neither seemed likely in this case. Database corruption usually isn’t so…predictable…and we quickly verified that this error was occurring in both our custom themes and stock TwentyTwelve. That would leave a core bug (unlikely with something so fundamental, but still possible) or a bad plugin.

After several patient hours of tracing execution I’d narrowed the problem to the function WordPress uses when building up the category list: the_category(). The category link string was correct before going in for formatting and it came out mangled. WordPress uses filters to allow plugins to “hook in” and modify output. A search of our plugin code revealed the culprit: Remove Title Attributes.

WordPress adds title attributes to links by default, a behavior which apparently annoys the hell of many people, including at least one person at Lafayette in the past. This plugin simply removes them with a regex (I would be remiss if I didn’t link to the famous StackExchange thread about why you should never, ever, parse HTML with a regex). To accomplish this the plugin added a filter which washed the generated category code through its regex.

Unfortunately, the regex is improperly written. In jargon, it’s greedy. This is the expression evaluated:

` title='(.+)'`

If you pass a string with multiple URL fragments it’s going to match beginning on the title tag of the first URL and ending on the end tag of the last URL. A more properly focused regex would be this:

` title=\"([^"]*)\"`

That’s it. Mystery solved.

Unresolved, however, is the larger problem with the WordPress plugin ecosystem. This plugin was added to the plugin repository in August 2009. It has never been updated since. It has been broken from the very beginning. The author has disappeared. The support forums are moribund. There’s no github repository for me to fork, should I want to continue support, since WordPress in its infinite wisdom uses SVN for everything. Spend some time Googling and you’ll find people talking up this plugin, never realizing the problems inherent. It’s still being downloaded. This may be inexperience (I’m a Moodle veteran and new to WordPress) but I don’t see a good way to get the word out that this plugin has a serious bug. If WordPress allowed you to usurp a plugin then I could push out an updated version so at least you’d get notified in your Dashboard. All I can do is leave a review indicating that it’s broken in 3.5.1 (for this specific use case) and link back to this post.

Not that it matters overmuch in this case since we’re likely to deep-six it here, but the situation feels inadequate. There’s got to be a way to do better.

eAmtrak, Part III

Yesterday I showed my phone to gate agent in Chicago and successfully boarded the Wolverine. This morning we boarded the Blue Water in Kalamazoo using only a phone. Our conductor beeped the QR code on the screen without incident.

Folks, I’m here to tell you that e-ticketing works. The only open question is how well these trips post to my rewards account. I don’t expect problems but I’ll check in a week or two to see if the points post. As I said in Part I the only thing missing from the app is my room and car assignment on the sleeper, and that’s only for my benefit.

Previous posts about e-ticketing:

eAmtrak, Part II

Yesterday I discussed Amtrak’s rollout of eticketing nationwide. I outlined four tasks which required a proof of ticket and which I hoped to accomplish with my phone alone. So far, we’re two-for-two. At the baggage counter, the attendant didn’t bat an eye as I offered her my phone with the eticket displayed. Our bag was ticketed through to Chicago and whisked away. Painless. At the Club Acela, I showed my phone again and the attendant verified that we were ticketed for a roomette on today’s Lake Shore Limited, allowing us access. Two steps to go.

As an aside, the baggage attendant had no problem with ticketing our bag to Chicago even though our ultimate destination, Kalamazoo, has no baggage service. I’m still puzzled by Seattle’s refusal to do the same thing in May 2011 with the Empire Builder, and I have to assume it was because of the endemic delays at that time (those delays will be covered in a future post).

eAmtrak, Part I

This summer Amtrak rolled out e-ticketing on all its routes. This is long overdue and a step in the right direction, not just in itself but for the efficiencies which should follow. One of the interesting features of the old system is that the paper tickets had cash value–that is, they were important in themselves. I once had to mail my actual ticket stubs via certified mail to 30th Street Station in Philadelphia in order to procure a refund (long story, and Amtrak fulfilled my request). With e-tickets Amtrak’s on the same footing as the airlines–your e-ticket holds no value of its own. This is a huge step forward.

And tomorrow I’m going to find out how well it works. I’m going to try to do all the following with my phone (I do have printouts available as a quick safety):

  1. Check a bag through to Chicago
  2. Gain entry to Club Acela (Amtrak’s lounge at Penn Station for First Class and sleeper passengers)
  3. Board the train (thus satisfying the gate agent, an institution Amtrak can abolish whenever it wants)
  4. Get my actual ticket checked.

I’ve already noticed a limitation that will probably require the printout for step #4. When you book a sleeping accommodation with Amtrak (in effect, a hotel room) you’re assigned to a car and room. This information is on the printout. However, it’s not visible on the phone. Doing this with the phone alone I would have no idea where my room was. The New York section has two sleeping cars (normally); each has two bedrooms, a handicapped-accessible bedroom, and twelve roomettes.

The last time I took the Lake Shore Limited was in May, before the nationwide rollout. I’m honestly curious to see the effect on boarding procedures. I’ve boarded at all four stations I’ll be using this trip (New York Penn, Chicago, Kalamazoo, Milwaukee) so I have a basis for comparison.

How to Screw Your Developers

I’m a Moodle developer by trade, with some administration duties thrown in for laughs. I see to the care and feeding of Lafayette College‘s Moodle sites. In addition, I handle some development and code management duties for the Collaborative Liberal Arts Moodle Project. All this is a long way of saying I push a lot of code around in a way that requires me to work with dozens (hundreds?) of developers whom I’ve never met. This means I have to document my work and develop against actual APIs. Further, working for an institution with thousands of students, staff, and faculty means that all our maintenances are published and (save emergencies) occur outside business hours. I can’t just shoot from the hip.

Gravatar is an online service which allows you to upload an avatar which will then be populated to other services. You don’t realize how many places use Gravatar until you upload an image and suddenly see yourself all over the web. It’s pretty cool. Gravatar provides a simple API so that you can add this functionality to your own website via web services. Moodle added support for Gravatars in the 2.2 release which dropped in December 2011. We turned it on at Lafayette since it’s easier than making thousands of people upload files.

So far, so good, right? Enter chaos.

Thursday morning we started seeing hundreds of broken user profile images on our Moodle instances. I knew we hadn’t touched anything. Stranger–we saw lots of Gravatars still appearing so it couldn’t be a recurrence of last Spring’s incident when Gravatar was unavailable. Cue an hour of tedious debugging until arriving at the conclusion that default image support had stopped working.

Gravatar’s API allows you specify a default image, to be used if the user doesn’t have a Gravatar. You may pass an image you host yourself, or use one of their stock images. Moodle uses the default headshot image, as defined by whatever theme you’re using. Moodle has a complex mechanism for determining which images to serve up, based on your current theme and context and whether caching is active. All image requests pass through theme/image.php, which acts as a clearinghouse for determining what image should be retrieved. This system is file extension agnostic for better compatibility and flexibility.

One of the benefits of collaborative development is that you’re usually not the first person to encounter a problem. I found that my issue had just been reported to the Moodle tracker by another developer who had come to the same conclusion. Here’s the issue. A Moodle request to Gravatar would look like this:

http://www.gravatar.com/avatar/6df0d771964ef4d1f10cab72149d8460?s=100&d=http://moodle.org/theme/image.php/moodleofficial/core/1348555103/u/f1

Let’s break that down. The URL contains the location of Gravatar’s image serving mechanism, an md5 hash of the user’s email address, a requested image size (s=100), and the default image url (d=<url>). If you try to use this now you get an error page which says “The type of image you are trying to process is not allowed.” Why?

I still don’t have the full picture but it appears that Gravatar made a change–unannounced and undocumented–to require file extensions in the default image. Several developers submitted support requests to Gravatar trying to confirm that this was the case. After several days(!) I got an answer back from one of Gravatar’s “Happiness Engineers” (blech). I’ve quoted the relevant part below:

We have recently implemented some changes that wouldn’t change our current documentation so much as an enforce that default images must actually be images. They should also be publicly accessible.

I noticed in the case you mentioned that you’re using a php file to serve up the image. For security reasons, that will no longer work.

This is nonsense. My own testing shows that they’re just looking at the extension, which is poor man’s security at best. Extensions can be faked. If they were serious about security they would eschew this extension malarky and just check the mimetype.

For me the greater issue is that this change happened in the dead of night, with no warning. Many hours of developer and administration time will now be consumed working around a change, leaving aside for a moment that the change is bonkers. What the support person told me perfectly explains the problem, yet as of writing the online documentation doesn’t reflect it.

Gravatar itself acknowledges on the same documentation page, when discussing displaying a Gravatar image:

If you require a file-type extension (some places do) then you may also add an (optional) .jpg extension to that URL:

I find that sentiment at odds with whatever process determined the change we’ve been discussing in this post.

So, that’s 760 words explaining the issue I spent far too much of my Thursday debugging. What does it all mean? That Gravatar is a neat, fun service which has no respect for the people who develop against its APIs. That may sound harsh but I maintain that if you have respect for your development community you don’t make changes like that without some kind of announcement or warning. That the change is technically deficient is also a cause for concern.

There’s a Moodle tracker item for providing support for alternative avatar services. It hasn’t gotten a lot of traction so far, but I intend to make a push there. Behavior like this makes me angry.

UPDATE: I’m amused, months later, to discover this blog post from Gravatar discussing the change, including the file extension requirement. It’s dated October 7, or over a week after the change and this blog post.

Thinking with networks

I’m a regular on some transit boards. Every once in a while someone will drop by and post a variation of “I need to get from A to B, is this possible?” In most cases if both places are served by public inter-city transport the answer is yes, so the real question is “how painful/time-consuming this?” In tonight’s thought experiment A is Milwaukee, Wisconsin while B is New Bern, North Carolina.

Where are we going?

Wikipedia tells us that New Bern is the birthplace of Pepsi, near Cape Lookout and a good 90-100 miles from major hubs like Raleigh and Wilmington. Hipmunk (if you’ve never messed around with Hipmunk, stop reading now and go do so) tells us that the Coastal Carolina Regional Airport is a stone’s throw from New Bern, and serves multiple major airlines with multiple departures. Greyhound’s System Timetables (another invaluable resource) tell us that New Bern sits a line between Raleigh and Myrtle Beach and sees two buses a day.

How do we get there?

Let’s start by asking Google Maps about the shortest distance between the two points. While public transport networks don’t (always) map to road networks this method can suggest possibilities that route planners don’t. Google Maps suggests two routes:

  1. Milwaukee-Chicago-Indianapolis-Dayton-Charleston-Greensboro-Raleigh-New Bern
  2. Milwaukee-Chicago-Fort Wayne-Columbus-Charleston-Greensboro-Raleigh-New Bern
The first thing you’ll notice is that neither of these maps well to Amtrak’s system map. Amtrak’s skeletal system will send you either to Washington (via the Capitol Limited) or Richmond (via the Cardinal and a bus connection).  Further, you can’t make a same-day connection in either of these places with Amtrak’s two Raleigh-bound trains, the Carolinian and the Silver Star.

The shortest distance between two points…

I’d say that there are three kinds of advice you can receive in a situation like this:

  1. Clueless advice.
  2. Bad advice.
  3. Good advice.

Clueless advice is someone who only knows how to use trip planners, and concludes that it can’t be done because of the day layover in Washington. Bad advice comes from someone who knows about the layover and, per the Dunning-Kruger Effect, thinks they’re giving good advice. That person says: take the night in Washington, catch the train to Raleigh or Selma-Smithfield the next day, and then take the bus. This is bad advice, because it overlooks something very, very important: the last bus to New Bern from Raleigh leaves after the earliest possible train arrival in Raleigh. If you take this person’s advice you’re spending the night in Raleigh as well.

Good advice is given by someone who checked on this possibility and realized that taking the train to North Carolina is a no-op and should be avoided. Instead, we need to work with Greyhound’s network as well and figure out how to get to New Bern faster, avoiding the overnight in Raleigh.  Greyhound will sell you a ticket to New Bern from Washington via Richmond and Raleigh. Your first bus leaves Washington at 7:35 PM. Your transfers are at 10:20 PM (Richmond–two hours layover) and 2:50 AM (Raleigh–two hours layover). This trades two hotel stays for a single awful night in buses and bus stations and an arrival in New Bern an entire day sooner.

(As an aside, even better advice is to take that Delta flight from Milwaukee to New Bern via Atlanta, which takes a total of six hours with the layover and is about $400 round-trip. Sometimes the answer is flying unless you’ve got no choice.)

Rounding it all up…

The poster didn’t say why s/he was going from Milwaukee to New Bern, and why s/he considered going by train. If you have business in Washington, for instance, then spending the night could make sense. If you have friends in Raleigh maybe you don’t mind the hotel stay there. Knowing how transit systems connect with each other can save you a day and some real aggravation.

Getting there from here

Today I’m grandly announcing a new series: Getting There From Here (GTFH). Perhaps one of the most mystifying things for people accustomed to flying is making sense of Amtrak’s routes. The trains have different names, go to different places, and (sometimes) offer different levels of services. They all cost varying amounts at different times. You’re starting to panic.

Relax: I’m from the Internet and I’m here to help.

I’m starting this series with my favorite problem: getting from Chicago to the East Coast (Washington-New York-Boston). I make this trip about twice a year. There are four different ways of doing it, and I’ve done three of them:

  1. The Lake Shore Limited from Chicago to either New York (train 48/49) or Boston (train 448/449).
  2. The Capitol Limited from Chicago to Washington (train 29/30), and then a connecting Northeast Regional or Acela Express from Washington to New York, Boston and points in between.
  3. The same as #2, except switching to the Pennsylvanian (train 42/43/44) in Pittsburgh and continuing to New York.
  4. The Cardinal from Chicago to New York (train 50/51) via Washington.

In later posts I’ll break down the difference between these four options. For now I’m going to explain selection criteria, or what Donald Rumsfeld might have called “unknown unknowns.” Here’s how to pick a train.

Timing

Trains depart and arrive at different times. Amtrak also publishes an endpoint-to-endpoint travel time for each train. Some times use a more direct route and may be faster, but may also leave at less convenient times. Consider what works for your schedule, and when you’d like to be onboard.

Cost

Amtrak uses a pricing strategy similar to that of airlines. Prices fluctuate based on time of purchase and demand. Railfans refer to “buckets” of pricing, with the “low bucket” being the lowest available fare for a given train between two given cities and the “high bucket” the opposite. To get a sense of what a reasonable fare between two cities, try plugging in your desired route about 5-6 months out. In most cases that will give you the low bucket, or something close to it. Amtrak fares will rise noticeably in the last few weeks, particularly for long-distance trains. Don’t wait! You can always cancel and rebook at a lower price–up until the day before in coach, and a week before in sleeping accommodations.

On-board amenities

Over the last twenty years Amtrak has pushed to standardize its offerings across the system. Like a Hampton or a Holiday Inn, you’re going to get the same experience on most trains, with a few noteworthy exceptions which we don’t need to get into here. What’s most important is to recognize the character of the train and the classes of services it offers. See this guide for more information.

Scenery

You’re on a train. Unless it’s the Acela Express you aren’t doing it for the speed and you’ll spend a good deal of time looking out the window. Amtrak publishes route guides for many of its routes full of information about the sites along the route and things to watch out for. I’m slowly adding guides of my own under the “Route guides” heading based on my own observations.

Equipment

Okay, this one is really nerdy. Amtrak operates several different types of equipment. If you’re like me this is actually a consideration. If you’re not like me it’s not.

Amtweets?

I’m on the road today, heading back to Michigan for a friend’s wedding. This involves three different transit operations playing ball: Trans-Bridge Lines between Easton and the Port Authority Bus Terminal (PABT) in New York, the MTA between the PABT and Pennsylvania Station (Penn), and finally Amtrak from Penn to Kalamazoo, via Union Station in Chicago.

One of the minor pleasures of taking the bus from the valley to New York (and there aren’t many so you really can’t be choosy) is running along the Northeast Corridor near Jersey City. Today, a little bit after 11 AM, I spotted the Silver Star, just a few minutes into its 31-hour, 1500-mile run to Miami and points in between. I recognized it from the two Viewliner sleepers behind the HHP-8 locomotive (see this page for more on train identification). Pleased, I tweeted the following:

On the bus to NYC and just saw the @AMTRAK Silver Star go by. Too fast for a picture!

This drew a quick reply from Amtrak’s social media folks. I’ve found them to be pretty responsive…

@mackensen Very cool! We’re glad you got to see it 🙂 How’s your ride going?

Amused that I’d gotten them interested, I replied with the following:

@Amtrak not bad but we’re crawling through the Holland tunnel. Happily I’m on the Lake Shore Limited this evening.

That tweet went out from the tunnel, incidentally. I continue to be impressed with Verizon’s coverage. That last tweet drew an odd reply, ending our little colloquy:

@mackensen We are sorry for any delay, we hope to have you to your destination ASAP! We look forward to having you on board again later!

I’ve been thinking this one over. At first I was deeply confused, but I’m coming to realize that I never said whose bus I was on, although I don’t think Amtrak operates any Thruway services in New Jersey. Also, it probably comes naturally to Amtrak to apologize for service delays (*cough*), even ones it isn’t responsible for.

Anyway, thought I’d mention all this. It really can be fun to tweet at Amtrak and see what you get back. A couple months ago I was coming back from New Orleans and got help up by Norfolk Southern maintenance in northern Indiana. I started including @Amtrak in my tweets slagging away at NS and eventually drew a friendly reply.

From Amtrak, that is. Those bastards at NS never said a word.

Newer posts »