Web Version Gets New Coat Of Paint

I spent 6 hours today with my local designer and the web version of BCC is quickly taking shape.  He has a much better eye for design issues, including UI and usability issues, than I do.  We’ve totally revamped almost all the screens for the web version, with the exception of (ironically) the one users spend the most time on.  It actually now looks almost pretty.  I would include screenshots except I am on Linux and GIMP scares me.  You can see for yourself.

I also started to rewrite some copy in preparation for the launch.  Hopefully this will be out the door to customers by tomorrow evening.

Still needed:

  • “Forgot password” recovery
  • Analytics — can be postponed
  • Integration with purchasing system — still needs testing
  • Tune up of front page copy to address the web version

Happy Fourth of July everyone!

Comments Off

Bingo Card Creator Goes Web 2.0

Three years ago, on July 1st 2006, I released version 1.0 of Bingo Card Creator.  It was ugly, underfeatured, and bug-ridden.  Now, it is ugly, underfeatured, and bug-ridden… with AJAX!

Feast your eyes at this very, very early sneak peak.  You’ll want to click one of the various “sign up now” text links rather than the download a free trial ones.  I haven’t gotten around to sitting down with my design guy and redoing the buttons and the sales pitch for the free download yet.

Featurewise, it isn’t quite competitive with the downloadable Bingo Card Creator, to be honest.  A few of the power-user features, particularly design-focused things like picking fonts, are shockingly difficult to implement in a good way in a web application.  Others, like consistent columns and call lists, I just quite haven’t had time to integrate yet.

I was really impressed that I got the live preview of the bingo cards to work as well as it does.  Check it out — I am very proud of that work, although it is rough around some edge cases.  It took probably half of the development time of the site but I think getting users super-responsive feedback to their actions is worth every minute of it.

AJAX Technical Detail

How does it work?  While users are typing words into their text box, Prototype periodically checks it for changes and, if there are any, serializes the contents of the form and calls an AJAX function on the server.  The server takes the contents of the form and saves it to a “scratch” record in the database, which is not otherwise visible to the user.  The return value from this function overwrites part of the calling web page, including replacing the previous preview image with a new image if the scratch value has changed (same url, new query parameter — this tricks browsers into always requesting the image anew rather than checking their cache).

The path to the image on the server is actually just more Rails code, which checks to see if the scratch record has changed since the last time it produced an image.  If not, Rails tells Nginx “give them the last image we wrote, straight from the disk”.  If yes, then Rails uses Prawn plus a boatload of custom formatting logic to create a PDF, then calls out to ImageMagick to turn that into a GIF and resize it, then writes that to the storage area on the disk and tells Nginx to serve it.  Total time per request: on order of 300 to 800 ms.  My back of the envelope math suggests that my server, with two Mongrels, can probably support about 20 teachers simultaneously editing cards as fast as their fingers can go… after that I need to get worried (or upgrade to a bigger slice, which I might do anyway).

Still To Come

I still have to:

  • rewrite my copy to address the existence of the web version
  • get Bingo Card Creator 3.0 tested, in particular the features where it links to the website
  • give the user workflow a graphical upgrade, because pretty buttons sell B2C software
  • rewrite my page templates to push both the trial and the online service — I sense a lightbox coming up…
  • improve usage stats collection (can be pushed after release)
  • test integration with the purchasing funnel to make sure it works right
  • give some spit-and-polish to some usability issues

I’d love if you have any comments on it.  Take it for a spin and  let me know.  This sneak-peak is not using the production database, which means when the sneak-peak ends you’ll lose anything you did with it.  In the unlikely event you want to use this for something important, make sure you save your cards locally.

Comments Off

Why does cron hate me so?

Once *again*, cron decided that it would stop deleting my Rails cached files after I upgraded to Hardy. I’m totally stumped as to why it happened — the logs say that the rf -rm happened at the scheduled times for the last two weeks, and I was able to successfully do it by sudoing into the appropriate user, but the files were still on disk and being happily served by Nginx, oblivious to the fact that Mother’s Day and Cinco de Mayo had long since passed.

