Matthew Lang avatar

The Real Life Thor

An amazing account of a USMC pilot who ejected from his F-8 Crusader over a thunderstorm.

As the parachute opened, he felt the familiar tug upwards. Except instead of a slow descent, he experienced a rapid ascent. The powerful updraft filled his parachute like a sail and rocketed him vertically thousands of feet at a velocity of nearly 100 mph. During his ascent, he could see hail stones forming around him. The lightning was described by him as “blue blades several feet thick” and incredibly close. The thunder was so loud, he could feel it resonating in his chest cavity and remembered this more so than how loud it was.

Lt. Col William Rankin - Ejects Into a Thunderstorm by WeatherImagery

via Kottke.org

Book Reviews #4

It's been a while since I last posted about the books I have been reading so here's what I've managed to finish in the last couple of months.

Hannibal Series: Enemy of Rome, Fields of Blood & Clouds of War by Ben Kane

I do enjoy books based on this era and while there are many books in this genre, there are only a handful of authors who get it right. Ben Kane is one of them and his series set against the Second Punic War is great to read and grand in scale. Great characters, story and action and a little glimpse into a point in history that some might not know too much about.

Ready Player One by Ernest Cline

Set in the near future when fossil fuels have ran dry and the divide between rich and poor has grown, many people are escaping a harsh world into a virtual universe. If you grew up in the eighties you'll love this book. The story uses many of the popular videos games, table top games, movies and people who were popular with kids in the eighties. I loved it.

Blood Song: Book 1 of Raven's Shadow by Anthony Ryan

Fantasy books have been a bit hit and miss with me lately. To be honest I had almost given up on the genre. After a run of non-starters though I finally found something worth reading. Abandoned by his father at a military school, Vaelin Al Sorna has to pass a training programme that will test his limits. Then he must use his skills for the benefit of the Faith. A dark story, but it was really entertaining. Can't want to move onto the next book.

The Red Line: The Gripping Story of the RAF's Bloodiest Raid by John Nicol

After reading Anthony Beevor's book, The Second World War, my interest in the subject has been renewed with some interest. A chance spotting of a Lancaster bomber flying overhead on holiday was the nudge I needed to read this book about the RAF's raid on Nuremberg in 1944. Amazing stories of the crews who flew on this mission and amazing accounts of those who survived. Highly recommended.

The App.net Daily Post Experiment

For the month of September I committed to posting a 256 character post to my App.net account every day. It turned out to be more beneficial than being a simple daily nudge.

The Experiment

It was initially an idea by Matt McCabe (@mttmccb) on App.net who was committing to posting a 256 characters post with the hash tag #adn256month included in the post somewhere. It sounded like an interesting challenge, and so I also joined in for the month of September.

I set myself a couple of guidelines at the start of the month for this. A rules of engagement sort of idea.

I didn't include a task in my to-do list for this or even set a reminder. It was the one thing each day that I had to remember to do. I like to think of it as a little mental exercise for the day. Settings reminders and scheduling appointments is great for the really important things, but for little tasks like this, I wanted the responsibility to remember to fall on me.

I limited myself by excluding any tools that would automate any part of the process. Most days I opened Kiwi on my MacBook and composed a post for a few minutes, editing it down to what I needed and then posted it. At the start of the month I did manage to write three posts ahead of their intended days but I stopped doing this as it meant on those days I didn't have too much to do and that seemed to go against the whole reason why I wanted to do this. I wanted to build up a daily habit using only me. No apps, tools, or other medium to remind me or to pull posts from.

My Findings

The month went well. I only missed a single day out of the whole month. I was surprised by this as I thought I would miss at least one a week, and not having an iPhone for the last two weeks I thought I was going to miss even more days. As it turns out I was able to keep the habit going missing just a single day.

The posts themselves started out as mainly random snippets for the first week and then for the remaining three weeks I themed the weekday posts to follow a specific topic. Weeks two and three were about productivity and week four was about Rails development. The weekend posts were usually kept light hearted and not too serious.

The posts also turned out to be great for expanding on ideas for essay posts I have considered but haven't drafted anything for. The chance to write something small on an idea kept me focused on the core idea for the post and also let me test how each post was received by my followers. A favourite or a repost signified that a post might be worth expanding on.

What Next?

The experiment has finished but the idea of the daily post of 256 characters lives on. I've committed to posting a single snippet of 256 characters to App.net on a daily basis using the hash tag #team256.

It's simply too good an exercise not to do on a daily basis. My only concern is that the audience for it is rather small at the moment. I have just over a 100 followers on App.net but I suppose it's better to start somewhere.

How to Build a Popular Content Section for Octopress using Gauges

In this post I'm going to try and briefly describe how I built the popular content section working on my Octopress blog using data from Gauges.

I'm using Gauges as the traffic and analytics service for my blog. I have done for over a year now. It's simple and very easy to use which is why I like it so much. One of the great things about it though is that it also provides an API for people who want to do more with the data that they have accumulated. One feature I wanted to include on my blog has been a link to what most people have been reading in the last few days. I thought that this would be extremely easy to add given that Gauges already has all the data that I need for it.

The Leaderboard

What we essentially want to build is a leaderboard comprising of the most popular articles sorted by the number of page views they have with the most popular article at the top. With this analogy in mind I just needed to populate the leaderboard with page titles, URLs and views for popular articles from my Gauges data.

In adding this feature to my Octopress blog, I started thinking about how I would interact with this feature. That was easy. A Rake task. Adding this as a Rake task means that I can add this to another Rake task that could pull in the popular content during the generate stage. For now though I run it as a separate Rake task on its own as I might generate the site a couple of times before publishing it.

Here's how I envisioned this popular content section to run:

PopularContent.top_content(3)

