This site is a low down on what's going on in my life, what I'm working on, what I'm thinking about, and how I'm feeling about life in general.

Sunday, 11 May 2008

Friday, 9th May 2008 was my last day as an IBMer. The day was an end to a 4 year career, and 8 years at Matrix Court.

It's very strange leaving behind friends and faces that I've known for such a long time, but I have to move on for the sake of my sanity.

The work had become stale and repetitive, causing more monotony than any sense of satisfaction.

I'm starting to think of this more as a Job Obituary.

NTL / IBM  June 2000 - 2008

I started as a Technical Support rep for ntl:, assisting customers with their dial-up Internet problems. I was able to lend some help to a team developing the next-generation or support tools after just a month in the business, but it would be over a year until I would do so again. In 2001 I was seconded into a development team as a web developer and there I would stay until I left.

September of 2004 was an exciting time. I was married on the 4th and outsourced to IBM on the 6th. It was an uncertain time, mainly fear of the unknown big blue. My fears turned out to be unfounded and I reveled in the openness of information and the training available. It was a relationship that would be tested numerous times. Despite falling in and out of love with developing for IBM on a number of occasions because of the red tape and the poor quality of projects I was being handed, I managed to flourish, getting involved with cross account best practice sharing, career development and assisting in other IBM outsource projects.

Whenever I could get my teeth into something outside of the Virgin Media contract, it was like Christmas. In VM, people are used to having a fast turn-around on projects, to a high degree of quality, for many outside of the contract though, meeting a team that said "yes, we can help with that" was refreshing. I once heard the term "Tiger Team" described as a team that could operate outside of the usual red tape, and just go in analyze and resolve problems with technology. Well, when outside of the VM contract this is pretty much what I was, I was given a problem, and I solved it quickly using web-based applications. The thing you enjoy most about this is almost being adored, you do one thing quickly and well, and people get this contageous enthusiasm for improving the business. The problem is that eventually, you fix the bulk of problems that can be solved in this manner, and before you know it you're being given 3 month, 6 month projects, which really doesn't interest me. To quote another buzz word, I was into "Hit and fade" tactics. I'm sure if I'd stayed longer I'd have been used more and more in this manner. Indeed I had to turn down a trip to Poland because I was leaving.

The problem was that between these quick fixes was the 3-6 month projects I was being handed in VM, that no-one cared if you went past the due-date on. In the end, I think this is the reason I decided to leave, no one cared what I did day to day. I could have done nothing for two weeks and no one would have noticed. I can't work on something that is given to me if they, or my manager do not care if it gets done or not.  

Ironically I move onto what may be the longest single project I've ever worked on, although it will be on an ongoing basis, but this is different. This time I'm able to direct the environment as I see fit, I'm not stuck in someone elses coding conventions, or templates, and ultimately I will be answerable for any delay in progress, and people will be paying attention to my progress in the new job, which I'm not worried about at all.

So thank you IBM, I will miss you, you are a great employer, and I may regret this for a long time, but I've got to be brave and try to improve my situation, rather than coasting along in a very comfortable job.



Tags: IBM NTL: VirginMedia Leaving Job

Sunday, 04 May 2008

I recently faced a conundrum after upgrading the memory on my old iMac G5.

After the upgrade, I was greeted by silence. A quick check in Leopards preferences indicated that there was no audio hardware present, a check in Apple System Profiler confirmed the same.

My first thought was that I'd knocked a card or cable while inserting the DIMM. A search online indicated that this was a real posibility. I was dreading pulling the plastic monster apart.

Before breaking out the toolkit, I thought I'd take a chance on an old friend, Apple + Alt + P + R.

I'd dabbled with macs on / off for the last 10 years or so, and you pick up a few trick, resetting the pram and the vram, rebuilding the desktop etc. Since my g3 iBook I can't recall ever using those tricks.

With nothing to lose I booted up holding down those four keys and on the second boot, chimes! I was a bit surprised it worked, and puzzled as to why it worked but I'm glad it did.



Tags: Apple Mac No Sound Upgrade Memory Failure Silent Macintosh OSX Leopard

Sunday, 04 May 2008

I've had two experiences of fantastic customer service in the last week. A rarity in this day and age, especially with my direct experience working with providers of customer service.

Firstly, we've bought various things for the baby, and there are numerous brands to choose from, but a lot of the practical items we've purchased are from the Tommy Tippee range.

This week, a breast pump we had bought twisted and bubbled in the steraliser. We rang the customer service number and they had a replacement out to us the next day free of charge! We only paid £10 for the pump so it was impressive to see this level of service.

