Cyberduck 3.2.1 is Out

July 15th, 2009

Cyberduck.jpg

This morning I noticed that the folks writing Cyberduck came out with a minor point release - and it's been a long time in coming. I can't remember the last time I saw an update from this crew, but then again, the software has been stable and hasn't needed updating.

It honestly looks more like a bunch of little feature enhancements as opposed to bug fixes, but that's just by count on the release notes. In any case, got it, and use it from time to time.

Another Start of Something Really Interesting

July 14th, 2009

cubeLifeView.gif

Today I needed to get really busy on the next phase of my web server/services - intraday alerts. Basically, we need to have a system whereby it's relatively easy to configure multiple alerts based on the data we collect about the company during the day. The first test is a simple one - if the P/L of any portfolio jumps more than a $1 mil in one tick - either way, then it's something I need to know about because it's likely bad data.

You can think of a lot more business-useful cases where it's not the data that's wrong, as in this first case, but that is going to bring into focus the moving average code I wrote as well as a much more complicated set of rules than simple edge-triggering. So what I wanted to do was to make a system a lot like we had with InfoShop in my last job: basic tools all wired together, but not configured until they are put in place in a configuration file.

I like the Java Properties file format for this, but primarily in it's ability to dovetail nicely with the System Properties and overlay multiple files, one on top of the other. The idea is to have the property files specified in the web.xml file as a list where order matters, and the list is loaded and layered on top of the System Properties so that the complete configuration of any component can be parsed from this map.

Then, I'll have as one named property a list of names. These will then be added to the 'baseProperty' name - something used to keep the Property namespace clean, and these will then be parsed and created by the system. It's a pretty easy way to have a config file do all the building and running you need while not having it be as overly complex as say, Spring.

My initial file looks like:

  #
  # List all the named alerts to create
  #
  FC.Alerts=CrazyJump
 
  #
  # CrazyJump - send email on big jump
  #
  FC.Alert.CrazyJump.ClassName=com.chicagotrading.firecache.trigger.BasicAlert
  FC.Alert.CrazyJump.Portfolio=[*]
  FC.Alert.CrazyJump.AlertExpr=abs((pnlSumNet - lastPnlSumNet)*fxToUSD) > 1000000
  FC.Alert.CrazyJump.MailTo=robert.beaty@chicagotrading.com
  FC.Alert.CrazyJump.Message="Portfolio " + portfolio + " jumped"

And from this, it's pretty easy to see where the name is used, and that there are a few mandatory properties for each named alert - the ClassName for instance. But there can be a lot of optional ones as well - dictated by the class that is functioning as the alert.

This is where the BasicAlert comes into play - we needed to build it with all the capabilities a general alert would need. Like the ability to parse expressions... send emails... create messages. All these things will be needed by the subclasses that will be the far more interesting alerts to write with far more complex business logic.

Still, it'll be relatively easy. We have a simple init() method that will be called, and then an onUpdate() for each updated row to check. It's a pretty simple pattern that's been used a lot in Java, which is why I used it. There's almost no Java coder that won't recognize this when he sees it. Consequently, it'll be easy for just about anyone to pick up and make an alert.

It took me the majority of the day to get this to the point that I think it's ready to use. Lots of set-up for the uses I'm trying to see will need to be covered. Thankfully, I've done something like this a couple of times before and have a really good idea about what needs to be done for the vast majority of the cases, and a few little things that will make even the odd-ball case possible.

I'm tired, and that's the way I like it. Leave it all on the track. Hold nothing back.

Miro 2.0.5 is Out

July 14th, 2009

miro.jpg

This morning I saw that Miro 2.0.5 was out with important fixes for YouTube video downloads. I've not used Miro as much as I had hoped, primarily because it doesn't have the content that I'd like to watch - Hulu Desktop does. But in the spirit of supporting a good cause, I'm going to keep looking at Miro as it's all about the Creative Commons, and that's a cause worth supporting.

It's got content, and it looks good. Give it a run.

Continuing to be Amazed by the iPhone 3GS

