Author Archives: David

About David

A mostly professional code monkey, to contact me translate the following "direct from blog to email" at the website ominian.net. Replace spaces with underscores or dashes, whatever is valid. A script will pick up your email, scrub it against a white list, and if your not a spammer I will get an email.

Software consultancy/freelancing and dating

For almost ALL consultancies, they start at the bottom of the food chain taking small mom & pop shop deals and slowly work their way upward ( or out of the business ) by gaining relevant skills and reputation. Unfortunately this progression somewhat promotes some bad behaviors and a fatalistic outlook for clients.

A small company can’t afford a NASA space program setup ( unit-test coverage w/70% or greater, Jeeves, scrum/agile when it’s just one developer and one client ) so the task becomes “Get it done on time/budget” and hope the coder’s discipline is strong enough not to deliver a ball of mud. Talking about time/money, these client’s might cover 10, 20, or at max 40 man hours and that’s not going to be enough to cover someone’s basic fiscal needs.

It take’s time to develop and manage reputation, so you might do hundreds of these small client’s for years and that will eventually skew how you approach clients and god help you when a relatively meaningful client comes in. The first 40 or even 160 hour work cycle comes to an end and the client is happy, which is sadly great. Great because it means money and stability, sad because you didn’t have time to do unit-tests, the architecture is hardcoded, and now you’re gonna eat all that technical debt you ignored to “get it done”. It become’s a question of whether you can learn fast enough how to function in a meaningful medium to long term relationship.

At this point I’m pointing the finger at the code monkey consultant as the person to blame, but that’s not quite reality either.

On the other side are client’s that don’t want to commit to a long term relationship under any circumstance. Maybe their a media company or a Boiler room consultancy that doesn’t actually have any employees beyond it’s sales & marketing staff. For these two client types, from my experience they either pay terribly or pretty decently. The latter usually stop paying decently the first time they hire a naive smart kid who’s happy with 1/5th pay. Both company types will setup some sort of long term open relationship with smaller firms but it’s understood that if they can find better and or cheaper, you’re gone. Honestly I don’t mind them too much as atleast their honest about their intentions. Still you can’t build a life on these firms as who knows when they’re going to kick you to the curb or never call back?

Also, I’ve run into a lifetime supply of extremely dishonest employer’s but the real dishonesty lies in themselves and their blind faith in success. “I know we contracted you for 6 months, but we ran out of money and can’t pay your last invoice” has happened a few times to me and people I know. For me I usually ask them if I can take something of equivalent value “How much do you think this desk lamp is worth?” and then walk away.

How this all correlates to dating explicitly is that sometimes your first real relationship seems like “It’s the one” until it’s not. Other time’s the one’s you think are right for you turn out not to be “…Google’s awesome but I feel utterly useless and alone…” is something a friend voiced to me on his 1 year anniversary at the super star company. Then there is “Yeah they make me work long/strange hours but the pay is good” sounds like “Yeah, Baby might hurt me occasionally but I know they love me.” And then there’s always the opposite “Man that was such a great company, I don’t know why I didn’t take it serious” is pretty much like Mike + Mechanics “All I need is a Miracle”.

Also, if anyone’s still thinking “I think you’re stretching, strange grammatically challenged wordpress guy” think about job/proposal interviews. You might not flat out lie and say “I invented C when I was 6, that Ritche guy just copied from me.” and how many “Fantastic opportunities” can there be in the entire software industry? I’ve lost count of how many “We have an amazing idea, just sign this NDA” turns out to be a Facebook/Twitter/Whatever is shiny this year clone. We can’t all be super star’s and there is only so many green fields to be developed on before the VC money runs out and it’s murder-mystery software maintenance time. It’s just a fact that both side’s in the average blind date want you to see them at their best and deliberately downplay their downsides, “This sweater hide’s my man boob’s perfectly” or “This dress perfectly cover’s my love handles.”.

For me, I had success in dating by writing my own rules. One of the first few things I said to my now wife was that I had man boob’s so I should be qualified to have some weigh in on female conversational topics ( except I don’t wear a bra, so I still got excluded). Sadly in business, my experiments in being brutally honest/real in project proposals/interviews hasn’t paid out as well… it might also have played against me that the word “eccentric” has been liberally used by others to describe me.

Ubuntu ruby-rvm package is toxic

If you do

  apt-get install ruby-rvm

On any Ubuntu distro, you are going to have a really bad time.

Proper directions are on Stack overflow, where the RVM repository owner mentions that he wishes the Ubuntu ruby-rvm package would be dropped.

SO link http://stackoverflow.com/questions/9056008/installed-ruby-1-9-3-with-rvm-but-command-line-doesnt-show-ruby-v/9056395#9056395

Orthello – Atlas Data doesn’t populate

Slowly went batshit trying to figure this out.