Argh, I hate computers some days…

Comments Off

Dropbox is saving my bacon

About a month and change ago a Japanese coworker asked me “Hey, Patrick, have you ever heard of Dropbox?”  All I knew is that they were some vaguely storage-in-the-clooooooooooooooooooooooud startup, but not really the specifics.  But since he and another coworker were interested in it I did some checking to tell them what they would need to press to sign up & etc.  And, yep, storage in the cloud, painless backup, blah blah.  So I grabbed an account for the heck of it and decided I would get around to backing up my files one of these days.

Sigh.  You think we would know by now, right?  “I’m going to start a backup any day now” ranks right up there with “Hmm, well, we haven’t heard from that freaky serial killer in a while.  I think I’ll stay in the house.”

This is despite Benji and Andy Brice both having recent hard drive failures.  (Andy’s, which was a year ago so I suppose not so recent, even came with the title “Your harddrive *will* fail”.  Yeah yeah, sure, and I bet you think there is a machete-wielding maniac over in the next room.  Bah, I think I’ll take a bath.)

Thankfully I was sufficiently moved by their advice to start keeping backups of my servers at Slicehost, which has the added benefit of protecting my source code (since I have my repositories on those servers).  Most of my critical business data is already off of my laptop — its at a Google server farm, or chilling on a Slicehost server, or over at Paypal, but there is still quite a bit of sentimental value in my photos and nuisance in having to reconfigure, e.g., Eclipse to match my personal setup again when I reinstall it.

Anyhow, today the inevitable happened: my Vista-using laptop decided to start the sputter and die deathspiral.  Thankfully, after an hour of fruitless restarts, I was able to boot into safe mode, where I am right now.  I think the hard disk covering some of the code loaded by all the bells&whistles that autoload when the machine boots is toast.  Luckily untoasted is my ability to read the rest of the disk and run Dropbox.

Which is currently streaming my last few folders of Really Don’t Want To Lose That to safer pastures.  Here’s $100, Dropbox — thanks a million.

Fun tip for Vista users: mklink /D name-of-your-symlink C:\Users\blahblah\Documents\whatever will create a symlink between two places on a Vista OS.  If you have a symlink pointing out of your Dropbox folder, dropbox will perceive the stuff outside (say, a full Cygwin installation) as being inside of the Dropbox, and automatically sync it for you.  I really appreciate that trick, as it meant I didn’t have to copy/paste the files I need to update and risk more harddrive activity at the moment.

2 hours until the last of the files are off the disk.  Go Dropbox, go!

Comments Off

Yay for A Productive Hour

I finally killed that little permissions error (protip: if you symlink a to b, and are wondering why you can’t access a/c, a/d, and a/e despite the preferences on a, c, d, and e all being right, check to make sure you’ve chmod-ed b/. properly.)

I also did my very first push out to github, which was slightly on the painful side (Windows user — I’m used to Rails programming having its share of pain) but cleared up fairly fast. I think I’m really going to like git for source control, although since I already have a SVN repository I’ll probably keep that as my main method.

Here’s what I did: took (a particular version of) Delayed::Job and extended it so that it can accommodate multiple workers at once. You can see the details here.

Comments Off

That too ENTIRELY too long

Well, on the plus side, the last three days have probably been my most productive programming spring ever.  On the minus side, a lot of it was spinning my wheels fighting against problems rather than making forward progress.  I blame fatigue.

What I Have Done:

Bingo Card Creator 3.0.  Whee.  It can interact with the server to save user’s word lists in the cloooooooooooud.  Which is apparently the $10 buzzword for a client-server application these days.  For extra bonus points I threw in PDF generation on the server — How hard can it be? – and then got to rediscover the joys of heavy duty fat client Java application development.  Did you know that there is no way in Java’s standard library to copy a file from point A to point B?  Or that if you open the desktop in a Java open/save window it will show you some GUIDs as possible folders?  Fun stuff.

What I Have Mostly Working