July 13th, 2009

iPhone3GS.jpg

Well, this weekend I decided to see how my iPhone 3GS handled getting calls. I have to admit that I've yet to actually receive a call on the phone - sticking mostly to text messages, apps, email, and the other smartphone features. I wanted to hear the ring, see how it handles the calls, and then set up and check the usage of my voicemail.

Pretty much, it's Apple all the way - class, ease of use, and exactly what you'd expect. But then there was the Voicemail. I was totally blown away.

Maybe it's because I've been using corporate voicemail too long, or maybe it's the old answering machines - I don't know, but when I realized that the iPhone downloaded the voicemail to the iPhone so that you can easily see who it's from, play (or re-play) it over and over, save it or delete it - all with the ease of text messages or email, I was completely blown away.

This had never even occurred to me as a possibility. I was thinking I was stuck with the horrible "press 7 to listen to the message" for the rest of my existence. No longer. I have seen the absolutely beautiful way that these engineers and designers have looked into the way you'd use a smartphone and made this do just exactly that.

Stunning.

I have to tell people that this alone, is a good enough reason to get an iPhone. The rest is gravy, but the ability to deal effectively with voicemail is something that every technology device connected to the phone system should learn from.

Simply amazing.

I'll never have anything other than an iPhone as long as they make them. It's only been a few weeks and already it's a life-changing device. I didn't think it possible. Stunning.

Hulu Desktop 0.9.6 is Out

July 13th, 2009

HuluDesktop.jpg

I read a tweet about DVRs and Hulu Desktop and decided to see if they had an update, and sure enough they did - 0.9.6 is out and it's got a nice new feature - it allows you to pick what you want the app to do on startup. I don't like it to start playing the last thing I was watching because, frankly, I've already watched it. No, I like it to go to the "favorites" menu so that maybe I'll see something that might catch my eye.

This is still one of the slickest apps that shows TV and movies to the desktop. I don't mind the commercials as it's targeted and I'd have to watch them on TV anyway. It's the cost of watching, I understand.

I also love that the web page for Hulu Desktop shows House, MD - one of my favorite TV shows.

MacVim Snapshot 46 is Out

July 13th, 2009

MacVim.jpg

It's been a while, but this morning I'm happy to say that the crew working on MacVim have been able to put together a new update of the fantastic editor for the Mac - Snapshot 46. There are quite a few changes including NetBeans support and a new logging/debugging facility so that should we have any issues, it's much easier for the guys to debug the issue.

Fantastic editor. If I only had one, it'd have to be Vim.

Updating Google Visualizations Behind a Curtain

July 9th, 2009

SquirrelFish.jpg

Today I was faced with a nasty little problem. I've started to add the annotations to the Google Visualization AnnotatedTimeLine widget and when switching them on and off I ran into a problem with the way I had implemented double-buffering: the unused area where the annotations are in the Flash component has a transparent background, so given that the two widgets have the same size in pixels, the "hidden" graph that doesn't have the annotations active is going to "bleed" through the one that does, with it's transparent background.

Yuck!

How to fix it?

Well, the simplest idea I had was to place a curtain between the two divs in zIndex space. Basically, in the HTML I added another div with nothing on it and set it's zIndex value to midway between the other two: 25.

This wasn't working right, so I changed the CSS on the curtain div to have a background-color of #fff. This looked a lot better, but again, it didn't seem to work all the time.

I pushed and prodded on this... adding a non-breaking space to the div... changing the color to try and see what was happening... then it hit me: Maybe the zIndex was being changed?

I added the one line to reset the zIndex of the curtain to 25 every time I flipped the other two, and Bingo! That was it. It seems that at least in Firefox, the JavaScript/CSS was "moving" the "static" div in zIndex space when I moved the others. Odd, but at least I have it worked out. Sweet.

PETA has Gone Off the Deep End – Fly Rights

July 9th, 2009

GottaWonder.jpg

This has got to be the evidence that PETA has really, collectively, lost their minds. I remember seeing the original video, and thought that the President was pretty neat in getting the fly.