There’s a fairly nice walk through on making 2d games with Unity3D but I ran into a weird problem. While trying to setup a SpriteAtlas, I could set the fields for Texture and Atlast Data, but nothing happened ( it’s supposed to populate the contents of the sprite atlas… but doesn’t).

The images below show the initial import of an Orthello SpriteAtlas, after dragging the Texture and atlas data to their appropriate spots, AND last bit occurred after I typed in an arbitrary number into the “size” field. After that the widgets internal logic kicked into gear and populated the atlas as desired.

Also, if reading just ain’t your thing OR you need a sanity check on getting started with Unity3D, this great video tutorial of making a 2D game was really helpful.

Google Discovery service

I am dumbfounded I haven’t heard of this service before, it’s pretty clever. Anyone familiar with WSDL or Soap is going to instantly grok this.

For example, here’s the Google Analytics API discovery document https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest

With this data set, it’s relatively trivial to auto-generate an interface / command pattern instance to make the user feel like they’re actually using the API directly.  Furthermore the discovery document provides a fairly good reference breakdown of required arguments, argument types, and basic validation type hints to developers.

A trivial example, here’s how to grab the first profile for the currently authenticated user in  analytics:

analytics = client.discovered_api("analytics",'v3')

#Grab the first profile
result = client.execute(analytics.management.accounts.list)
print result.data.items[0]

Until I called discover on analytics, my client had no idea how to deal with the Analytics API, but now it not only knows how to work with the remote service but can provide basic validations, some advanced error handling ( bad/wrong input, connectivity issues) and in an interactive console in Ruby or Python I can explorer the api as needed.

Follow up on Google API with service accounts and ruby

refer to the previous post on this subject

Using analytics.data.qa.get doesn’t work as desired, so instead you need to do something like:

visitCount = client.execute(analytics.to_h["analytics.data.ga.get"], {
                              :ids=>"ga:" + YOUR_PROFILE_NUMBER,
                              "start-date" => "2012-06-12",
                              "end-date" => "2012-07-01",
                              :metrics => "ga:visits"}
                            )

Note the part of using to_h[‘analytics.data.ga.get”] to get the right signature to pass onto the APIClient execute method. That will work and works well. To make it easier to formulate queries against GA, I’d recommend using Google’s query explorer tool here http://ga-dev-tools.appspot.com/explorer/

Service accounts with Ruby and the google api client

  1. Goto https://code.google.com/apis/console
  2. Create a new project
  3. Under services, select Google Analytics
  4. Goto API Access of a new project
  5. generate a new oAuth credential, selecting “service account”.
  6. Download your p12 cert file

 

In Google analytics, use the service account email address and assign it as a new administrator to the desired GA profile.

On ALL servers destined to use the service account to GA, install and syncronized with ntp.  If your even 500ms off, you’re going to have a bad time with “Grant_invalid” messages.

In a testbed project, make 2 files: Gemfile & testbed1.rb ( you’re going to create a lot of these testbed files on your own ).

Gemfile

source "http://rubygems.org"
gem 'google-api-client'
gem 'pry'

testbed1.rb

require 'pry'
require 'rubygems'
require 'google/api_client'

keyFile = "SOME_KEY_GOES_HERE-privatekey.p12"

cID = "YOUR_SOOPA_SECRET_SA"

scope = 'https://www.googleapis.com/auth/analytics.readonly'
email = 'YOUR_EMAIL_GOES_HERE@developer.gserviceaccount.com'


#Normally it would be bad to put the passphrase here, but aftet talking to several dozen devs, everyone's pass phrase is not a secret
key = Google::APIClient::PKCS12.load_key(keyFile, "notasecret")

asserter = Google::APIClient::JWTAsserter.new(
   email,
   scope,
   key)

puts asserter.authorize()

binding.pry

If all goes well, the JWTAsserter instance will get a valid token and no exceptions/errors will be thrown. If you’ve followed all of the steps listed earlier and things are still breaking, troubleshooting paths are: Verify your machine time is correct, verify your service account email address is bound to google analytics, and lastly you might need to wait until Google platform catches up with the changes. For myself, it took 9 hours until my account finally authenticated through. Google has potentially a million or more servers organized into cells, the fact that they seem to cooperate well doesn’t mean they’re perfectly in sync at all times.

Otherwise if all else fails, I recommend stalking this guy Nick https://groups.google.com/d/msg/google-analytics-data-export-api/maa_fyjD2cM/sT8tDDh0wNsJ – It seems like he’s a Google employee on the service account dev/implementation team and generally stuff gets fixed if he says it’s getting fixed.

As I run into any more troubles, I will update and add more notes.

My business DSL connection was out this evening, so I wrote up a quick script to track how long exactly it was out for.

import envoy
import time

roller = 0
Limit = 50
while Limit > 0:
    rs = envoy.run("ping google.com")
    if rs.status_code != 1:
        print "PING %s" % time.ctime()
        Limit -= 1
        time.sleep(10)        
    
    roller += 1
    if roller % 100:
        print "PONG %s" % time.ctime()