Secondly, the Wednesday after Michael was born, our tumble dryer broke down, which was lucky because when I cracked it open to see what was at fault, it was a total fire hazard. I went straight over to tesco and picked up a new Whirlpool Dryer. It's great, huge capacity, efficient, and slightly smaller than the old one so it fits better behind the door. The only downside I've found with the machine is that I'm constantly cutting myself on the ridge around the door.

I dropped whirlpool an email after a particularly bad cut. I thought no more of it, but 20 minutes later I had a phone call from the local service branch wanting to send someone out to look at the dryer. They're coming out Tuesday so not sure what they'll do, maybe a free upgrade, but probably just file down the plastic slightly.



Tags: Whirlpool Tumble Dryer Machine Service Customer Excellent Breast_Pump Tommy_Tippee Tommy Tippee

Monday, 28 April 2008

I can't believe it's been two weeks since Michael was born. It's flown by, and already he's changed so much.

All babies loose weight after birth. Michael went down from 7.4 to 6.8, but 2 weeks on has regained that weight and filled out a lot, getting a small belly. He's also become more alert, holding our gaze and looking towards us when we talk. He can also roll onto his side already which is impressive. In the last few days he's started to learn about kicking. When he's in the bath we put his feet against the end of the bath and he'll push himself to the other end. After initially hating the bath it's now his favourite thing, and will usually scream when he comes out.

Becoming a parent for the first time has been a strange experience. I day dream about him running around playing with his toys but can't quite believe it's going to happen. It's also hard getting used to the fact that you can't just sit down and play on the computer when you want, and it's hard to program holding a baby. I might have better luck with the harness though.

It's really strange having everything you've ever wanted, and probably why I still can't quite believe it.



Tags: Baby Michael Family Parenting Fatherhood

Friday, 25 April 2008

I recently wrote about how to create a bar graph using the <canvas> tag in html. This was more of a theory article, so as promised, here is the substance.

Screenshot of my bar graph solution

Start by creating your html body as follows:

<body onload="buildChart();">
<div class="chart">
<div id="label_container" style="position: relative; margin: 20px auto; display: inline-block;">
<canvas id="canvas" width="400" height="200"></canvas>
</div>
</div>
<table id="mydata">
<tr> <th>Customers</th><th>Value</th> </tr>
<tr><td>Design</td> <td>2</td> </tr>
<tr><td>Enquiries</td> <td>5</td> </tr>
<tr><td>Home Screen</td> <td>1</td> </tr>
<tr><td> Navigation</td> <td> 4</td> </tr>
<tr><td> Projects</td> <td> 6</td> </tr>
<tr><td> To-do</td> <td> 9</td> </tr>
</table>
</body>

The table contains the data used to build the chart, this can be built dynamically which is really useful for reports etc.

Now lets start on the javascript to build our chart. Firstly, lets start working with our buildChart function.