The response is out of control:

"We support compassion even for the most curious, smallest and least sympathetic animals," PETA spokesman Bruce Friedrich said Wednesday. "We believe that people, where they can be compassionate, should be, for all animals."

They're saying he shouldn't have swatted the fly! What's up with these people? Are they totally off the deep end? What little compassion I had for them and what they are trying to accomplish vaporized as soon as I read this official statement. Show more compassion for a fly? As if anyone should? How about rabid dogs? Bats? Venomous snakes?

Amazing.

Safari 4.0.2 is on Software Updates

July 9th, 2009

Safari.jpg

Last evening I was updating Liza's MacBook Air and I noticed that there were a few updates for her machine on Software Updates - included was Safari 4.0.2. This morning I got Safari 4.0.2 for my MacBook Pro. Too bad they require a restart, but so it goes.

The update has stability fixes for the Nitro (SquirrelFish) JavaScript engine as well as the standard round of security and stability fixes that comes with all Safari Updates. Had to get it, but hated the reboot.

Neat Idea for JavaScript-Based Time Localization

July 8th, 2009

WebDevel.jpg

My web app caches the data it sends to the clients so that if another client asks for the same data while nothing's changed, I send them the same data and it's pretty fast. The problem there is that it's timed data, and that means that all the clients around the world have been seeing the data in Chicago-time. Not really what I want for a good user experience in New York and London.

So I needed to see if there was a way I could bring client localized time to the app without losing all the advantages of the cached datasets. If I passed in the location (region/TimeZone) of the client to the servlet, then I'd have a different cached response for each request in a region. Not ideal. Much better to be able to do it client-side. But that begs the question of how to do this?

One way would be to have the server generate GMT times for everything and then each client would have to deal with adjusting the data to the local time, and I almost went with that, but I decided to stick with the Chicago-based time and then add the GMT Offset in the package from the server.

If the client has the GMT Offset of the server, then it can see if it's GMT Offset is different from the server's, and if so, it can calculate the difference and apply it to all the times in the result set. Nice... for the Chicago users (the vast majority) there would be no change as the changes would be skipped, but for New York and London, I could update the data.

OK, how to do this?

Well... the first part is to generate the GMT Offset in the servlet. Since the offsets in Java and JavaScript have an opposite sign, the right thing to do is to standardize on one and then make the other 'fit' it. I chose to stick with the JavaScript version, so my Java servlet code looks like this:

  public UserInfo() {
    // don't forget to call the super's constructor - no matter what
    super();
    // start by getting the GMT offset in mins for this guy
    GregorianCalendar   now = new GregorianCalendar();
    if (now != null) {
      _gmtOffsetMins = (int)(-1)*(now.get(now.ZONE_OFFSET)
                                  + now.get(now.DST_OFFSET))/60000;
    }
  }

where my UserInfo is passed back to the client AJAX with some information about the validated user. Now it's got the GMT Offset in the same sign as JavaScript expects. Good. Now all I needed to do was convert the data that needed converting.

I created a JavaScript function:

  function convertTimesToLocalTime() {
    // get the time right now for the correct offset
    var now = new Date();
    var localOffset = now.getTimezoneOffset();
    if (localOffset != userInfo.gmtOffsetMins) {
      // get the soze of the table as we're going to need it
      var rowCnt = graphData.getNumberOfRows();
      // now let's run through the first column anc update the times
      for (var r = 0; r < rowCnt; ++r) {
        var obj = graphData.getValue(r, 0);
        if (obj instanceof Date) {
          // get the time from the server into UTC
          var utc = obj.getTime() + userInfo.gmtOffsetMins * 60000;
          // make this UTC time into a local time
          graphData.setValue(r, 0, new Date(utc - localOffset * 60000));
        }
      }
    }
  }

With this, I don't do anything unless I need to, and when I have to, I get the time data in the local timezone - regardless of where that is! I'm really happy with this as it adds a little overhead to the client, but it allows my server to not mess with localizations and keeps the cache intact. Nice.