Delayed Job integration.  If somebody tries to generate a thousand bingo cards on Prawn, that essentially takes one of my Mongrels and ties it up for a minute.  Behind that, requests start piling up and not getting executed.  Plus, should they have a connection hiccup, well, guess I lose.  So rather than generating PDFs in the request/response cycle, they get queued up for execution in the near future, using Delayed Job.  

Why is it only “mostly” working?  Well, following standard Linux best practices, the user that is supposed to execute the jobs has very little in the way of privileges.  Apparently too little to actually touch his directory.  I have tried everything I can think of to fix this, with no dice, so its time to walk away and come back fresh later.

What Isn’t Even Started Yet

The web version of the software.  (Well, OK, technically the PDF-ification and most of the existing infrastructure will get reused, but I still have to actually make the screens for it, and then tie them into the purchasing pathway.)

I hope to get the web stuff mostly working this weekend and then open 3.0 up for beta testing.  If you’re interested in helping out, please drop a comment, particularly you Mac freaks out there.  

You can see the newly redone PDFs and GIFs for most cards at http://staging.bingocardcreator.com .  Still got some bugs to iron out of that, though…  (Prawn + Imagemagick is literally fifty times faster than rendering through the Windows printer and then screenscraping Adobe Acrobat reader then pasting into Paint — automated, naturally — for cropping out a GIF screenshot, incidentally.)

Comments Off

572 day uptime…

11:59:49 up 572 days, 20:07, 1 user, load average: 0.00, 0.00, 0.00

Sadly, I just had to resize the slice that has been running bingocardcreator.com for the last 572 days. This requires about a minute of downtime. Drats, my perfect record!

Comments Off

Hard to get motivated some days

I’m wrapping up day two out of the five-day vacation I have for Golden Week, and have not quite gotten as much accomplished on getting the new version out as I had hoped.

Task list to embarass myself into working hard tomorrow:

Bingo Card Creator 3.0

  • Client connects to server, validates license key
  • Server accepts connection from client, validates and if necessary reissuses license key
  • Client contacts server, server saves word list to database
  • Client-side GUI for saving word list to server
  • Client contacts server, server responds with word list
  • Client-side GUI for loading word list from server
  • Client contacts server, server responds with list of client’s word lists
  • Client-side GUI for loading word list from server
  • Client contacts server, server responds with PDF of specified word list
  • Client-side GUI for configuring PDF
  • Client-side GUI for saving PDF
  • Update license agreement to clarify usage of server
  • Client requires acceptance of updated agreement to use server
  • Set e-junkie to use automatically generated license keys instead of saved ones to stop reissuing the same key (sidenote: my fault, not theirs — I used the same key list for the CD version and download version)
  • Update PAD file to reflect Bingo Card Creator 3.0
  • Recruit Mac testers for BCC 3.0

Bingo Card Creator.net (my internal name for the web app version)

  • Set up staging.bingocardcreator.com for testing
  • User account page — edit name, email, password, Registration Key, etc
  • User dashboard — display existing lists, printouts
  • Word list editing workflow
  • Printing workflow
  • Generation of bingo cards PDFs
  • Cache saved PDFs to disk
  • Rewrite content publication to use Prawn & ImageMagick instead of laptop automation
  • DelayedJob integration to remove PDF generation from HTTP request/response cycle
  • Lightbox to present download BCC or sign up for BCC.net choice
  • Lazy logins (no login for guest mode, upsell to free trial)
  • Free trial upsells to $$$

Random tasks

  • Integrate signup with MailChimp API to do autoresponder series for hints & tricks
  • Set up mailing list for newsletter
  • Resize Slicehost slice to 512MB to accomodate anticipated need for DelayedJob instances and extra Mongrels
  • Blog about why I’m finally spending time to make a web version
Comments Off

Major Progress on BCC Web Application

I did some more work on the upcoming BCC 3.0 this weekend, which is going to coexist on the desktop and the Internet.  (Feel the power of Web 2.0… several years late!)  

