Tuesday, March 31, 2009

Gotcha Of The Day: Installing Custom Built Apps on T-Mobile G1 / Android

I had my first little Android App written, but for the life of me, I couldn't figure out how to get it to run on my phone instead of the emulator.

Poking around, I found this article, which gave me some initial insight. But still, I was left scratching my head.

Turns out, it's not hard at all. I just needed to:

  • On the phone handset, go to the Home > Settings screen and insure:
    Applications > Unknown Sources is checked
    Applications > Development > USB Debugging is checked
  • Next time you plug in your phone, your Windows box will complain it can't find the driver to use. Good. From the device manager, choose to update to the drivers that come with the Android SDK, they are found in ANDROID_SDK_HOME/usb_driver
  • Once the phone is properly detected, run the adb command to confirm the device is present:
     ANDROID_SDK_HOME/tools/adb.exe devices
     List of devices attached 
     emulator-5554   device
     HT851GZ89495    device
    
    In this case, I have both the emulator and my real phone available.
  • To install an application, run:
     ANDROID_SDK_HOME/tools/adb.exe install foo.apk
    

Happy Hacking!

Location Stamper: Putting Moby Scheme To Work

I was so impressed with Moby Scheme I just had to give it a try. So, instead of going to bed on time last night, or working on billable work this morning I hacked some scheme.

I decided I'd write a trivial program: Location Stamper. The idea isn't particularly exotic - you have a small app running on your phone. Whenever you want, you click the screen and a message is logged to a twitter account with your current location. It might be useful, but probably isn't. As a side note, I chose to record the data in Twitter, because it's effectively an easy to integrate, always online, free for anyone to access database. How generous of them.

So far, I've taken the program from idea, to Moby Scheme, to running on the Android Emulator. I need to do a bit more homework before I can figure out how to run developed apps on my cell phone. I was hoping it was trivial to do, but alas, I couldn't find the quick and dirty instructions. But, this is hardly Moby Scheme's fault - I know I've got a Android application ready to go.

So, here's the code and some comments to explain what's going on:

;; The first three lines of this file were inserted by DrScheme. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-beginner-reader.ss" "lang")((modname location-stamper) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ())))
;;
;;This is a basic Android APP that is used to record your current GPS coordinates
;; in a twitter feed at the click of a button. Useful? Not really. Intersting,
;; none the less
;;

;; Include our standard libraries
(require moby/stub/net)
(require moby/stub/world)
(require moby/stub/location)
(require moby/stub/parser)

;; Not sure if our URLs will grow too long for Twitter, but it's trivial to tinyurl
;; them.
(define (url->tinyurl u)
  (get-url (string-append "http://tinyurl.com/api-create.php?url=" u)))


;; Constants.
(define twitter-username "locationlog")
(define twitter-password "wouldn'tyouliketoknow")
(define WIDTH 320)
(define HEIGHT 480)

;; Our world. The current location and a comment about that location.
(define-struct loc (lat lng comment))


;; Various functions to convert stuff to strings. Our world to strings,
;; and just a lat and lng to string
(define (lat-lng->string lat lng)
  (string-append (number->string (exact->inexact lat)) ","
                 (number->string (exact->inexact lng))))
(define (loc->string w)
  (string-append (lat-lng->string (loc-lat w) (loc-lng w)) " "
                 (url->tinyurl (string-append "http://maps.google.com/maps?q=" (lat-lng->string (loc-lat w) (loc-lng w))
                                              "%26z=10"))))
                 
  
;; Like the name says, our initial world
(define initial-world (make-loc 0 0 "Initial location set to zero"))

;;
;; Our callback functions that make this all work. This is where Moby Scheme really shines.
;; Each function takes in our world an returns our world, and is indepdent and clean.
;;
(define (update-location w lat lng)
  (make-loc lat lng
            (string-append "Location updated: " (lat-lng->string lat lng))))
  