function buildChart(){

// source data table and canvas tag
var data_table = document.getElementById('mydata');
var canvas = document.getElementById('canvas');
var td_index = 1; // which TD contains the data
var max_value = 0;
var ySegmentCount = 5;

Here, we've defined our variables for the table, the canvas and specified the column that contains the values for our graph. max_value will be set to the largest of the values, and ySegmentCount contains the number of values to be listed horizontally.

I've defined a fixed pallet for this example, however you can easily adapt this to use a dynamic pallet, I just like to control the colours used.

var myPallet = new Array();
myPallet[0] = "#2A416A";
myPallet[1] = "#39588E";
myPallet[2] = "#4572AD";
myPallet[3] = "#688BC3";
myPallet[4] = "#8EA6D2";
myPallet[5] = "#B2C3DF";
myPallet[6] = "#CCD8EA";
myPallet[7] = "#DDDBFB";
myPallet[8] = "#F0F0F0";
myPallet[9] = "#2A416A";
myPallet[10] = "#39588E";
myPallet[11] = "#4572AD";
myPallet[12] = "#688BC3";
myPallet[13] = "#8EA6D2";
myPallet[14] = "#B2C3DF";
myPallet[15] = "#CCD8EA";
myPallet[16] = "#DDDBFB";
myPallet[17] = "#F0F0F0";

Next we retrieve the chart values and calculate some parameters.

var tds, data = [], color, colors = [], value = 0;
var trs = data_table.getElementsByTagName('tr'); // all TRs


for (var i = 0; i < trs.length; i++) {
tds = trs[i].getElementsByTagName('td'); // all TDs

if (tds.length === 0) continue; // no TDs here, move on

// get the value, update total
value = parseFloat(tds[td_index].innerHTML);
if(value > max_value){ max_value = value; }
data[data.length] = value;

// Assign color
color = myPallet[i];
colors[colors.length] = color; // save for later
trs[i].style.backgroundColor = color; // color this TR
}
var itemCount = trs.length-1;

var yIncrement = max_value / ySegmentCount; //determine increment between y axis increments
var barWidth = (canvas.width - (10 * (itemCount * 2))) / itemCount;
var yIncrementPixels = (canvas.height - (2 * (ySegmentCount * 2))) / ySegmentCount;

We now know how wide to make the bars based on the canvas width and number of items, and also the distance between value markers.

We now need to prepare to draw our bar graph, we start by preparing the variables.

var ctx = canvas.getContext('2d');
var canvas_size = [canvas.width, canvas.height];

var backSoFar = 2;
var ySpanPosition = 0;
var yTotal = max_value;

backSoFar contains the vertical (y) start position of each background block. This starts at 2 to create a slight gap at the top. ySpanPosition contains the vertical position of the span containing the axis value.

Lets render the background.

for(i=0; i<ySegmentCount+1; i++){

if(i==ySegmentCount){

yTotal = canvas.height-8;

var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode('0');
oSpan.setAttribute('style','left: -50px; top: '+yTotal+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: 45px; display: block; text-align: right;');
oSpan.appendChild(oLabelText);
labelContainer.insertBefore(oSpan, labelContainer.lastChild);
}else{
backSoFar += 2;
ySpanPosition = backSoFar -8;

ctx.fillStyle = '#E7EEF6';
ctx.fillRect(0,backSoFar,canvas.width,yIncrementPixels);

var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode(yTotal.toFixed(2));
//var oLabelText = document.createTextNode('sdfsg');
oSpan.setAttribute('style','left: -50px; top: '+ySpanPosition+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: 45px; display: block; text-align: right;');
oSpan.appendChild(oLabelText);


labelContainer.insertBefore(oSpan, labelContainer.lastChild);
yTotal += -yIncrement;

backSoFar += yIncrementPixels;
backSoFar += 2;
}
}

Change the value of ctx.fillStyle to set the background colour. Now for our final block for javascript in this function, we render the bars themselves.

var sofar = 0; // keep track of progress
// loop the data[]
for (var piece in data) {

var percentHeight = (data[piece]/max_value)*100;
var pixelHeight = (canvas.height-4)*(percentHeight/100);

var barFloor = canvas.height - pixelHeight; //subtract bar height from canvas height to get ground level;
sofar += 10; //add left margin

//ctx.beginPath();

ctx.fillStyle = colors[piece]; // color
ctx.lineWidth = 4;
ctx.strokeStyle = '#FFF';

ctx.shadowBlur = 3;
ctx.shadowColor = "#999";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.strokeRect(sofar,barFloor,barWidth,pixelHeight);

ctx.shadowBlur = 0;
ctx.shadowColor = "#333";
ctx.fillRect(sofar,barFloor,barWidth,pixelHeight);

//Add labels
var xLabelPosition = sofar;
var yLabelPosition = canvas.height + 10; //add span height

var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode(data[piece]);
//var oLabelText = document.createTextNode('sdfsg');
oSpan.setAttribute('style','left: '+xLabelPosition+'px; top: '+yLabelPosition+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: '+barWidth.toFixed(0)+'px; display: block; text-align: center;');
oSpan.appendChild(oLabelText);

labelContainer.insertBefore(oSpan, labelContainer.lastChild);


sofar += barWidth;
sofar += 10;
}
}

After calculating the positioning of the bar, we create 2 rectangles, the first is white and has drop shadow, the second is the coloured bar. Then we access the DOM to create the span labels and position them appropriately. The 10 value added to the sofar variable spaces the bars 10 pixels.

Finally, some css to make sure everything displays as required.

canvas { background: #fff; border-bottom: 1px solid #ccc; }
.chart {
position: relative;
display: block;
text-align: center;
background: #FFF;
padding-bottom: 10px;
padding-top: 10px;
}
span { font-family: Arial, Helvetica, sans-serif;}

So there we have it, a low bandwidth bar graph that looks great and is totally dynamic. I haven't had time to make the code as efficient as possible but it definitely does the job. I hope you find this useful.



Tags: Javascript Tutorial HTML Canvas Charting Graphing Chart Tabulated Bar Graph Guide Low_Bandwidth Reporting Visualisation Data Table