The biggest challenge with BCC coding-wise has always been laying out the bleeping cards.  Mostly, this is because Java has very primitive printing facilities.  I render everything to a Swing canvas and then essentially print the canvas, and Swing is most definitely not designed as a printable format.  This exacerbates some issues which are always going to be hard, such as “How do I automatically size text so that it looks visually appealing without requiring user input?”

Since printing in a web application is sort of hard to control (CSS and usability issues galore), I’ve opted to generate PDFs, which is a quite common choice.  The Prawn library (a new-ish alpha-quality Ruby library for PDF printing) is an absolute lifesaver — I’ve got better behavior out of it in 8 hours of playing around then I’ve been able to coax out of BCC in 2 years.  There is still some ugly spaghetti code hiding in the bowels of it, but its literally a quarter of the size of the stuff in BCC itself, and much, much more comprehensible.  

Feast your eyes: 

(I know, Roald Dahl’s name is screwed up due to some sort of encoding issue.)

Here’s the same card printed in Bingo Card Creator:

I really prefer the Prawn version to the Java version for out of the box behavior:

  • prettier autosizing (particularly for the column headers)
  • better line breaking logic
  • better centering of the words in the squares
  • capability to add titles (often requested by customers, never implemented in Java because it would essentially require a rewrite of code that I scarce dare to tread in)
  • capability to add watermarks/footers (often requested by, erm, me)

Printing is, by my estimation, about 90% accomplished.  (I still need to work out some internationalization kinks and then figure out how I’m going to generate the PDFs and store them outside of the web request/response cycle — I don’t want someone printing 800 cards for a Fortune 500 retreat to lock up the server accidentally, but I do want to support that use case.)

After I get printing done I still need to:

  • Code GUIs for word entry, loading/saving lists, etc.
  • Figure out user management (usernames/passwords, forgot password, restricting access appropriately, etc)
  • Extend my admin interface so that I can address issues that people have, should they have any.
  • Figure out how to integrate the web app into my site without confusing the heck out of people.
  • Rewrite a whole lot of copy.  (See the above point.)
  • Sprinkle my pages with copious sign-up-for-webapp-now calls to action.
  • Adjusting the BCC client for close-to-seemless integration with the website (save to/load from Internet)

Now that printing is mostly working the technical issues are all downhill from here.  My biggest worry is the perinneal one for web applications: can I convince non-technical users that “web sites” are worth paying money for?  This is one of the main reasons I’m not planning on deprecating the downloadable version anytime soon.

Comments Off

Bad Places To Have Bugs: Pricing Logic

About a week ago I noticed a deficiency in my understanding of how my shopping cart actually worked for purchases of 2+ units: specifically, e-junkie thought they were mispriced and was bouncing the transactions, resulting in a customer getting charged but not getting their key automatically. I only get about one of these orders a year, so I hadn’t seen the behavior yet. *sigh* So I did something I thought I would fix it: turn on variable pricing, then set prices manually through my cart. Done, right?

Wrong. The next day, I started getting orders at $20.00, the new price floor. I looked around for the possible cause and figured that if you had Javascript disabled or clicked through my cart before its Javascript could load, you’d get taken to e-junkie’s fallback hosted cart, where you’d be given the option of modifying the price. For some reason it defaulted to $20, despite $29.95 being set as the default price. Not quite sure why. So I fixed it, by making the default item be a single copy at $29.95 and only having the pricing logic apply when buying through my cart.

But still the $20.00 units kept coming. Then it hit me — it wasn’t actually that edge case, it was a different edge case — involving an ugly mess of Google Checkout, e-junkie, and my code. Grr. So I went back to Plan A: reverted to the cart which charges 1,499 customers a year correctly and causes 1 guy to wait a bit while I decide how to address this in a more long-term fashion, rather than having half of the purchases this week get screwy behavior.

I lost about $120 that I know about in arbitrary discounts, plus more if anyone was scared off by the weird inconsistency between my site’s pricing and the pricing at Paypal/Google Checkout. Not that I blame them. Grr.

Memo to self: self, you’ve said it before, but avoid doing 5 minute changes at midnight.

Comments Off