Envoy is probably one of my favorite utility libraries after the Http Request library. Github repo is here https://github.com/kennethreitz/envoy/blob/master/README.rst

Ubuntu 11.10 Google native client dependancies

sudo apt-get install ia32-libs
sudo apt-get install gcc-multilib g++-multilib libsdl1.2-dev texinfo libcrypto++-dev libssl-dev lib32ncurses5-dev m4 libelf-dev

This is about 300Mb of stuff, some of it can be culled but I didn’t feel like messing around with that.

Allows for pepper 19 examples to be compiled successfully.

CraftJS; interesting potential

The other month/week I resumed some dabbling/hacking experiments in working with HTML5’s canvas. This go around, I decided to give CraftyJS a try.

The short version of my experiments, CraftyJS has a lot of potential if it can get it’s memory leaks under control, which might be a daunting task.

Here’s the example Pong game implementation that can be found on CraftyJS’s website:


Crafty.init(600,300);
Crafty.background("rgb(127,127,127)");

//Paddles
Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(255,0,0)')
    .attr({ x: 20, y: 100, w: 10, h: 100 })
    .multiway(4, { W: -90, S: 90 });

Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(0,255,0)')
    .attr({ x: 580, y: 100, w: 10, h: 100 })
    .multiway(4, { UP_ARROW: -90, DOWN_ARROW: 90 });

//Ball
Crafty.e("2D, DOM, Color, Collision")
    .color('rgb(0,0,255)')
    .attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })
    .bind('EnterFrame', function () {
        //hit floor or roof
        if (this.y <= 0 || this.y >= 290)
            this.dY *= -1;

        if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }

        this.x += this.dX;
        this.y += this.dY;
    })
    .onHit('Paddle', function () {
    this.dX *= -1;
})

//Score boards
Crafty.e("LeftPoints, DOM, 2D, Text")
    .attr({ x: 20, y: 20, w: 100, h: 20, points: 0 })
    .text("0 Points");
Crafty.e("RightPoints, DOM, 2D, Text")
    .attr({ x: 515, y: 20, w: 100, h: 20, points: 0 })
    .text("0 Points");

Now I will break this down.

Crafty.init(600,300);
Crafty.background("rgb(127,127,127)");

Relatively straight forward; this generates a HTML5 canvas element of 600x300 pixels, sets the color to a neutral color range.

Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(255,0,0)')
    .attr({ x: 20, y: 100, w: 10, h: 100 })
    .multiway(4, { W: -90, S: 90 });

Part of Crafty's cleverness is in it's component based entity system. The first line tells the Crafty library that you're defining a new entity called "Paddle" which is a 2D, DOM behavior like, color'd objected that reacts to multiple user inputs. Break down:

.color(...) defines the paddles color
.attr(...) defines the entities dimensions AND position.
.multiway(...) is a clear API method which states
the entities movement speed, and then which direction a triggered keyboard input will send the entitiy. So in the above case W is north, and S is south.

Skipping the other paddle, we come to the ball in a pong game.

Crafty.e("2D, DOM, Color, Collision")
    .color('rgb(0,0,255)')
    .attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })
    .bind('EnterFrame', function () {
        //hit floor or roof
        if (this.y <= 0 || this.y >= 290)
            this.dY *= -1;

        if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }

        this.x += this.dX;
        this.y += this.dY;
    })
    .onHit('Paddle', function () {
    this.dX *= -1;
})

Something I glossed over, Crafty's e(...) function is actually a Javascript prototype class generator. It's important to note that because of the interplay between .attr() and every other post e(...) method call.

In the above

.attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })

defines additional properties of the entity. x/y & w/h are already used by the 2D and DOM components to determine the entities position on but in the later .bind("EnterFrame") notice that the logic involved is referencing this attributes.

So inside the EnterFrame handler for the Ball are two crucial sections.

if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }

These two if clauses handle bounds check's and then depending on position award the appropriate side a point.

Notice the Crafty("") calls.  In this case Crafty("LeftPoints") calls up the appropriate entity or entities ( in this case there are only 1 per side ) and applies a closure to increment the winning side's this.points and body text.


The other crucial section is the 2 line closure 

.onHit('Paddle', function () {
    this.dX *= -1;
}

A fairly cool concept in Crafty is that collision detection between almost any entity is dealt with by Crafty, so to determine if the Ball hits a paddle, you just have to ask Crafty.

Summary

I was fairly impressed with CraftyJS, it is very much the spiritual relative of jQuery for a dirt simple and comfortably clever API. Unfortunately Crafty can blind side you with it's cleverness if you're not careful. What I mean is that in experimenting with CraftyJS I found it fairly easy to create non-obvious memory leaks and or abuse closures to much.

Still it's a fairly nice library and though this post is slightly long, I am only covering a thin scratch of the depth that is in CraftJS. This could be a fantastic building stage for making a slew of quick and dirty games.