(define (log-location w b1 b2 type)
    (if (eq? type 'button-up)
        (make-loc (loc-lat w) (loc-lng w)
                  (string-append "Twitter status: " (twitter-update twitter-username twitter-password
                                                                    (string-append (loc->string w)))))
        w))

(define (render w)  
  (place-image
   (text (loc-comment w)  10 "black")
   20 20
   (empty-scene WIDTH HEIGHT)))

;;
;; Get this party started!
;;
(big-bang WIDTH HEIGHT 5 initial-world)
(on-redraw render)
(on-location-change update-location)
(on-mouse log-location)

I'd show a screenshot, but there's really not all that much to see.

Now for some feedback...

Gotchas

I ran into a handful of items that made development of this tiny program harder than I expected. One of the biggest issues I had was that running DrScheme in Beginning Student Mode is painfully slow (on Windows, Vista) for me. I use it for production code all the time, and the performance is just fine. If I had to guess, I'd say it was the code coverage tool that was chewing up CPU. Regardless, it's just no fun to develop in an environment that moves slowly.

As a side note - I found the develop and test in DrScheme, then use command line tools to generate and compile Java, worked quite well. Even when it came to modifying the generated Java code, I didn't have a problem. The development loop, I assume, could get smoother, but is quite usable now.

The other big gotcha I ran into was that lack of services offered by the API. For example, there's a very cool get-url that grabs the contents of a URL, but there was no way to set the HTTP headers on this request, or even an easy way of URL encoding parameters. The HTTP header issue meant that in order to implement twitter-update I had to write code at the Moby Framework level, rather than the application level. This included writing a Scheme stub of twitter-update as well as a Java specific twitterUpdate(...). While I was impressed with how easy it was to add this functionality in, it still slowed down development significantly. I assume this is a fairly temporary problem, and as time goes on, services will evolve and fill out completely.

Finally, having Moby Scheme depend on the Beginning Student Language is a double edged sword. It's excellent for those learning to program (which is Moby's target audience, and that's a good thing!), but it does make writing apps quickly and efficiently frustrating. It's actually amazing how complete a program you can write when a function can only have a single statement in it, and you can't use begin or let. I actually found programming Beginning Language mode kinda fun.

Final Thoughts

I think the bottom line is that Moby has plenty of growing to do, and even when it has a more complete library, it's probably not going to be the best option for production Android programming. But who cares! Heck, those aren't the goals of the project. If you're looking for a I'd like to teach my friend/kid/husband/wife how to program, this is an excellent place to start. And when the kinks are worked out of it, developing little apps should be a terrifically fun. I'm seeing visions of hand held web mashups in 25 lines of code or less...

Whether your a Scheme head or not (especially if you're not), this is a fun project to keep an eye on.

Update: I figured out how to install apps on my phone, it's not too painful at all. Now the real fun can begin!

A Facebook meets Passover

If you're celebrating Passover this year, and have a Facebook account you've probably already seen the Facebook Haggadah. But in case you haven't, it's definitely worth a read. Even if you aren't a Facebook user, you'll get a kick out of it. Absolutely hilarious.

I've got my Brother David to thank, who got this from our friend Hirsch. Sort of passed along from generation to generation, if you will.

A Goofy Take On Obama's Latest Press Conference

Perhaps it's the mood I'm in, but I found this video to be rather funny.

Ahh, nothing like yanking the chain of the Mainstream, Gotcha-Journalism, Just-a-filter media.

The Art Of The Propagator - A Thought Provoking Read

I saw mention of the Art Of The Propagator paper on Lambda The Ultimate and was intrigued. I was expecting a paper that reinforced the discussion of constraint propagators in SICP (which would have been fine by me), but instead was provided with an unexpected topic.

The paper delves into the question of how you can design a system that handles partial information, information from multiple sources and even conflicting information. Combine this with the ability for propagators to back into information given a known result, and you've got a really interesting approach to system design.

I can imagine a system like this would be helpful when you're analyzing business data and making assumptions from it. As more data is provided, conflicts will no doubt arise, and the ability to handle contradictions seems essential.

This does have me wondering, how does a concept like this move from research into the Real World? Regardless, it's definitely cool research to keep an eye on.

Sunday, March 29, 2009

PLT Scheme Meets The Android Platform

I just read a post from Grant Rettke that mentions Moby Scheme:

We are delighted to announce the first release of Moby Scheme, a compiler from Beginner Student Language (BSL) + World programs to smartphones. The current prototype compiles to the Android platform, and supports almost all BSL programs as well as libraries to accelerometer, GPS, and SMS functionality.

This apparently was the topic of the keynote at the most recent International Lisp Conference.

The World programming library allows for the creation of Simulations and Animations easily - check out this eBook for more information.

This is definitely a novel idea and can hopefully carve some time out to play around with it.

Scheme and Android geeks unite - oh wait, how big a population is that?

Update: I just got done viewing the keynote talk slides while listening to the audio. The setup took a bit of effort to get right, but it was definitely worth it. What an excellently delivered talk. Highly recommended.

Update: I couldn't resist at least making my own little hello-world application in Moby Scheme. So, here it is:

(require moby/stub/world)

(define WIDTH 320)
(define HEIGHT 480)

(define (render w)
  (place-image 
   (text "Hello World" 10 "Black")
   20
   20
   (empty-scene WIDTH HEIGHT)))

(big-bang WIDTH HEIGHT 10 0)
(on-redraw render)

After a few minutes of poking around, I was able to compile this to Java and then run it on the Android Emulator:

Man, am I impressed. They sure have made programming for the Android platform fun and easy. Now I just need to think up an application to write...

A Delayed Gratification Hack

One of my Facebook friends commented about how he was "teaching his child about delayed gratification" and provided a link. I wasn't exactly sure what I expected the link to connect to (some silly photo is probably what I was hoping for), but I was pleased by what I found.

Here's the article at the end of the link. It's by Marc Warnke.

The post not only talks about how important delayed gratification can be for kids (and my guess for adults), but also provides strategy one can use to teach it as a skill.

The researchers then followed the few children who had exhibited that behavior [of putting up with delayed gratification] and found that they excelled across the board in many of life’s endeavors, proving that delayed gratification is a very important life skill.

The kids who did not naturally have the trait were provided with adult modeling and they were able to learn it. The key was that they learned a distracting behavior which helped them wait the allotted time. It’s a skill that can be learned, and, as a parent, I find that huge.

I'm with Marc - the fact that you can take an important skill that some naturally have and some don't, and yet follow a strategy that makes it available to everyone - well, I think that's pretty sweet.

Read the article to learn the strategy. And next time you have choice between the quick win, and the long term benefit - pull it out.

Passover - It's On

Today, I officially started preparing for the upcoming holiday of Passover. Dave and I hit the Kosher Mart, in Rockville, MD to pick up everything from the essential to the absurd. (Two examples below - can you tell which is the essential and which is the absurd?)

For the first time this year, we even bought Breaded Chicken - I have no idea how that works, but according to the big Kosher For Passover sticker, it works. Long gone are the days of suffering through awful Kosher for Passover food - now it's just an excuse to try new things. Not that I'm kvetching...

So here's where we're at - we've got a big o'l pile of food. Next up, the fun part - the cleaning and the organization. Just think, we get to completely re-invent our kitchen and everything we eat for just 8 days? Who wouldn't want that opportunity?

Friday, March 27, 2009

Grading Obama's First Virtual Town Hall Meeting

Yesterday, the White House held it's first virtual town hall meeting. If you didn't catch it, the full video is below. I give him a...

B+

First, what he did well:

  • He gets points for even having a virtual town hall meeting. While powered by relatively new technology, I have to believe that if Bush had wanted to pull this off, he could have.
  • He gets points for taking whitehouse.gov from an informational site, to an interactive one. It's a good start, but like any technological advance, it's not an end point. I think it's critical that they continue to improve Whitehouse.gov. Though, all things considered, this was a good first step.

  • He gets points for explaining complex phenomena is understandable ways. For example, he explained the difference between a leading and following economic indicator, or how the student loan system has some potential flaws in it - and he did so in a way that a layman could understand. My guess is that looking back Obama won't be remembered so much as a great speaker, but as a great educator. Whether it's race, patriotism, the economy or any other topic, he makes his strongest arguments when his main emphasis is on educating you about the topic.

Where he lost points:

  • I have to say, I as extremely disappointed in the handling of the marijuana question. Go ahead and joke about it a bit, if you want. But the fact is, your constituents asked you a question, the very least you could do is give a serious answer. A "No, because I said so answer" runs contrary to the goal of being a reason based government; and seems just plain unnecessary. Either he has an informed opinion on this topic, or he should be up front about it and get one.
  • One of the fundamental problems with these town hall meetings is that so many questions are asked, that the administration can inevitably pick the ones that suit their needs. Or as rrrobbed quipped:
    Obama online "town hall", 29000 questions submitted means "we're going to find questions about the topics we want to talk about." Pointless.
    The Town Hall meeting ends up being more of a speech and less of a impromptu discussion. This is definitely a non-trivial problem to fix and I'm not sure what the solution is. Voting on the questions is definitely a good thing, but it's not quite enough yet.

So, Obama team, what are you planning to do to pull your score up to an A?

Here's the whole virtual meeting:

Thursday, March 26, 2009

Recipe: Ben's 1 Minute Chili

Ingredients:
- 1 serving kidney beans
- 1 serving Morning Star Farms Sausage Flavored Crumbles
- Cholula

Recipe:
1. Combine beans and crumbles
2. Microwave on high for 1 minute
3. Douse in Cholula
4. Enjoy!

Feeds one very hungry, very rushed programmer.

This recipe won't win any contests, but when it's all you have around and no time to prepare it in, it'll do.

The Human Side Of The AIG Bonuses

I was really pleased to see this resignation letter from an AIG employee published in the New York Times. It's about time that we heard from at least someone who's getting the bonuses that congress and the country are so up in arms about.

As the letter explains:

After 12 months of hard work dismantling the company — during which A.I.G. reassured us many times we would be rewarded in March 2009 — we in the financial products unit have been betrayed by A.I.G. and are being unfairly persecuted by elected officials. In response to this, I will now leave the company and donate my entire post-tax retention payment to those suffering from the global economic downturn. My intent is to keep none of the money myself.

Perhaps I'm a bit sensitive to this. See,I've been in the position of being promised a significant (well, significant to me anyway) bonus if I lived up to my side of a business agreement. When the time came to pay out the bonus, the venture capitalists who made the promise found a way out of the agreement.

The whole notion that you can make an agreement with an employee, have them put in significant time and energy, succeed in their goals - and then not deliver on the promise you made to them is more than insulting, it's fundamentally wrong.

I understand people's outrage at what sounds like ridiculous bonuses (and perhaps they are). But, it should be our lawmaker's responsibility to take a calm and rational approach to this issue and not simply blame the person who's getting the bonus. What about the fact that AIG made the agreements with them? Or what about the fact that the federal government changed the rules so that AIG could get themselves into this mess in the first place.

There's plenty of blame to go around, but demonizing the people who had agreements in place before this all started, and who played by the rules is just plain crazy.

Wednesday, March 25, 2009

The Twins First Video Appearance

We have left Boston, so this will be our last posting for awhile, so we thought it would be good to make it multimedia.

Here's the Baby Girl, in Dream Land, not quite sure if she wants to wake up or not:

And Here's the Baby Boy, stretching and eyeing the camera. He is a natural.

We can't wait to see them again, and see how they've grown. Stay tuned!

PHP 5.3 Features To Watch

I don't usually get too excited about PHP as a programming language - but check out these two additions to PHP 5.3: anonymous functions and namespaces.

These are two features that are sorely needed, as they should to avoid code filled with absurdly long function names and throw away functions.

This is still a long way from the lexically scoped elegance of JavaScript or Scheme, but it's a start.

Of course, I have to wait for my clients hosting providers to deploy PHP 5.3 before I can start programming against it. Not sure how long that will be, but I assume it'll be some time.

Still, it's nice to see PHP making at least a little linguistic progress.

Metal mouth transformation

For the last week, I've had orthodontic spacers in my lower back teeth. While not particularly painful it has been annoying having this sensation of a chunk of food in my teeth that I can't dislodge.

Well all that ends today. The spacers go.

That's the good news. The less than good news is that they are getting replaced by braces. So much for comfortable teeth.

I just signed the waiver that says that any number of things can wrong and it's not their fault. Oh and they suggested I reduce or drop sugar from my diet during the treatment. Uh, don't think so.

And it begins...

[1 hour later]

And I have braces! Though I was tempted, I didn't get hot pink ties on them. Nope, they are as subtle as they can be.

For all my kvetching, the process didn't hurt and they were quite nice.

Now, I wonder how long I'll go before I break something because I'm not following the rules?

My New Look:

(Yikes that's ugly!)

Tuesday, March 24, 2009

A Flying First - In Flight WiFi

Shira and I are on our way back from Boston, and were given quite a treat on our Southwest flight home - free, inflight, WiFi. I'm currently blogging this mid flight, a first.

Overall, I've been very impressed with Southwest. Mostly, it's their upbeat, laid back attitude I like. The fact that we could change our tickets without fees as also a big plus. Not to mention, I find their seats to be larger and more comfortable than even my United trip overseas. And now they give me free WiFi - what else could I want?

The WiFi is only available on 4 Southwest planes, as they are just testing it out.

Why am I not surprised that Southwest offered WiFi before say United or USAir? It's in their culture to do more with less, and this seems like another example. WiFi seems like a smart investment - it provides both entertainment to passengers as well as infrastructure you can build on later (perhaps allowing folks to use free cheap laptops during the flight). I can't imagine the WiFi is much more expensive than outfitting your plane with TV screens like Jet Blue.

On the technical side, the WiFi has been slow in terms of accessing pages. Though, according to some quick measurements, I'm getting 300kb/second download rates.

This, I believe, is a taste of the future. I think WiFi is probably going to be common on flights before we're making cell phone calls from the air.

Part of me is a little disappointed about this. Flight time is usually a chance for me to either relax, or focus on stuff without interruptions. It's one of the few times that I had the perfect excuse to chill. Not anymore. This Southwest flight is now as much an office to me now as my desk at home, the waiting room at the hospital and the lobby of a hotel. Oh well, that's as much a good thing as it is a bad.

OK, I should be working. But, perhaps I have a responsibility to fully test this connection? YouTube, here I come...

Sunday, March 22, 2009

Twins: Life Day 5

We got to spend quite a bit of time with the twins this afternoon, as apparently, feeding two babies takes quite a bit of time!  Who knew?  So, what do you do with two babies that don't really do much?  You take photos of them, of course!  We will spare you the whole batch, but we know there are a lot of folks who are far away who are waiting on some more photos, so here they are.  

Finishing Up The Nursery

One of our projects today is finishing up the nursery. As you can see, I took responsibility for the Hardware while Shira focused on the Software.

We hope the twins like their new digs. It's no womb and all, but it's still quite cozy.

Saturday, March 21, 2009

Finally, Photos of the Twins

Here they are, photos of Elana and Shmuel's twins from day 3 of their lives. Aren't they adorable?

A must have baby item

Shira and I are out making a diaper and supplies run for the new twins. I think this item is pretty essential, don't you agree?

Friday, March 20, 2009

Meeting the Twins

We just met the twins - and boy, they're amazing! They're so tiny and precious and fragile and loveable and wonderful.

Welcome to planet Earth guys, we're glad to have you! I promise, life gets easier once you a little more grown up (but then it gets harder again, but we can ignore that fact for now).

I took all sorts of photos, but for some reason, the hospital has blocked Picasa. So, you'll have to get by with just a few photos uploaded below.

You can tell below that I included my hand in a bunch of the shots. I did this to try to show some scale. It's hard to believe, that at the moment, the baby's heads are the size of the palm of my hand. Life is truly miraculous when you think we all started off more or less this size.

Crap, can't seem to upload pictures using the usual Blogger technique or Picasa. Giving Twitpic a try:

Update: Finally, I managed to post the pictures. Check them out here (or here).

Off To Boston

[photo censored]

Shira made the executive decision - we're heading to Boston to meet our new Niece and Nephew. I'm so psyched to meet them!

I love getting the call saying we have two hours to pack our bags and make a flight. It must be what a special forces operator feels like when called up for a mission, minus the risking my life for my country bit, of course.

To be fair though, I doubt SF guys need to fly Southwest...

I do love adventure though!

Thursday, March 19, 2009

Dabbling With Generators

Some time ago, I blogged about generators, and specifically mentioned the implementation here. I've since incorporated this into my production code, and every so often find a good use for it. Today, I believe, was one of those days.

Bare with me for a moment - I'm going to try to describe the problem without mentioning any customer specific details.

Assume that you've got a list of items you want to render on the screen, such as:

(define data '(a b c d e f g)

Laying out the data in sequence is trivial. For example:

a b c d
e f g 

But, the client wanted to get fancy. He wanted, in some cases, to be able to have blank spots in the rendering. So, you might have:

a b c d
_ _ e f 
_ _ _ g

I already had the sequential approach implemented, so I just wanted to augment this with the ability to specify where the holes were. Here's what I came up with for a solution:

#lang scheme

;; We assume that you've put definition of define/y from
;; http://blog.plt-scheme.org/2007/08/control-and-macros.html into
;; yield.ss
(require "../lib/yield.ss")

;; This belongs in a helper file too. It's just a basic while
;; loop construct.
(define-syntax while
  (syntax-rules ()
    [(while cond expr ...)
     (let loop ()
       (when cond
         expr ...
         (loop)))]))

;; Define our data
(define data '(a b c d e f g))

;; Define our layout. #t assumes we can put an element there
;; #f means we can't.
(define layout '(#t #t #t #t
                 #f #f #t #t
                 #f #f #f #t))


;; Our main program. `Data' is a list. `layout' is a function
;; that we can invoke to give us instructions on where to layout.
;; We create layout using a helper function below.
(define (do-layout data layout)  
  
  ;; A trivial implementation of "show" - the real system
  ;; might do something more complicated than print the data out.
  ;; Notice the `modulo 4' trick here is just to print out our sequence
  ;; propery.
  (define shown-so-far 0)
  (define (show x)
    (printf "~a " (if x x "-"))
    (set! shown-so-far (add1 shown-so-far))
    (when (zero? (modulo shown-so-far 4))
      (newline)))    

  ;; Again, render here has been kept especially simple. It just calls show.
  ;; In a "real" system, render here might change a GUI or something like that.
  (define (render value guide)     
    ;; A bit of magic happens here. We invoke (guide) to give us a clue as to whether
    ;; or not it's cool to lay out an element here. If not, then show nothing and 
    ;; try again. Essentially, we lay down one blank spot for each #f listed above.
    (while (not (guide))
           (show #f))
    ;; Finally, we know we have a valid hole, so show our value
    (show value))
  
  ;; The our main loop - just go through each piece of data and ask to render it.
  (let ([guide (layout->guide layout)])
    (for ([value data])
      (render value guide))))

;; A bit of magic to convert a list like:
;;  '(#t #f #t #f)
;; into a function, that when invoked, will sequentially return back
;; these values.
(define (layout->guide layout)
  (define/y (guide)
    (for-each yield layout))
  ;; [1] See note below
  (lambda ()
    (guide)))
      
    

You can test this with the expression:

 (do-layout data layout)

The Good, The Bad And The Ugly

Overall, I like the solution above. The define/y handles all the annoyances of keeping track of whether or not my next spot is a free one. So, we'll call that the good.

There's not much bad above, as far as I can tell? (Well, besides my ridiculous example)

The ugly to me is:

;; A bit of magic to convert a list like:
;;  '(#t #f #t #f)
;; into a function, that when invoked, 
;; will sequentially return back
;; these values.
(define (layout->guide layout)
  (define/y (guide)
    (for-each yield layout))
  ;; [1] See note below
  (lambda ()
    (guide)))
      
    

The above function has to be careful to not just create a generator, but arrange for a fresh one to be returned. Otherwise, you may have code that expects to be starting at the beginning of the sequence of generators, and yet, be at the end.

If I use this construct more, I'm going to tune this process further. Perhaps something like:

  (define/y-maker (make-foo)
    (yield 1)
    (yield 2)
    (yield 3))

The usage would be:

 (let ([foo (make-foo)])
   (list (foo) (foo) (foo)))

The above is nice, because it emphasizes that you're defining a function which returns your generator function, rather than being the generating function itself.

My guess is that someone's already done this properly, and it's probably lurking on planet, just waiting for me to use it.

Still, the above has been a great thought exercise.

Two Unexpected (and Free) PDF Related Tools

Generating PDFs: Google Docs

Need to generate a PDF in a hurry, and want to do it for free? You could use the already mentioned PrimoPDF (thanks Gareth!). Another option is to use Google Docs.

Just go to File >> Download As >> PDF.

I've been finding this functionality especially useful for contracts and other documents that weren't really intended to be edited once they've been agreed upon.

Tweaking PDF Docs: The Gimp

I was pleasantly surprised just how cleanly The Gimp handles PDF documents. It allows you to import the pages as layers or separate images - and Just Worked.

In this case, I used it to tweak a contract (that hadn't been agreed to yet), by editing out a particular clause. It just looked cleaner than me printing it out, crossing it out, and re-scanning the document.

The Gimp solution isn't perfect, as once you've extracted the PDF solution, you're stuck with images files. But still, for a quick edit it totally works.

And I've Been Uncled (again!)

I just got the news - my sister-in-law, Elana just had her twins!

The details all very hazy at the moment, so we are still in wait and see mode...

But, wow, this is wonderful!

Apache Monitoring From The Command Line

I wanted to get a quick sense of what one of my Apache web servers was up to, so I through together the following:

  1. I ssh'ed to the server
  2. Enabled mod_status, so the URL http://servername.com/server-status would work. I did this by adding in the following to my httpd.conf file:
    <Location /server-status>
    SetHandler server-status
    
    Order Deny,Allow
    Deny from all
    Allow from localhost
    </Location> 
    
  3. Restarted the web server to have the above take effect
  4. Kicked off the command:
     lynx -dump http://localhost/server-status | head -30  
    

The result is a screen that refreshes every 2 seconds and tells me which processes in Apache are busy, and with what. Here's a sample screenshot:

Gosh I love Unix.

The White House Talks Business

I enjoyed listening to Obama address and answer questions from the (White House?) Business Roundtable. There's no soaring rhetoric here, just a solid case made for what the Obama team is thinking with respect to their budget and other items.

I found most of the questions to be disappointingly gentle. Though, I did like answer provided on carbon emission caps - an answer which will not please everyone, but came across as pragmatic and thought through.

I doubt this video will change your mind with respect to the current White House policies - but it might at least give you a clear definition of their argument and approach.

Monday, March 16, 2009

Best Recession Advertising. Ever.

Well done Jet Blue, your WelcomeBigWigs.com site is beautiful. But, note the warning...

An introduction to commercial air travel for CEOs only. No minions, lackeys, or "regular" people allowed.

Talk about taking advantage of a bad market to sell your service. Nice move. Now, go and enjoy it. Or, have your assistant's assistant go enjoy it, if that's more your speed.

CodePad.org - Seeing is believing

I've been enjoying the programming problems (and solutions) offered by Programming Praxis. I noticed a neat feature they offered in the latest solution, the author linked to a codepad.org.

CodePad is a site where you can not only store snippits of code, but actually execute them as well. This insures that they're correct, among other things.

Consider this example:

Seems like a really handy site.

Programming Praxis also has a nice article on blogging source code content that's worth a read.

It's Time To Have Your Own Website

I was browsing livingdigitally.net and came across the following update:

My 7-year-old daughter wanted a website like mommy and daddy. We spent the afternoon building this: http://bit.ly/IxsG9

Now take a moment and check it out - Ocean Alive - a blog about ocean animals.

It's wonderful. Just think, if a 7 year old with a little help from Daddy can pull this off, what do you think you as an adult can do?

Head over to Wordpress, Blogger, PBWiki, Google Pages, or Squidoo and sign up today. It's free. Then start typing.

That's all there is too it. And chances are, there's probably even a 7 year old around to help you if you get stuck.

Developing AIR Apps on Windows With Unix Tools

I've been happily developing Flex apps on Windows using Unix dev tools for some time now. Last week I wanted to create my first AIR app - which is just like any other Flex app, but with access to desktop friendly APIs.

Here are a few hurdles I had to clear before I could be productive.

Compiling AIR Apps

I've found emacs + fcsh to be a great combination for developing and compiling Flex content. If you try this same approach with AIR specific classes, you'll get a compilation error explaining that the class doesn't exist.

After much poking around, I learned that web based Flex apps and AIR based Flex apps both use the same compiler, but start off with different configuration files. As an aside - if you've downloaded Flex 3, you have everything you need for AIR - there's no need to download the AIR SDK. To control the different config file in use for compiling, you can set the line argument +configname. You could, for example, run the following two commands:

 # Compile with web based Flex settings
 mxmlc +configname=flex Foo.mxml

 # Compile with AIR based Flex settings
 mxmlc +configname=air Foo.mxml

It's worth noting that two commands toggle between the configuration files found in $FLEX_ROOT/frameworks/flex-config.xml and $FLEX_ROOT/frameworks/air-config.xml. Don't forget to enable debugging in these config files to get line numbers when there's an exception (oh, and for web content, you'll want the debugging Flash player).

I folded the above information into my emacs setup by adding the following functions:

(defun fcsh-flex-mode ()
  "Setup fcsh to compile in flex mode"
  (interactive)
  (setq *fcsh-mxmlc-command* "mxmlc +configname=flex"))

(defun fcsh-air-mode ()
  "Setup fcsh to compile in flex mode"
  (interactive)
  (setq *fcsh-mxmlc-command* "mxmlc +configname=air"))

Now, when I'm ready to start developing I type M-x fcsh-air-mode and then M-x fcsh-compile, and I'm all set.

Previewing AIR Apps

There's nothing too exotic here. The Flex SDK comes with the command adl.exe. Go ahead and point it to your application descriptor, and you can run your AIR app without installing it:

  adl.exe Foo.xml

Packing AIR Apps

Packing up an AIR app isn't all that difficult. You'll use the adt.bat file with the -package argument. I've found make works great for this.

Before, you can get started though, you'll need to create a test certificate to allow for the package process to continue. To setup a test certificate (which apparently is its own stand alone keyring as well), you can run the command:

adt.bat -certificate -cn "YourName" -c US 2048-RSA cert.p12 somepass

Once you've got cert.p12, you can setup the following make rule to package up things quickly:

# Makefile to build our AIR app
ADT = /c/tools/flex3/bin/adt.bat
APPS = Foo.air
CERT = cert.p12
PASS = somepass    # same as what you used to create with above

# Our rule to package up Foo.air
package : $(APPS)

%.air : %.xml %.swf
  $(ADT) -package -storetype pkcs12 -keystore $(CERT) -storepass $(PASS) $@ $<

Now, packing up my AIR file is a simple one command (make) ordeal.

Enabling One Click Installs

One of the features that attracted me to AIR is the one click badge install. Essentially, users without AIR installed can click on a widget on your web page, and the appropriate AIR runtime and application will be installed. Give it a try here here.

There's nothing Unix or Windows specific about getting this setup. I had initially thought that the badge functionality was specifically built into AIR. But, it turns out, it's just a nice add on.

The Flex SDK comes with the badge code in its samples directory (named, not surprisingly, badge). To get the badge working, all you really need from that directory is badge.swf. You should also look in default_badge.html to see how it's used.

The badge is nothing more than a regular SWF file that takes in arguments which include the preview image to show and the AIR file to download/install.

The first time I attempted to put this in place, I attempted to install the application and got the error:

Sorry, an error has occurred.

The application could not be installed. Try installing it again. If the problem persists, contact the application author.

Error# 2032

But I am the application author - who do I contact? Well, Google of course. And Josh Buhler ran into the same problem I did. Turns out, the path handed to badge.swf needs to be a full URL, not just a relative path to your AIR file. I fixed this, and my badge worked as advertised.

Happy Coding

After getting the above tools straightened out, I'm happy to say, I've been off and developing without a problem. If you haven't tried AIR, you really should. Imagine the lexically scoped beauty of JavaScript with a complete and modern widget/functionality set. It's good stuff.

A special thanks to Christian Cantrell, who was instrumental in me understanding the nuances of AIR and how to get the above working.

Sunday, March 15, 2009

The Family That Drinks Beer Together...

We had a great treat tonight with my Aunt and Uncle in from California. Shira suggested Gordon Biersch for dinner, which was a wonderful choice. I think the beer was a good warm up for Grandpa's birthday party coming up in October.

Who am I kidding, my liver is going to need a lot more than a beer to get warmed up for that event.

It was great getting to see them on a happy occasion and we hope they come back soon. Or, at the very least, we'll see them at next year's conference!

Friday, March 13, 2009

A Source For Random Clever Text, or a Twitter API + PLT-Scheme Example

The internet radio station Boot Liquor, plays an eclectic mix of country music. Recently, I learned they broadcast their playlist over Twitter, to make it easy to see what's playing now.

Say what you will about the sound of country music, but the lyrics and even song titles are often wonderfully clever/ironic. So, watching the BootLiquor twitter feed, I couldn't help but think this would be a novel source for random text. (And why would you need this random text? No idea. It was just too interesting too ignore.)

With tongue firmly in cheek, I present the following following code which uses the Twitter API to pull down the latest data and spit it out in a list.

On a more serious note, you can never have too many examples of code parsing XML and doing something useful with the result. Here's the code - of course, you can generalize it to pull from any Twitter feed and do anything with the status updates. I can assure you, it's not limited to country music.

#lang scheme
(require net/url net/uri-codec  xml   scheme/match
         srfi/13  srfi/1    games/cards)

(provide/contract
 [random-clever-text (-> (listof string?))])

(define (status->text s)
  (string-trim (regexp-replace "^.* - " s "")))

(define (random-clever-text)
  (let ([xml (xml->xexpr (document-element
                          (read-xml 
                           (get-pure-port
                            (string->url "http://twitter.com/statuses/user_timeline/bootliquor.xml")))))])
    (shuffle-list (filter-map
                   (match-lambda
                     [(list-no-order 'status (list 'text '() junk text) _ ...) (status->text text)]
                     [else #f]) 
                   xml)
                  7)))

And here's the current results of running the program:

;; (random-clever-text)  =>
("Small Motors"
 "Baggage Claim (The Cowboy Song)"
 "My Heart Is A Ufo"
 "She Loves To Ride Horses"
 "Whiskey River"
 "Sunday Morning Coming Down"
 "Una Soda"
 "We Live A Long Time To Get Old"
 "Careless Coin"
 "Camile"
 "Adrift On The Sea"
 "Nothin' Makes A Man Go Crazy"
 "Going Home"
 "If The Drink Don't Kill Me"
 "Lucky Tonight"
 "All Downhill"
 "So Much Wine"
 "White Line Fever"
 "Let's Have A Party")

Hmmm, nothing particularly clever. Oh well, it was worth a try.

Thursday, March 12, 2009

Information Beauty

Rachel Maddow mentioned flowingdata.com, a site dedicated to graphical visualization.

For example, consider this graphic showing all of Evolution in a single photo:

It looks like it would be a fun site to poke around and get educated in the many creative ways to display information.

Speaking of information visualization, check out this approach to thinking about 1 trillion dollars (thanks laurakozak!).

Two Introductory Web Dev Tutorials

Here are two web dev tutorials I've come across and think are worth a mention:

Web Applications in PLT Scheme - This is (yet another?) introduction to web development with PLT Scheme. It's nice in that it covers not only the basics of HTML generation, but goes as far as storing data in a SQL database. This introduction looks gentle enough that non-lispers will find it especially useful. Once you've made it through the tutorial, check out Jay McCarthy's blog, he's got all sorts of cool articles about web development features in the PLT Web Server.

How To Develop with CSS - If you're still using <table> tags for layout or naming your styles style1, then this article is for you. It goes beyond the syntax of CSS and talks about coding HTML/CSS in a high quality way. I found it a useful refresher, and a bit of reminder to get back to coding cleanly.

What tutorials have you seen these days that you'd like to share? Please use the comments and do so!

Democrats on an Escalator

This clip is making it's way through twitter. Yes, it's goofy - but, I have to say it's quite funny.

I give you, "Democrats on an Escalator:"

OK, MoveOn.org, the ball's in your court - what would a Republicans on an Escalator be like?

Wednesday, March 11, 2009

Definition: Layup

While developing, I was struggling for just the right term - so why not make a new one up? I give you Layup.

A Layup is a cross between Overlay and Pop-up. It's an HTML convention where you create a small window, like an HTML pop-up, but do so using DHTML. Technically, the pop-up is just a div that's overlaying your current page.

Sample usage:

Why don't we create two layups on this page: one for the help message and one for the search preferences. That way, users won't have to leave the page to get this information. On the other hand, because it's a layup, we won't need to worry about pop-up blockers.

Tuesday, March 10, 2009

Almost My 15 Minutes Of Fame

I was almost popular today - check it out, kelly killoren bensimon was #16 on Google Trends.

For at least a moment, bensimon was more popular than chuck norris birthday and what is purim. Though, I it still didn't beat out maytag recall and the always popular ulysses s. grant vi.

Alas, I'm not at all related to Ms. Bensimon. Though, if you google for bensimon you do find the this blog.

Considering the reason Ms. Bensimon is in the news, perhaps it's a good thing that there's no relation.

Thanks to Chris for the pointer to my near fame.

Chag Purim Sameach!

And a very Happy Purim to everyone! The photo below is from the Megillah reading this morning (just as we were about to start).

The Book of Esther has all the makings of a hit soap opera. Sex, violence, double crossing and intrigue.

I'm always struck by the ending though. At this point, the King has given the evil Haman permission to annihilate the Jews. The King, after Esther's plea, realizes that this wasn't such a good idea. His solution?

"Now, write up a new decree concerning the Jews as you see fit, and sign it with the royal signet ring. Since the first decree was written in the name of the king, and signed with the royal signet ring, it cannot be repealed."
...
The decree stated that the king permits the Jews of each city to gather and defend themselves, to destroy, kill, and eradicate all the armies menacing them, children and women, and to pillage their property,

In other words, the King couldn't undo his order. But, he could write a new order giving the Jews permission to fight back. And that's what he did.

It's an odd solution, for surely the Jews would have thought to fight back even without a royal order. But for some reason, I actually buy it. I think there is something powerful about having someone externally encourage you to take an action that you could already take, if only you had the will to do so.

It's certainly an interesting approach to ponder.

Chag Purim Semeach!

Monday, March 09, 2009

A Linguistic Journey

Joe Marshall is documenting his journey from being unimpressed by computers, to be being a Lisp Hacker. They are a wonderful read: here, here and here. Oh, what the heck, just read his blog.

I wish my journey were as exotic.

Before my senior year in high school, I really had no idea what I was going to go to college for. Perhaps something photography related, as I really enjoyed that. But, I wasn't sure how I would make a living by it. Journalism, maybe?

Then, I took AP computers with Dr (Mr?) Kreiger (sp?). We started off on dumb terminals with a line editor, but luckily, a few weeks into the course we started using Macs. Pascal was the order of the day. It was a disaster. I got a 2 on the AP - the score one gets for basically showing up.

But, there was something that felt right about it. I remember staying up till 2am trying to figure out why my for loop program wasn't working. I finally figured out I was doing:

 for(...);
  begin;
   for(...);
  ...

rr, something like that. In other words, I had a perfectly correct program, but included a semicolon in the wrong spot. There was something magical about unraveling the mystery.

It was pretty clear from that point on, I would be a CS major.

And so it was at University at Buffalo that my CS career started. Again, I didn't get off to the best of starts. CS 113 was the hardest class I ever took - the basic comp sci programming course. The language this time was C++. Yuck.

I can recall the time early on when I had gotten a low grade on a project for a simple error - I had written += as +=, and so the program didn't work. I plead my case to the TA, who told me some story about how a NASA space ship had crashed due to a trivial FORTRAN error. The lesson: it didn't matter how few characters were involved in the bug - a bug, was a bug. I was to accept the C+ I got on the project and go on with life. And so I did.

From there, things got easier and just 11 years out of school I can finally say, this programming thing isn't all that hard to learn, or even get good at. It just takes plenty of practice.

But I like Joe's story better - so go, and read it.

Sunday, March 08, 2009

Laura and Jamie Tie The Knot

What a joy it was to get to attend my cousin Laura's wedding to my brand new cousin-in-law, Jamie! They had an on the beach wedding which was just the most perfect thing you've ever seen. And then we had a night of excellent food, wine and dancing to top it all off.

I even got to meet my new 2nd cousin, Asher, who's just a few months old. While everyone was looking sharp last night, Asher, in his tux-onesie, definitely took the take for most cute.

We've got a couple more weddings coming up this year in my family - so this is just the first of many simchas we have coming up. How wonderful is that?

Some photos from the evening are below - as usual, they don't do the event or venue justice:

Mazel Tov to Laura and Jamie, we wish you guys lots of happiness with your new life together! Don't forget to visit us in DC :-).

Friday, March 06, 2009

Like Out Of A Brochure

Wow, this place is gorgeous! Any reservations I had about getting on any airplane have been erased.

So, now I'm sitting outside, having a quick bite to eat - the sun is shining, there's a cool breaze and the WiFi is free. What more could you ask for in a remote office?

Back Too soon?

I have to admit, I'm not excited about the prospect of getting back on an airplane after my little travel-fest yesterday. But, the travel is for a good reason - my cousin is getting married and I'm flying to Florida for the wedding.

How cool is that?

Thankfully, I don't think the jet lag has kicked in from my trip yet, as I'm feeling pretty good.

I did try to check in for my USAir flight at a United Kiosk - but I think that's just me not paying enough attention to the ticket Shira bought me. Nope, can't pass that off as a jet lag oops.

Let's see if I can make it through one more set of flights as smoothly as the previous ones have been.

Thursday, March 05, 2009

Portable Forth Learning Environment

I dusted off my ancient HP 200LX palmtop in the hopes of using it to do some hands on learning of Forth while on my latest trip. I figured with 40+ hours of flying, there had to be some time to spend coding? The experiment turned out to be pretty successful - I've learned quite a bit about Forth, embedded programming, alternate approaches to problem solving, got a new use out of some old hardware, and most importantly, passed the time in various lines and flights much faster.

I was reminded at what an amazing device the 200LX is. The keyboard is remarkably usable. And, the device really is a DOS based computer - so anything that runs on DOS can run on it. And it was great to travel with - a couple double AA batteries lasted the entire trip. Something my cell phone and laptop can't begin to compete with.

Here's what the device looks like - I'm using my G1 as reference:

What makes this experiment successful isn't just the 200LX hardware. There's also the Forth implementation. I went with HP-Pygmy Forth, a version of Forth customized for the 200LX, and I wasn't disappointed. What beautiful software this is.

It's small enough to run comfortably on the palmtop, yet serious enough to do sophisticated Forth programming with. It's also completely self contained - the software provides it's own editor to write code in, as well as a really easy way to view the source code of itself. There's even extensions available for working with graphics on the device. I really can't say enough good things about how impressive HP-Pygmy is.

I had big plans for developing some significant code in Forth - I was thinking about writing my own Sudoku game. However, I never got close to implementing it. Though, I did learn a number of peripheral lessons and wrapped my head around embedded systems and Forth.

I really enjoyed being able to work on a programming problem while standing in a lengthy customs or ticket line. There's something pleasantly active about programming that reading a magazine or book can't compete with.

This, of course, has me wondering if I could replicate this sort of environment on my T-mobile G1 phone, so I wouldn't have to carry around two devices. Seems simple enough, but I'm not sure. The whole self contained nature of HP-Pygmy, including an editor, compiler, assembler and source code, is something I haven't seen in a Java based Forth. On the other hand, a Java based Forth should allow me easy access to Java classes and method calls, which means that developing software that actually does interesting stuff on the G1 seems quite possible.

Regardless, it sure is a wonderful feeling to grasp new concepts - and if there's one thing to be said about Forth, it has many new concepts.

Kvetching From Sydney to LA

A Mid Air Rant:

Currently:
Altitude: 38,653 ft
Time to dest: 0:34
Distance traveled: 7320 miles

After having flown long flights on British Airways and Qantas this trip,I can tell you, this United flight I've been on for the last 12 hours has been an absolute joke. Let's see...

Movies are shown in sequence, on a single cabin screen - so while the selection of movies was good, seeing them was a pain. I'm in Economy, so leg room is non-existent. I needed to squeeze my laptop in just so to even see part of it.

And then there are the parts of the flight out of United's control. Like the screaming infant sitting 4 seats away.

And don't get me started on these Kosher Meals, My heavens. It's like they intentionally make them inedible. Mid flight, I woke from my haze to find a meal in front of me. Upon breaking the seal, I found a damp tray of some grayish goo that I didn't have the stomach to even try. Our people need fewer doctors and lawyers and more chefs.

And then there's the whole tone of the service. Last night, at dinner, they came through and offered meals. My seatmate to the left (I'm in my preferred isle seat) didn't make her choice fast enough and the guy got frustrated and was ready to move on. It was like a scene from a refugee camp - don't act fast enough, go hungry. And breakfast hasn't been much better - she asked for water *and* tea and you'd think she wanted caviar with her breakfast.

There's a fine balance between efficiency and being overly short with your customers. They've drifted to the later.

This poor service issue is especially obvious when compared to Qantas or BA - where the whole tone was that of "what can we do to make your flight more pleasant?" versus the United way which comes across as "what can you do to make this flight easier for us?"

On the Qantas flight, they noticed Shira wasn't signed up for a veggie meal, yet she didn't want the meat breakfast. So, they proactively found her a veg option. That took someone paying attention, versus just getting through meal service quickly.

*** End Rant ***

Whew, I feel much better now. I hate spewing all this negativity, so I'll finish this note with a list of positive things about the flight:

- My laptop battery continues to shine - lasting longer than I did (3+ hrs, before I was exhausted)

- My G1's battery did great too, playing music for 5+ hours and still having battery life left to write this note

- I listened to a long recording I had of the Drone Zone, and it helped me to get a good number of hours of sleep (5ish, I think?), so I'm as rested as I'm going to be.

- So far, the flight has been safe and we look like we'll have an uneventful landing. And as my Mother-in-Law likes to say, any landing you can walk away from is a good one. I'll be glad to extend that notion to the whole flight.

- In 30 minutes, I'll be back on US soil!

To cap it off: America may be the leader in many things - air travel, I'm sorry to say, isn't one of them.

Wednesday, March 04, 2009

The Way Home

I'm typing this note from the Sydney Airport, as I prepare to head back home. I'm typing this note from one of those Internet Kiosks, where you effectively pay by the minute. It's not too expensive (a little over a dollar for 20 minutes - enough time to jot out this blog post), but I still feel kinda dirty for paying for anything by the minute.

It's hard to belive the trip is now over, but it is. All I need to do is to make from here to LA and then back to Virginia. It's about 18 hours of flying time, but who's keeping track?

I find it interesting that I'm flying into the West Coast after having left the country from the East Coast. In other words, I'll have circled the globe this trip. I'm not sure why I find that exciting, but I do. What can I say, I'm easily entertained. I guess I now know a bit how Magellan felt after his voyage. Minus the scurvy and all.

Crap, I was hoping to post a photo or two that I had snapped as I was flying from Canberra to here. Alas, I can't get the USB port on this kiosk to behave. Oh well, just do a Google Images search for Sydney Opera House, and you'll get a view of what I saw flying in.

See y'all stateside!

Canberra And The Darwin Exhibit

Today Shira and I had a really special treat - we got to see the Charles Darwin exhibit at the National Museum of Australia.

I hadn't really appreciated what a unique guy Darwin was. He was both extremely logical (the list of pros/cons of why he should get married is priceless) and had a love of natural science. Yet, he was a poor student and didn't do particularly well in school. He was given this amazing opportunity to travel around the world and collect samples, yet almost didn't go because his father thought it was a bad idea. And when he did go on the trip, he was able to observe remarkable phenomena - ranging from earthquakes to strange fossils to obscure species of rats. And he absorbed it all.

He was also able to coalesce his different findings he had into one theory. Rather than proposing natural selection based on just the turtles he saw on the Galapagos Island, he found examples everywhere he went (including the turtles). As the exhibit showed, the breadth of what he studied was nothing short of remarkable. Of course, he had a leg up on the competition. In 1831, how many people had access to the entire world in which to poke and learn from?

I also found it interesting how crude his tools were. Using nothing more than a magnifying glass and a microscope, he was able to deduce the theory of evolution. At the end of the day, it was just a matter of observing nature, taking lots of notes and then trying to make sense of it all.

The exhibit definitely had a bit of a propaganda (educational?) feel to it, in terms of the evolution versus creationism debate. They made it quite clear that evolution was the only explanation science had to offer as to how man developed. They also had a short movie I found interesting on what a scientific theory is. As they explained, theories don't get turned into facts, they are used to explain facts. So, calling it a Theory of Evolution doesn't imply some sort of doubt in it.

During the introductory movie, Shira - who's a big fan of science and Darwin's theory - turns to me and says, this is like an Obama rally for scientists. By the end of the film, we were both ready to start chanting, "Yes we can!"

The rest of the day was spent checking out some more of the classic sites Canberra has to offer. Because Canberra is so spread out, it included plenty of walking. But, the day was perfect for it, so who can complain?

Here's a few photos from the day...

Tuesday, March 03, 2009

To The Top Of Mt. Ainslie

Yesterday, I took a fun jog to the top of Mt Ainslie. See, this is exactly what I'm talking about when I say Canberra is the most under rated city in the world. Not quite sure how I would get to the top of the mountain, I started jogging towards it. When I got to the base of the mountain, behind the top notch War Memorial, I learned there was a trail to the top.

Not only is it a well maintained trail with excellent views, but they also have plaques along the way to remember various engagements in WW II. Add to this the fact that I ran by a family of kangaroos, and I have to say, this was one terrific experience.

Here are some photos:

So here's my recommendation: If you do make it to Canberra, the first thing you should do is visit the War Memorial, and then make your way up the trail in the back for a spectacular view.