So, all we're doing here is passing in the number of days that we want to look back on but there's a number of things that need to happen here:

  1. We need to connect to the Gauges API.
  2. We need to ask for the content stats we need.
  3. We need to calculate the most popular article over the time period that we pass in.
  4. We need to return the most popular article as an object with a title and a URL.

Get Connected

When we initialise this object we need to do two things:

  1. Connect to the Gauges API
  2. Create our leaderboard

This is done quite easily. When we initialise the TopContent class we pass in our Gauges ID and API key so that we can connect to our own data. In order to make this process even easier, we're going to use the Gauges gem rather than working directly with the Gauges API.

Once this is done we create a blank array that will serve as our leaderboard for compiling the top viewed articles over the last few days.

def initialize(gauges_id, api_key, days = 3)
  @gauges_id = gauges_id
  @api_key = api_key
  @client = Gauges.new(token: api_key)
  @leaderboard = []
end

Building the Leaderboard

Gauges doesn't group popular content data. Instead it serves the data you need on a date basis. So we need to ask for each date that falls in the date range we specified:

def build_popular_posts(days)
  end_date = Date.today
  start_date = end_date - days

  while start_date <= end_date do
    content = @client.content(@gauges_id, date: start_date)
    content["content"].each { |c| update_leaderboard(c["title"], c["views"], c["url"]) if valid_content_page?(c) }
    start_date  = 1
  end

  @leaderboard = @leaderboard.sort! { |x,y| y[:views] <=> x[:views] }
end

There's a lot going on here, so let's take it one step at a time. First of all we initialize some variables for our start and end date using the number of days variable that pass in.

end_date = Date.today
start_date = end_date - days

Next, we iterate over these dates beginning with the start date.

while start_date <= end_date do
  # ...
end

For each date we're going to pull the data we need from Gauges. This is a list of top content for the date we are on.

content = @client.content(@gauges_id, date: start_date)

Next we update our leaderboard by iterating over the content that has been viewed for the current date.

content["content"].each { |c| update_leaderboard(c["title"], c["views"], c["url"]) if valid_content_page?(c) }

This is the point where we start accumulating page views for each page. The update_leaderboard method takes the page title, URL and number of views and uses them to create or update an existing entry on the leaderboard.

def update_leaderboard(title, views, url)
  position = @leaderboard.index { |a| a[:title] == title }
  if position
    @leaderboard[position][:views]  = views
  else
    @leaderboard << { title: title, views: views, url: url }
  end
end

Finally we sort the leaderboard according with the highest number of page views at the top.

@leaderboard = @leaderboard.sort! { |x,y| y[:views] <=> x[:views] }

Display the Results

Once this is done, it's a simple matter of writing the popular content to a config file using the Rake task so that we can use it in the generating of our Octopress blog. Accessing these from an html file is straight forward enough if you're familiar with working with Octopress layouts. I have the following code located in my post layout just after the post section:

<div class="related">
  <h2>Popular Posts</h2>
  <ul class="related-posts">
    <li>
      <h3><a href="{{ site.popular_post_first_url }}">{{ site.popular_post_first_title }}</a></h3>
    </li>
    <li>
      <h3><a href="{{ site.popular_post_second_url }}">{{ site.popular_post_second_title }}</a></h3>
    </li>
    <li>
      <h3><a href="{{ site.popular_post_third_url }}">{{ site.popular_post_third_title }}</a></h3>
    </li>
  </ul>
</div>

That's it really.

If you look at the code, you'll see a few other methods that are used to filter out data. I intentionally filter out the home page views and other pages that I don't want to include in the list. This is done just by checking page titles or paths.

I've been running this code on my blog for quite a while now. Previously it only returned a single page URL and title, but I wanted to include a list of posts so I added methods to pull the second and third most popular posts.

The code itself is quite straight forward to read and follow. It might not use all the latest Ruby idioms and tricks that many Ruby developers know and love but for me it's straight forward code that works.

The fully listed code to accompany this post can be found on Github.

Time and a Place for Client Work

There's a time and a place for client work. Rushing out the door on a Saturday morning isn't one of them.

Over the weekend I made mistake in some code I had changed for a client. After pushing the quick change to Github and then to the test environment for the client, I then realised the mistake I had made. With no time to correct the change, I decided to leave it until Monday morning. After seeing my mistake in all it's glory this morning, I admitted my mistake to my client and then proceeded to fix the code correctly.

There's no excuse for the mistake that I made but making the change on a Saturday morning when I was due to leave the house probably wasn't the best time to do it. Also I didn't read the message fully from my client that prompted the change. In my haste I missed the last sentence which would have changed the way I updated the code. A hard lesson learned.

Freelancing is definitely a learning experience and with each mistake you make you see the correct process you should be following. In this case it's client work. It should be reserved exclusively for your typical working day. In my case it's during the week at my normal office hours and only when I have at least 30 minutes to carry out the work and review it accordingly. The only exception should be for emergencies and when carrying out that work it should receive your complete focus.

It can be tempting to be the ever accommodating freelancer and provide help on your client's every request and wish, but going down that path will only degrade the quality of your work. Your clients will come to expect fully working changes when they demand them regardless of the hour of the day. Responding in this way isn't in the best interests for you or your client. Instead, defer fixes for client work for first thing the next morning or even before your main day begins if you have the time.

There's a time and a place for client work. It's during the agreed times that you already have with your client. Keep it that way to ensure your clients get the complete attention and focus they paid you for.

Want to Blog?

Write Carl's question on an index card. Put it on your wall. Answer his question. Repeat daily.

I miss longer-form pieces. I miss the minds behind the writing. Anyone can share a link with a snarky comment. I want to read the words behind your thoughts. I want to read your why.

Share by Carl T. Holscher