<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6900110617341786018</id><updated>2024-09-07T08:11:44.201+02:00</updated><category term="Node.js"/><category term="OpenTV"/><category term="Test Driven Development"/><category term="Object Oriented C"/><category term="TDD"/><category term="5Live"/><category term="OOOCode"/><category term="Amazon"/><category term="C Preprocessor"/><category term="EC2"/><category term="Grunt"/><category term="Macros"/><category term="Mocha"/><category term="MongoDB"/><category term="Mongoose"/><category term="Variadic"/><category term="nodeunit"/><category term="watch"/><category term="workaround"/><category term="AWS"/><category term="Agile"/><category term="Amsterdam"/><category term="BrowserStack"/><category term="Constants"/><category term="Cross browser testing"/><category term="DNS"/><category term="DST"/><category term="Delighting customers"/><category term="EBS"/><category term="Eclipse"/><category term="Free Tier"/><category term="Git"/><category term="Google Hangouts"/><category term="James Shore"/><category term="Javascript"/><category term="Jon Nylander"/><category term="Josh Fraser"/><category term="Magic Boundary"/><category term="Magic Frontier"/><category term="Olson database"/><category term="Ports"/><category term="Radical Management"/><category term="Scrum"/><category term="Security Groups"/><category term="Startup Weekend"/><category term="Steve Denning"/><category term="TCP"/><category term="Testacular"/><category term="Ubuntu"/><category term="XFS"/><category term="bitcoin"/><category term="browser"/><category term="currency"/><category term="daylight savings"/><category term="fstab"/><category term="future"/><category term="heroku"/><category term="junit dependencies"/><category term="lean"/><category term="lean startup"/><category term="minimum viable product"/><category term="mining"/><category term="mocking"/><category term="moment.js"/><category term="mysteries"/><category term="node-time"/><category term="nodejitsu"/><category term="osgi console"/><category term="plugins"/><category term="putty"/><category term="puzzles"/><category term="require.cache"/><category term="should.js"/><category term="timezone detection"/><category term="timezone-js"/><category term="tls-tunnel"/><category term="trading"/><category term="zoneinfo"/><title type='text'>Stuff Pete Does</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-5098467240315844117</id><published>2013-10-04T23:45:00.001+02:00</published><updated>2013-10-04T23:45:09.551+02:00</updated><title type='text'>Ubuntu on early 2009 Mac Mini (3,1)</title><content type='html'>Well that was a pain but at least it seems to be working now. I wasted so much time on this that I figured it would be worth while leaving some notes.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s what didn&#39;t work:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Creating bootable USB drives using the following method&amp;nbsp;http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-mac-osx&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The default 64 bit 12.04.3 server image&lt;/li&gt;
&lt;li&gt;The default 64 bit 12.04 desktop image&lt;/li&gt;
&lt;li&gt;The default 64 bit 13.04 desktop image&lt;/li&gt;
&lt;li&gt;All three of these show up as 3 options when booting and fail to start the installer&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Then I discovered that there are mac specific images for 12.10 and 13.04 - I chanced upon these and never once saw them mentioned in any guide that I read elsewhere. Check the releases site, eg.&amp;nbsp;http://releases.ubuntu.com/raring/&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Still I had problems with 13.04 desktop - it installed but would not boot into the desktop unless I started it in recovery mode. I almost got caught up in trying to make this work but then remembered I only wanted a headless server install in the first place&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
So here&#39;s what did work:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;The 64-bit Mac (AMD64) server install image worked fine and now I have what I wanted (almost - I would have preferred the 12.04.3 LTS version but I can live with 13.04)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/5098467240315844117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/10/ubuntu-on-early-2009-mac-mini-31.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/5098467240315844117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/5098467240315844117'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/10/ubuntu-on-early-2009-mac-mini-31.html' title='Ubuntu on early 2009 Mac Mini (3,1)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3276266392921580246</id><published>2013-10-04T22:33:00.000+02:00</published><updated>2013-10-04T23:53:46.133+02:00</updated><title type='text'>BuildItAndTheyWillCo.me part 2</title><content type='html'>Well I don&#39;t think they will. I got this running and along the way I learnt a bit more about AWS, Chef and Knife. But now I kinda lost interest :o and will take my new knowledge on to the next project.&lt;br /&gt;
&lt;br /&gt;
For now there&#39;s a blank word press installation running at test.builditandtheywillco.me but it won&#39;t be there long. I&#39;ll keep hold of the domain name for a while though and add it to the list (along with IKnowTh.is).</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3276266392921580246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/10/builditandtheywillcome-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3276266392921580246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3276266392921580246'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/10/builditandtheywillcome-part-2.html' title='BuildItAndTheyWillCo.me part 2'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-6292718959254761381</id><published>2013-09-21T11:25:00.001+02:00</published><updated>2013-09-21T11:25:35.612+02:00</updated><title type='text'>AWS Revisited - the birth of BuildItAndTheyWillCo.me</title><content type='html'>I&#39;ve been playing with Chef a lot recently, mainly with Vagrant to separate and control development environments, but now I feel the need to get fully into the whole DevOps thing. With that in mind I&#39;m going to see if can&#39;t get something running in a whole continuous deployment kind of way with AWS.&lt;br /&gt;
&lt;br /&gt;
What to build though? To be honest I don&#39;t really care so first I figured, how about a personal web site. Then I realised that I may like to blog about the experience and remembered this blog. Then I had a moment and thought what about a blog site that documents the process of building itself (Wooooah!).&lt;br /&gt;
&lt;br /&gt;
What about a name then? Well, as I&#39;m building something and maybe hope that people will visit it I&#39;ve gone for &#39;BuildItAndTheyWillCo.me&#39; (now duly registered) in honour of the Kevin Costner classic &#39;Field of Dreams&#39;, ghosts are not welcome though ;)</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/6292718959254761381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/09/aws-revisited-birth-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6292718959254761381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6292718959254761381'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/09/aws-revisited-birth-of.html' title='AWS Revisited - the birth of BuildItAndTheyWillCo.me'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-2933617462784533458</id><published>2013-03-24T10:05:00.000+01:00</published><updated>2013-03-24T10:08:54.720+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bitcoin"/><category scheme="http://www.blogger.com/atom/ns#" term="currency"/><category scheme="http://www.blogger.com/atom/ns#" term="future"/><category scheme="http://www.blogger.com/atom/ns#" term="mining"/><category scheme="http://www.blogger.com/atom/ns#" term="trading"/><title type='text'>Becoming fascinated with bitcoin</title><content type='html'>Is this the future of currency?

&lt;a href=&quot;http://www.online-accounting-degrees.net/bitcoin/&quot;&gt;&lt;img src=&quot;http://ig.online-accounting-degrees.net/bitcoin.jpg&quot; alt=&quot;Bitcoin 101: The Digital Currency Revolution&quot; width=&quot;500&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Image source: &lt;a href=&quot;http://www.online-accounting-degrees.net&quot;&gt;www.online-accounting-degrees.net&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/2933617462784533458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/03/becoming-fascinated-with-bitcoin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/2933617462784533458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/2933617462784533458'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2013/03/becoming-fascinated-with-bitcoin.html' title='Becoming fascinated with bitcoin'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3191722083666715414</id><published>2012-10-20T12:21:00.000+02:00</published><updated>2012-10-20T12:21:24.527+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Amazon"/><category scheme="http://www.blogger.com/atom/ns#" term="BrowserStack"/><category scheme="http://www.blogger.com/atom/ns#" term="Cross browser testing"/><category scheme="http://www.blogger.com/atom/ns#" term="DNS"/><category scheme="http://www.blogger.com/atom/ns#" term="EC2"/><category scheme="http://www.blogger.com/atom/ns#" term="heroku"/><category scheme="http://www.blogger.com/atom/ns#" term="lean"/><category scheme="http://www.blogger.com/atom/ns#" term="Mocha"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="nodejitsu"/><category scheme="http://www.blogger.com/atom/ns#" term="TCP"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Test Driven Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Testacular"/><category scheme="http://www.blogger.com/atom/ns#" term="tls-tunnel"/><title type='text'>Gah! TCP doesn&#39;t won&#39;t work the way I want :(</title><content type='html'>Well, I&#39;ve been having more fun messing around with Node.js and allowing myself to be distracted by interesting problems. The latest of which was triggered by my desire to integrate the &lt;a href=&quot;http://www.browserstack.com/&quot;&gt;BrowserStack&lt;/a&gt; beta API for cross browser testing. This is a nice service that will fire up any number of different versions of browsers and point them at a URL that you specify. Integrating this with &lt;a href=&quot;http://vojtajina.github.com/testacular/&quot;&gt;Testacular&lt;/a&gt; and &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; means that I can run all my browser javascript tests in all browser variants and get the results right back in my shell immediately, without having to run a myriad of browser versions locally :) This even includes mobile platforms :D&lt;br /&gt;
&lt;br /&gt;
So what&#39;s the catch?&lt;br /&gt;
&lt;br /&gt;
Well, in order for BrowserStack to connect to my Testacular server it needs to hit a public URL. Unfortunately my development machine is not reachable on a public URL (nor do I want it to be, at least not &lt;u&gt;really&lt;/u&gt; public). The solution suggested by BrowserStack was to use a simple service called &lt;a href=&quot;http://progrium.com/localtunnel/&quot;&gt;LocalTunnel&lt;/a&gt;. This service provides a client with which you can create an SSH tunnel to a local port that you specify. The service then allocates a random subdomain of localtunnel.com from which it will forward HTTP requests to your local port. Very useful and sounds easy, right? Unfortunately when I tried the client it didn&#39;t work and the only clues were leading me into a world of SSH keys, etc.&lt;br /&gt;
&lt;br /&gt;
Hence the distraction. As I probably want to fire up my tunnel and browsers programatically I&#39;m not so fond of relying on command line interfaces and really I want a node module to do it. What&#39;s more if I&#39;m going to dig around in secure connections why don&#39;t I take the opportunity to expand my knowledge in a direction that I want it expanded. So I decided I would implement my own tunnel service and client solution in node and thus the &lt;a href=&quot;https://npmjs.org/package/tls-tunnel&quot;&gt;tls-tunnel&lt;/a&gt; package was born.&lt;br /&gt;
&lt;br /&gt;
Early on I figured I didn&#39;t want to mess about with generating random sub domains and trying to route based on the sub domain on which a connection was made so instead I decided to assign ports on the server to satisfy client connections. This way whenever a new client connects and requests a tunnel the server will allocate a port from a predefined range of available ports and start listening on that.&lt;br /&gt;
&lt;br /&gt;
My plan was to use a free Heroku or Nodejitsu instance to then deploy my tls-tunnel server when I needed it.&lt;br /&gt;
&lt;br /&gt;
This is where I learnt a hard lesson in the problems of bottom up development. Although I am applying TDD principles I did in fact fail to validate one of my initial assumptions - that I could use multiple ports! Both Heroku and Nodejitsu will only expose one port to your application... this could/should have been a red flag. I realised this early on but plowed ahead anyway thinking that at a later date I could apply a small change to my tunnel and instead use the random subdomain solution to differentiate between tunnels.&lt;br /&gt;
&lt;br /&gt;
So I got my tunnel working using TLS (hence the name) with clients and servers authenticating each other with their own self signed SSL certificates. I was pretty proud of myself for implementing something that was in theory protocol agnostic - I had noticed that other similar solutions were limited to HTTP traffic... this &lt;u&gt;should&lt;/u&gt; have been a red flag!&lt;br /&gt;
&lt;br /&gt;
I next turned to the problem of making it all work on one port. Having already learnt quite a bit about the TLS/SSL problem domain I now learned a hard lesson about the TCP domain or more specifically the Node.js net domain.&lt;br /&gt;
&lt;br /&gt;
I had made the assumption that when a raw TCP socket was connected to a server I would be able to read out the domain name that it had used... Wrong!!!&lt;br /&gt;
&lt;br /&gt;
What LocalTunnel is doing is using the HTTP protocol to get the domain name that was used for the connection. GAH!! and what do you know this is the same reason the Heroku and Nodejitsu limit access to a single port. Double GAH!!!&lt;br /&gt;
&lt;br /&gt;
So now I&#39;m left with a choice. My solution can still work but I&#39;m going to have to put it on an Amazon EC2 instance or something (I can get one for free for now). Or I can bite the bullet and implement the same HTTP restriction (boo) and do subdomain based tunnelling.&lt;br /&gt;
&lt;br /&gt;
It&#39;s not such a simple choice though. On the one hand it&#39;s easy to integrate Heroku and Nodejitsu into my development and testing process (and even share that) as opposed to the hoops I will have to jump through to get it up and running on an EC2 instance. But on the other I don&#39;t want to limit my solution to HTTP and I haven&#39;t actually verified yet that I can use random subdomains on either service (once bitten, etc).&lt;br /&gt;
&lt;br /&gt;
Perhaps there is a third way though - maybe if I only support one tunnel at a time I can use a single port...&lt;br /&gt;
&lt;br /&gt;
That said, I&#39;m leaning towards the EC2 solution&amp;nbsp;for flexibility (&quot;lean&quot;-ing might be a bad choice of word&amp;nbsp;here though - if you&#39;ll excuse the pun ;))&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3191722083666715414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/10/gah-tcp-doesnt-wont-work-way-i-want.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3191722083666715414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3191722083666715414'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/10/gah-tcp-doesnt-wont-work-way-i-want.html' title='Gah! TCP doesn&#39;t won&#39;t work the way I want :('/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3659387057697716658</id><published>2012-07-21T12:48:00.000+02:00</published><updated>2012-07-21T12:51:02.300+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="5Live"/><category scheme="http://www.blogger.com/atom/ns#" term="browser"/><category scheme="http://www.blogger.com/atom/ns#" term="daylight savings"/><category scheme="http://www.blogger.com/atom/ns#" term="DST"/><category scheme="http://www.blogger.com/atom/ns#" term="Javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="Jon Nylander"/><category scheme="http://www.blogger.com/atom/ns#" term="Josh Fraser"/><category scheme="http://www.blogger.com/atom/ns#" term="moment.js"/><category scheme="http://www.blogger.com/atom/ns#" term="node-time"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="Olson database"/><category scheme="http://www.blogger.com/atom/ns#" term="timezone detection"/><category scheme="http://www.blogger.com/atom/ns#" term="timezone-js"/><category scheme="http://www.blogger.com/atom/ns#" term="zoneinfo"/><title type='text'>Scheduling for the internet</title><content type='html'>While trying to figure out the best way to synchronise scheduled event start times across different users in different time zones, I managed to work my way around in a bit of a circle yesterday.&lt;br /&gt;
&lt;br /&gt;
I have an app that allows users to schedule events and obviously specify start times. In my initial hacking I was specifying those start times and storing them in the database as strings (not even validated as dates, really just a place holder to mock up the site). So yesterday I thought I would tackle this to make it more functional.&lt;br /&gt;
&lt;br /&gt;
I added a date picker widget and a time picker widget and fixed things so that only dates and times could be specified which I then stored in my database.&lt;br /&gt;
&lt;br /&gt;
But wait, I thought, how do i know what timezone the user intends. After all, when i publish this event to other users I will want to give the start time in their timezone. Hmm... So I started my research on timezones.&lt;br /&gt;
&lt;br /&gt;
I started out trying to put a timezone picker on my event scheduler page which would default to the current timezone of the clients browser. This actually isn&#39;t so simple.&lt;br /&gt;
&lt;br /&gt;
A major complication is that I don&#39;t really want the timezone, I actually want the locale of which the timezone is only a feature. The other feature is daylight savings time (DST). There are only so many time zones (which is quite manageable) but there are lots of variations in the treatment of DST (not so manageable). Unfortunately for me I need to consider DST if I am to know what real time an event organiser is actually aiming for (they will always be working in local time I presume and would not care to specify start times in UTC).&lt;br /&gt;
&lt;br /&gt;
Here are a few of the interesting libraries that I looked at to get get a handle on this.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;On the client to detect and select a timezone&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/&quot; target=&quot;_blank&quot;&gt;Josh Fraser&lt;/a&gt;&amp;nbsp;provided the best hope for something simple with his client timezone and DST detection algorithm in Javascript. But he does mention that instead folks should use...&lt;/li&gt;
&lt;li&gt;Jon Nylander&#39;s &lt;a href=&quot;http://www.pageloom.com/automatic-timezone-detection-with-javascript&quot; target=&quot;_blank&quot;&gt;jsTimezoneDetect&lt;/a&gt;&amp;nbsp;solution. This is apparently much more advanced and works off the complete list of time locales from the Olson zoneinfo database. Unfortunately this would be tricky to integrate in my web page and would provide a huge number of options for users. I&#39;ve seen these before on the internet and they are annoying.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Then on the server to get a nice unix time in my database&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TooTallNate/node-time&quot; target=&quot;_blank&quot;&gt;node-time&lt;/a&gt;&amp;nbsp;looked interesting&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://momentjs.com/&quot;&gt;moment.js&lt;/a&gt;&amp;nbsp;seemed to talk the talk but on further analysis I wasn&#39;t sure if it knew about DST or if I would have to tell it&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mde/timezone-js&quot;&gt;timezone-js&lt;/a&gt;&amp;nbsp;may have been the most promising&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
But then came my small eureka moment... Why am I doing all this work? Well, pretty much because my client side controls give me strings and not date objects. However the browser does know what time locale it&#39;s in and how to present dates. So this is where I returned almost to my starting point.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I ripped out all the timezone selector stuff from my page and instead I used the client side date functions to generate a Date object there and transmit a nice simple unix time back to the server for storage. For those that don&#39;t know, unix times are the number of milliseconds since 00:00:00.000 01/01/1970 (UTC). They don&#39;t care about time locales. So now I do all the locale specific formatting and parsing in the browser. Seemed obvious after I&#39;d done it :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I may add a widget to my pages to let the user know which zone the times are being displayed in but I&#39;m not sure even that is worth the effort. It would only catch a few issues with people working on devices with the wrong timezone set.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3659387057697716658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/scheduling-for-internet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3659387057697716658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3659387057697716658'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/scheduling-for-internet.html' title='Scheduling for the internet'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-1176606589981889823</id><published>2012-07-20T14:56:00.000+02:00</published><updated>2012-07-20T14:56:53.805+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="5Live"/><category scheme="http://www.blogger.com/atom/ns#" term="Grunt"/><category scheme="http://www.blogger.com/atom/ns#" term="James Shore"/><category scheme="http://www.blogger.com/atom/ns#" term="Mocha"/><category scheme="http://www.blogger.com/atom/ns#" term="MongoDB"/><category scheme="http://www.blogger.com/atom/ns#" term="Mongoose"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="nodeunit"/><category scheme="http://www.blogger.com/atom/ns#" term="require.cache"/><category scheme="http://www.blogger.com/atom/ns#" term="should.js"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Test Driven Development"/><category scheme="http://www.blogger.com/atom/ns#" term="watch"/><category scheme="http://www.blogger.com/atom/ns#" term="workaround"/><title type='text'>Grunt watch and the Node.js require cache revisited</title><content type='html'>Still inspired by James Shore&#39;s series &lt;a href=&quot;http://www.letscodejavascript.com/v1/early_access/&quot;&gt;&quot;Let&#39;s Code: Test-Driven Javascript&quot;&lt;/a&gt;,&amp;nbsp; I&#39;ve been continuing with my endeavors to get the Grunt watch stuff working flawlessly(?).&lt;br /&gt;
&lt;br /&gt;
In my &lt;a href=&quot;http://stuffpetedoes.blogspot.nl/2012/07/nodeunit-mongoose-and-grunt-watch.html&quot; target=&quot;_blank&quot;&gt;last post&lt;/a&gt; I mentioned some niggles that were remaining from my previous workaround.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The workaround only addresses the Mongoose issue&lt;/li&gt;
&lt;li&gt;The workaround assumes intimate knowledge of Mongoose&lt;/li&gt;
&lt;li&gt;Grunt watch still explodes silently when unhandled errors are encountered in tests&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;undefined references&lt;/li&gt;
&lt;li&gt;nonexistent requires&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
The good news is that I think I have addressed all of these. In addition to that I&#39;ve figured out some stuff about how to extend grunt and how to manipulate the Node.js require cache.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
First off I thought I&#39;d take a look at Mocha to see if it handled things better. After all Mocha also has a watch function.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Mocha watch does not explode on undefined references (which is nice)&lt;/li&gt;
&lt;li&gt;Mocha watch does still explode on nonexistent requires (actually I didn&#39;t find this out till much later on when integrating with grunt)&lt;/li&gt;
&lt;li&gt;Mocha watch still failed to handle my Mongoose issue&lt;/li&gt;
&lt;li&gt;Unfortunately Mocha watch doesn&#39;t integrate with JSHint and actually I&#39;d quite like to lint my code on file changes too&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
So despite only having a small advantage in not falling over so much I thought Mocha showed more promise than NodeUnit and as James noted it is much more active on GitHub. In fact it&#39;s under the same banner as Express and Jade which are definitely very popular and well maintained frameworks for Node.js.&lt;br /&gt;
&lt;br /&gt;
Next thing was to integrate Mocha with Grunt so that i can use the Grunt watch function to both lint and run tests on file changes.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The nice thing about writing my own task to run Mocha instead of NodeUnit is that it was then quite easy to fix the issue of exploding on nonexistent requires... It just needed a &lt;b&gt;try/catch&lt;/b&gt; around the &lt;b&gt;mocha.run&lt;/b&gt; call. In retrospect I could probably have added this to the existing NodeUnit task but by the time I got to this point, I&#39;d already ported all my tests to Mocha.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
[A short interlude on Mocha and Should...]&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
James noted in his videos that Mocha is targeted as a BDD test framework and as such he is not so keen on it&#39;s verbosity. I can see what he means but, to be honest, I don&#39;t find it much of an issue and in fact quite like it, so for a while at least, I think i&#39;ll stick with it.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I also tried the &lt;b&gt;should.js&lt;/b&gt; assert library that provides an interesting take on asserts by making them a bit more natural language like. Things like:&amp;nbsp;&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;thing.should.have.property(things).with.length(5);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
On first take I thought cool and went full steam ahead in making all my asserts like this. Currently though I&#39;m not sure I like it.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For one, I keep thinking that I should be able to write something in a natural way but find that it&#39;s not really supported - it kinda feels like I&#39;m being teased. This will lessen I guess as I really learn the idioms.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A more annoying problem though is related to the way Javascript handles types and comparisons. I keep finding comparisons that i think should work and don&#39;t and then comparisons that I think shouldn&#39;t work and do! I think this is made worse by hiding the comparisons inside assert functions. As a result I&#39;m starting to come to the opinion that not only is the should framework more trouble than it&#39;s worth but in fact any assert framework that hides comparison logic is not such a good idea to use in tests in Javascript. This includes very standard things like:&amp;nbsp;&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;assert.equal(object1, object2);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I may revert to just a single check function that will better reflect how comparisons would actually be written in production code. Ie:&amp;nbsp;&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;assert(conditionalCodeThatResolvesToTrueOrFalse);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
[...interlude over]&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
So there I have it, I can now run my tests as files change and rely on the watch task to keep going no matter what happens (so far!). Just the mongoose problems to resolve then, and actually I added another.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;If a unit test&amp;nbsp;&lt;b&gt;beforeEach&lt;/b&gt; function falls over then the &lt;b&gt;after&lt;/b&gt;&amp;nbsp;functions are not run&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;This means that as I open a database connection in &lt;b&gt;before&lt;/b&gt; and close it in &lt;b&gt;after&lt;/b&gt;, when I get such an error I then continue to get failures when files change due to not being able to open the database anymore (it&#39;s already open)&lt;/li&gt;
&lt;li&gt;Not as serious as the silent failures as at least the watch process keeps pinging me and I can restart it. But still a little annoying&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
This new issue got me thinking again about the &lt;b&gt;require cache&lt;/b&gt;. My previous investigations here had proven fruitless but then, perhaps&amp;nbsp;I had&amp;nbsp;been led astray by some dubious comments on &lt;a href=&quot;http://stackoverflow.com/questions/6676612/unloading-code-modules&quot; target=&quot;_blank&quot;&gt;StackOverflow&lt;/a&gt;. Beware, this code does not work:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;for (var key in Object.keys(require.cache)) {delete require.cache[key];}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
So now I was thinking about the Mongoose module.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;The problem &lt;b&gt;isn&#39;t&lt;/b&gt; that the changed module is still in cache&lt;/li&gt;
&lt;li&gt;The problem &lt;b&gt;is&lt;/b&gt; that the Mongoose module is still in cache&lt;/li&gt;
&lt;li&gt;In fact the problem is that &lt;b&gt;any&lt;/b&gt; modules are still in cache&lt;/li&gt;
&lt;li&gt;I must clear the cache completely before running my tests!&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Actually I had tried this and it didn&#39;t seem to work&lt;/li&gt;
&lt;li&gt;However I had tried it in my tests themselves, now I could try it in my new grunt task :)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I had already needed to add code that dropped all my own files from cache to make things work. It made sense to drop the rest too when I come to think about it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
So i fixed the code above:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: #eeeeee; color: #444444; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 13px; line-height: 17px; text-align: left;&quot;&gt;for (var key in require.cache) {delete require.cache[key];}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Tidied up my mocha task adding support for options and this is what I have in a new module...&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;script src=&quot;https://gist.github.com/3150484.js?file=mocha.js&quot;&gt;
&lt;/script&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To use this I dropped it in a grunt tasks directory and updated my grunt.js file...&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;script src=&quot;https://gist.github.com/3150484.js?file=grunt.js&quot;&gt;
&lt;/script&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Note that the call to&amp;nbsp;&lt;b&gt;loadTasks&lt;/b&gt; takes the directory name. Also note that I overrode the built in NodeUnit &lt;b&gt;test&lt;/b&gt; task and that the options to pass into mocha are given in the mocha config property.&lt;br /&gt;
&lt;br /&gt;
So that&#39;s it I no longer have to use my Mongoose workaround as the Mongoose module is cleaned up along with everything else before I run the tests :)&lt;br /&gt;
&lt;br /&gt;
I hope this will save me from similar gotchas in other modules too, but I guess I&#39;ll just have to code and find out :D&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/1176606589981889823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/grunt-watch-and-nodejs-require-cache.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1176606589981889823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1176606589981889823'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/grunt-watch-and-nodejs-require-cache.html' title='Grunt watch and the Node.js require cache revisited'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-4494066228318118865</id><published>2012-07-18T14:17:00.000+02:00</published><updated>2012-07-20T15:00:23.629+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Grunt"/><category scheme="http://www.blogger.com/atom/ns#" term="mocking"/><category scheme="http://www.blogger.com/atom/ns#" term="Mongoose"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="nodeunit"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Test Driven Development"/><category scheme="http://www.blogger.com/atom/ns#" term="watch"/><category scheme="http://www.blogger.com/atom/ns#" term="workaround"/><title type='text'>NodeUnit, Mongoose and Grunt watch</title><content type='html'>&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Edit: Although interesting to me as a history to my Node.js testing issues, this article is now pretty much superseded by this &lt;a href=&quot;http://stuffpetedoes.blogspot.nl/2012/07/grunt-watch-and-nodejs-require-cache.html&quot; target=&quot;_blank&quot;&gt;one&lt;/a&gt;&amp;nbsp;which better addresses all of the below problems&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
Now that James Shore&#39;s &lt;a href=&quot;http://www.letscodejavascript.com/&quot; target=&quot;_blank&quot;&gt;&quot;Test Driven Javascript&quot;&lt;/a&gt; series has kicked off I&#39;ve been integrating unit tests into the 5Live hangout project. This has, for the most part, been simpler than I expected. &lt;a href=&quot;https://github.com/caolan/nodeunit/&quot; target=&quot;_blank&quot;&gt;NodeUnit&lt;/a&gt; is pretty easy to use and from one of the comment threads I have been introduced to &lt;a href=&quot;http://gruntjs.com/&quot; target=&quot;_blank&quot;&gt;Grunt&lt;/a&gt; which allows me to tie all my lint tasks and unit tests into a single automated script (James has been doing this himself in Jake but I figured I would give Grunt a try as it does some of the &#39;grunt&#39; work for me :)) .&lt;br /&gt;
&lt;br /&gt;
Like I said, for the most part this has all been going swimmingly. One of the nice features of Grunt that I discovered is the watch task. This allows me to watch a list of files and when they change, automagically kick off my lint tasks and unit tests - very nice :D&lt;br /&gt;
&lt;br /&gt;
There are some problems though. My application uses &lt;a href=&quot;http://mongoosejs.com/&quot; target=&quot;_blank&quot;&gt;Mongoose&lt;/a&gt; to interact with a &lt;a href=&quot;http://www.mongodb.org/&quot; target=&quot;_blank&quot;&gt;MongoDB&lt;/a&gt; database. As such I follow the standard mongoose pattern of using a singleton and defining my model schemas like this...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=greetee.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
As I&#39;m doing TDD I actually start off with something like this in a separate test file...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=greetee.test.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
That&#39;s all hunkydory. I can run the tests and they pass. I can kick off &lt;b&gt;grunt watch&lt;/b&gt;&amp;nbsp;and leave it running while I start editing my files. Let&#39;s see what happens when I change my test, thusly...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=newGreetee.test.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
As expected &lt;b&gt;grunt watch&lt;/b&gt;&amp;nbsp;pings me to let me know that my test has failed :)&lt;br /&gt;
&lt;br /&gt;
So I go back to my model and update the &lt;b&gt;greeting&lt;/b&gt; function...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=newGreetee.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
Gah, &lt;b&gt;grunt watch&lt;/b&gt; pings me again to say that my test still fails. Puzzlement abounds!&lt;br /&gt;
&lt;br /&gt;
If I stop &lt;b&gt;grunt watch&lt;/b&gt; and run the tests manually they pass! So what&#39;s going on?&lt;br /&gt;
&lt;br /&gt;
Well I wasted a lot of time messing around with the &lt;b&gt;require.cache&lt;/b&gt; object, as I figured it was something to do with Node.js module caching, but that wasn&#39;t it at all. Either NodeUnit or Grunt is smart enough to remove the changed files from the module cache (I think it must be Grunt that does this but I didn&#39;t check).&lt;br /&gt;
&lt;br /&gt;
Eventually I realised that it was the mongoose singleton that was causing the problem. After all this only happened with my mongoose model tests. As the mongoose singleton persists between test runs it doesn&#39;t matter that I change the methods on my models, the old versions also persist.&lt;br /&gt;
&lt;br /&gt;
Again I tried a number of workarounds but so far the best seems to be the following.&lt;br /&gt;
&lt;br /&gt;
First I created a wrapper for the mongoose singleton which allows me to reset the schemas...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=mongooseTestWrapper.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
Next I integrated this wrapper into my tests (only the tests, i still use the the mongoose singleton directly in the model implementations)...&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/3135534.js?file=fixedGreetee.test.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
So why do I prefer this solution and what else did I try?&lt;br /&gt;
&lt;br /&gt;
Well I also had another workaround which fixed the problems with method updates.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Instead of using Schema.methods to assign methods I used Model.prototype&lt;/li&gt;
&lt;li&gt;Instead of using Schema.statics to assign static methods I just assigned them to the Model directly&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Why didn&#39;t I like this?&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;This solution meant a little rejigging of the code to what seemed like a non standard pattern in the actual implementations&lt;/li&gt;
&lt;li&gt;This did &lt;b&gt;not&lt;/b&gt; fix a similar problem with updating the actual Schema - ie. adding or removing fields&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
I still don&#39;t much like my eventual workaround as...&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;it depends on knowledge of the the internals of Mongoose (which might change)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
But at least it&#39;s contained in my tests and seems to work for all changes in the model.&lt;br /&gt;
&lt;br /&gt;
However, even with this workaround in place I&#39;m still &amp;nbsp;not fully happy with the way &lt;b&gt;grunt watch&lt;/b&gt; works.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Annoyingly, it exits on a number of test failures particularly when things are not yet defined. This happens a lot when doing TDD, it&#39;s how we write failing tests.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;When it does exit it doesn&#39;t actually ping me. As such I have to keep looking to see if it stopped (If i have to do this all the time, it occurs to me that I may as well not use it and instead run my tests manually)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;I&#39;m now just waiting for the next gotcha as I only worked around a problem with Mongoose.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;It seems to me quite likely that there will be other libraries that follow similar internal patterns and they are likely to trip me up in the same way&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
I have a solution to suggest though...&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Spawn a new Node.js process at least for every &lt;b&gt;grunt watch&lt;/b&gt; event if not for every NodeUnit test&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Wouldn&#39;t this fix the problem once and for all?&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/4494066228318118865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/nodeunit-mongoose-and-grunt-watch.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4494066228318118865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4494066228318118865'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/nodeunit-mongoose-and-grunt-watch.html' title='NodeUnit, Mongoose and Grunt watch'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3849439446784853276</id><published>2012-07-12T19:55:00.003+02:00</published><updated>2012-07-13T11:44:57.531+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Amazon"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="EBS"/><category scheme="http://www.blogger.com/atom/ns#" term="EC2"/><category scheme="http://www.blogger.com/atom/ns#" term="Free Tier"/><category scheme="http://www.blogger.com/atom/ns#" term="fstab"/><category scheme="http://www.blogger.com/atom/ns#" term="Git"/><category scheme="http://www.blogger.com/atom/ns#" term="MongoDB"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="Ports"/><category scheme="http://www.blogger.com/atom/ns#" term="putty"/><category scheme="http://www.blogger.com/atom/ns#" term="Security Groups"/><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><category scheme="http://www.blogger.com/atom/ns#" term="XFS"/><title type='text'>Amazon EC2 learnings</title><content type='html'>Yesterday I discovered that Amazon AWS offer a &lt;a href=&quot;https://aws.amazon.com/free/&quot; target=&quot;_blank&quot;&gt;free tier&lt;/a&gt; which basically means I can have a free server (possibly more than one) in their cloud for a year!&lt;br /&gt;
&lt;br /&gt;
Awesome, I&#39;ll have some of that :)&lt;br /&gt;
&lt;br /&gt;
I decided to see if could get our 5Live hangout project up and running there. Figured it would be useful as our free heroku plan limits us to a 16MB database!!!! On AWS I can have up to 30GB of storage for free :)&lt;br /&gt;
&lt;br /&gt;
Of course I&#39;ll have to be my own sys admin to get it though. So that&#39;s where the adventure begins. This is what I needed to setup...&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;A server&lt;/li&gt;
&lt;li&gt;Some storage&lt;/li&gt;
&lt;li&gt;Install Node.js&lt;/li&gt;
&lt;li&gt;Install MongoDB&lt;/li&gt;
&lt;li&gt;Install Git&lt;/li&gt;
&lt;li&gt;Open ports to allow access from the interwebs&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
In figuring this stuff out I probably created and terminated about 20 EC2 instances. There&#39;s the first 2 things I learned...&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Amazon refers to it&#39;s virtual machines as EC2 instances
&lt;/li&gt;
&lt;li&gt;Amazon calls deleting an instance &quot;terminating it&quot;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;When you terminate an instance it does not go away immediately (takes about 20 minutes) but it is not recoverable&lt;/li&gt;
&lt;li&gt;There is an option for termination protection which I haven&#39;t tried but might be a good idea :)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
Only a limited number of the virtual machine types are covered by the free tier but that&#39;s ok I only actually tried 2 of them. Didn&#39;t think I&#39;d be interested in running my stuff on windows so I only tried the Amazon Linux and Ubuntu 12.04 images. Both of which are free in the micro configuration (1 core, 613MB RAM). After switching between the 2 a few times I settled on Ubuntu mainly because it is more familiar to me. However my research suggests that the Amazon Linux images might be better optimized for EC2.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now for the real purpose of this blog post, which is mainly for my own notes, these are the steps to setting up the above list of requirements.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;





Create an Amazon AWS account&lt;/h3&gt;
&lt;div&gt;
First we need an AWS account&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;From&amp;nbsp;
&lt;a href=&quot;https://aws.amazon.com/free/&quot;&gt;https://aws.amazon.com/free/&lt;/a&gt;&amp;nbsp;sign up for a new account if you don&#39;t have one and verify with the fancy phone call verification&lt;/li&gt;
&lt;li&gt;Wait for email confirmation of the new account&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;





Create an EC2 instance&lt;/h3&gt;
&lt;div&gt;
We need a virtual machine&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsnUJFqriQvi3WVX_brAKM3KhEzpEbXDIzeivS4SG_7HLfiW2J6CrhhPeuvWYT12k9OP1Gm5B0hRFIS1RXfQtqZbfrOhUvTUeevEjP62CUqL514aVXQoBPYxqXUclm9z5afAnD5qktwZb/s1600/InstanceType.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsnUJFqriQvi3WVX_brAKM3KhEzpEbXDIzeivS4SG_7HLfiW2J6CrhhPeuvWYT12k9OP1Gm5B0hRFIS1RXfQtqZbfrOhUvTUeevEjP62CUqL514aVXQoBPYxqXUclm9z5afAnD5qktwZb/s320/InstanceType.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Choose the free tier eligible machine type&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM40Wsxkat80a6fMVcygP2FrAaF0o80i95rNmc_RkM1W8El5-PIWym5KJHnicFoLpGGOl_nVHU4JY6CemwdDXiPJ4DBYxb8-GDP8pxpQqEClEDje77PPjdZr6LP0EZq0tKDYeHQ7OypwQr/s1600/InstanceOptions.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM40Wsxkat80a6fMVcygP2FrAaF0o80i95rNmc_RkM1W8El5-PIWym5KJHnicFoLpGGOl_nVHU4JY6CemwdDXiPJ4DBYxb8-GDP8pxpQqEClEDje77PPjdZr6LP0EZq0tKDYeHQ7OypwQr/s320/InstanceOptions.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Keep the default machine options&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6-PUyaiWGjC4gplVg1HUlMc5U05gPT2CfUfzLxn4ya36RdCCEc65mhh4Zzjfjba6vDkEvYhLeLjANi8LSg_as1D_r0aJppYK652agQlXwWioqANmEooVYYZ9b6gBvQACdVcfJrN8_X5q/s1600/SecurityGroups.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6-PUyaiWGjC4gplVg1HUlMc5U05gPT2CfUfzLxn4ya36RdCCEc65mhh4Zzjfjba6vDkEvYhLeLjANi8LSg_as1D_r0aJppYK652agQlXwWioqANmEooVYYZ9b6gBvQACdVcfJrN8_X5q/s320/SecurityGroups.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Create a new security group&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ol&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsnUJFqriQvi3WVX_brAKM3KhEzpEbXDIzeivS4SG_7HLfiW2J6CrhhPeuvWYT12k9OP1Gm5B0hRFIS1RXfQtqZbfrOhUvTUeevEjP62CUqL514aVXQoBPYxqXUclm9z5afAnD5qktwZb/s1600/InstanceType.PNG&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;
&lt;li&gt;Head over to&amp;nbsp;&lt;a href=&quot;http://aws.amazon.com/console/&quot;&gt;http://aws.amazon.com/console/&lt;/a&gt;&amp;nbsp;and sign in with your new account&lt;/li&gt;
&lt;li&gt;Select the &lt;b&gt;EC2 &lt;/b&gt;link&lt;/li&gt;
&lt;li&gt;Select the &lt;b&gt;Instances/Instances&amp;nbsp;&lt;/b&gt;link on the left hand side&lt;/li&gt;
&lt;li&gt;Click the &lt;b&gt;Launch Instance&lt;/b&gt; button&lt;/li&gt;
&lt;li&gt;Choose the &lt;b&gt;Classic Wizard&lt;/b&gt; option and click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Choose&amp;nbsp;&lt;b&gt;Ubuntu Server 12.04 LTS&amp;nbsp;64bit&lt;/b&gt; and click &lt;b&gt;Select&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Keep the default options for the machine type as pictured above and click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Keep the default options for for the machine features as pictured above and click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Enter a name for the instance (this is only used for display in the AWS console and is not the machine name) and click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Next you will have to create a key pair - this is used instead of passwords to log on to the virtual machine using SSH (If this is not the first instance on the account then you can reuse an existing key pair). Enter a name for the key pair and click&amp;nbsp;&lt;b&gt;Create &amp;amp; Download your Key Pair&lt;/b&gt;&amp;nbsp;- keep this somewhere safe but accessible. Then click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Create a new security group with at least port 22 open so that you can SSH to the instance as pictured above. I have decided that it is best to create a new security group for each EC2 instance as it is not possible to change to a different security group after the instance has been created. However it is possible to change the rules in a security group, so if you want different instances to have different rules then you need to create different security groups for each instance. Then click &lt;b&gt;Continue&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;You will then be presented with a page to review so just click &lt;b&gt;Launch&lt;/b&gt;&amp;nbsp;and on the next dialog click &lt;b&gt;Close&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;





Create an EBS volume&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
We need an Elastic Block Store volume so we can separate our MongoDB data from the OS volume&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Select the &lt;b&gt;Elastic Block Store/Volumes&lt;/b&gt;&amp;nbsp;link on the left hand side. Notice that there is already an 8GB volume for the EC2 instance OS. Make a note of the zone for this existing volume (eg. us-east-1d), we will want to create our new volume in the same zone so the EC2 instance can be attached to it&lt;/li&gt;
&lt;li&gt;Click &lt;b&gt;Create Volume&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Select the size of the volume (eg. 10GB) and the same zone as noted in the last step. Don&#39;t select a snapshot. Click &lt;b&gt;Yes, Create&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Right click the newly created volume and select &lt;b&gt;Attach Volume&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Select the newly created Ubuntu instance and leave the &lt;b&gt;Device&lt;/b&gt;&amp;nbsp;field to the default. Click &lt;b&gt;Yes, Attach&lt;/b&gt;. This will actually attach the volume to &lt;b&gt;/dev/xvdf&lt;/b&gt; and not &lt;b&gt;/dev/sdf&lt;/b&gt; on this version of Ubuntu, as noted on the dialog&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;





Start the instance and log on using SSH&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
We&#39;re going to need our key pair file in the next step. On OSX and linux it can be supplied to the ssh command using the -i option but on windows I use Putty. Putty does not accept *.pem files as generated by amazon so it&#39;s necessary to convert it to a *.ppk file using PuttyGen. Anyway follow these steps to logon...&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;In the AWS console go back to &lt;b&gt;Instances/Instances&lt;/b&gt; on the left hand side&lt;/li&gt;
&lt;li&gt;Select the instance and on the &lt;b&gt;Description&lt;/b&gt; tab scroll down until you find the&amp;nbsp;&lt;b&gt;Public DNS&lt;/b&gt; entry. This is the public host name of your server. As an aside it also contains the static IP address in case you want to know what that is - eg.&amp;nbsp;ec2-&lt;b&gt;&lt;hyphenated address=&quot;&quot; ip=&quot;&quot;&gt;&lt;/hyphenated&gt;&lt;/b&gt;.compute-1.amazonaws.com&lt;/li&gt;
&lt;li&gt;Launch Putty and paste the &lt;b&gt;Public DNS&lt;/b&gt; host name into the &lt;b&gt;host name&lt;/b&gt; field&lt;/li&gt;
&lt;li&gt;Prepend the host name with&lt;b&gt; ubuntu@&lt;/b&gt; so that you don&#39;t need to specify the user name when connecting (the default user is called ubuntu)&lt;/li&gt;
&lt;li&gt;On the left hand side select &lt;b&gt;Connection/SSH/Auth&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;b&gt;Private key file for authentication&lt;/b&gt; browse for the *.ppk file generated by PuttyGen from the *.pem file created and downloaded from Amazon&lt;/li&gt;
&lt;li&gt;Go back to the &lt;b&gt;Session &lt;/b&gt;section at the top on the left hand side and save the session with a sensible name&lt;/li&gt;
&lt;li&gt;Click &lt;b&gt;Open &lt;/b&gt;and you should just be logged in as the ubuntu user (after accepting the public key)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;





Format the EBS volume and mount it permanently&lt;/h3&gt;
&lt;div&gt;
We want a nice efficient file system and it seems that it&#39;s de rigueur to use XFS. XFS is supported by the Ubuntu 12.04 kernel but the tools to format volumes are not there by default. Anyway here are the steps to follow at the command line...&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;sudo apt-get install xfsprogs&lt;/li&gt;
&lt;li&gt;sudo mkfs -t xfs /dev/xvdf&lt;/li&gt;
&lt;li&gt;sudo mkdir /mnt/data&lt;/li&gt;
&lt;li&gt;sudo nano /etc/fstab&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
The last step will start nano so that we can edit the /etc/fstab file to ensure that our volume is mounted whenever the machine reboots. Add the following line...&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;/dev/xvdf /mnt/data xfs noatime,noexec,nodiratime 0 0&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Write out the file with ctrl-o and exit with ctrl-x.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now we need to mount the data volume. At the command line...&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;sudo mount -a&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3&gt;





Install the latest stable Node.js&lt;/h3&gt;
&lt;div&gt;
At the time of writing the default Node.js package available in Ubuntu is 0.6.12 and the latest stable is 0.8.2. In order to get the latest stable release do the following at the command line...&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;sudo apt-get install python-software-properties&lt;/li&gt;
&lt;li&gt;sudo apt-add-repository ppa:chris-lea/node.js&lt;/li&gt;
&lt;li&gt;sudo apt-get update&lt;/li&gt;
&lt;li&gt;sudo apt-get install nodejs npm&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3&gt;





Install and start the latest stable MongoDB&lt;/h3&gt;
&lt;div&gt;
At the time of writing the latest MongoDB was 2.0.6 and that is what we download in the following steps. Check with&amp;nbsp;&lt;a href=&quot;http://www.mongodb.org/downloads&quot;&gt;http://www.mongodb.org/downloads&lt;/a&gt;&amp;nbsp;to see if there is a newer version. At the command line...&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;cd ~&lt;/li&gt;
&lt;li&gt;curl -O http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2.0.6.tgz&lt;/li&gt;
&lt;li&gt;tar -xzf mongodb-linux-x86_64-2.0.6.tgz&lt;/li&gt;
&lt;li&gt;cd mongodb-linux-x86_64-2.0.6/bin&lt;/li&gt;
&lt;li&gt;sudo mkdir /mnt/data/db&lt;/li&gt;
&lt;li&gt;sudo chown ubuntu /mnt/data/db&lt;/li&gt;
&lt;li&gt;./mongod --fork --logpath ~/mongod.log --dbpath /mnt/data/db/&lt;/li&gt;
&lt;li&gt;cd ~&lt;/li&gt;
&lt;li&gt;tail -f mongod.log&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
This will start the MongoDB daemon in the background and output the logging to ~/mongod.log. The last command allows you to check that the daemon starts up ok. Once it has completed the startup sequence then it is safe to ctrl-c out of the tail and mongod will continue running. To stop mongod, the safest way is from the mongo client. At the command line...&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;cd ~/mongodb-linux-x86_64-2.0.6/bin
&lt;/li&gt;
&lt;li&gt;./mongo&lt;/li&gt;
&lt;li&gt;use admin&lt;/li&gt;
&lt;li&gt;db.shutdownServer()&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
The last command shutdown the server and prints out lots of stuff that looks like errors but it should be fine and it should be possible to start the server again as before.&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;





Install Git&lt;/h3&gt;
&lt;div&gt;
I use GitHub and all my code is up there so I need git to put it on my new server. At the command line...&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;sudo apt-get install git&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;





Opening more ports&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
While developing Node.js applications I usually use the default Express port of 3000. You will remember that when we created the server instance we only opened port 22 in the security group. In order to hit the server on port 3000 we have to add that to our security group too...&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;In the AWS console select &lt;b&gt;Network &amp;amp; Security/Security Groups&lt;/b&gt; on the left hand side&lt;/li&gt;
&lt;li&gt;Select the the security group created specifically for the server instance&lt;/li&gt;
&lt;li&gt;Select the &lt;b&gt;Inbound&lt;/b&gt; tab&lt;/li&gt;
&lt;li&gt;For &lt;b&gt;Create a new rule&lt;/b&gt; select &lt;b&gt;Custom TCP rule&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;For &lt;b&gt;Port range&lt;/b&gt; enter &lt;b&gt;3000&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;For &lt;b&gt;source &lt;/b&gt;enter&amp;nbsp;&lt;b&gt;0.0.0.0/0&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Click &lt;b&gt;Add Rule&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Click &lt;b&gt;Apply Rule Changes&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
It should now be possible to connect to services running on port 3000 from the internet. Remember that the host name is the &lt;b&gt;Public DNS&lt;/b&gt; entry under the EC2 instance description.&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3849439446784853276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/amazon-ec2-learnings.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3849439446784853276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3849439446784853276'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/amazon-ec2-learnings.html' title='Amazon EC2 learnings'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsnUJFqriQvi3WVX_brAKM3KhEzpEbXDIzeivS4SG_7HLfiW2J6CrhhPeuvWYT12k9OP1Gm5B0hRFIS1RXfQtqZbfrOhUvTUeevEjP62CUqL514aVXQoBPYxqXUclm9z5afAnD5qktwZb/s72-c/InstanceType.PNG" height="72" width="72"/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-7590963396319431349</id><published>2012-07-09T16:10:00.000+02:00</published><updated>2012-07-09T16:23:35.434+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="5Live"/><category scheme="http://www.blogger.com/atom/ns#" term="Amsterdam"/><category scheme="http://www.blogger.com/atom/ns#" term="Google Hangouts"/><category scheme="http://www.blogger.com/atom/ns#" term="lean startup"/><category scheme="http://www.blogger.com/atom/ns#" term="minimum viable product"/><category scheme="http://www.blogger.com/atom/ns#" term="Startup Weekend"/><title type='text'>Startup Weekend Amsterdam - The 5Live Crew</title><content type='html'>Had a fantastic time at &lt;a href=&quot;http://amsterdam.startupweekend.org/&quot;&gt;Startup Weekend Amsterdam&lt;/a&gt; this weekend. Big up to the organisers :)&lt;br /&gt;
&lt;br /&gt;
It was hard work and I think it will take a while for my girlfriend to forgive me (I found out about it and signed up Thursday with much too little discussion) but I&#39;m so glad I did it.&lt;br /&gt;
&lt;br /&gt;
It kicked of at 6pm Friday with 66 pitches! Some good, some bad, some completely indecipherable but all of them given and received in great spirit, in 60 seconds or under (with change overs I guess it would have been at least 2 hours of pitches, phew).&lt;br /&gt;
&lt;br /&gt;
There was a shameless pitch to clone &lt;a href=&quot;http://www.kickstarter.com/&quot;&gt;Kickstarter&lt;/a&gt; in Europe (did you know Europeans couldn&#39;t raise funds on &lt;a href=&quot;http://www.kickstarter.com/&quot;&gt;Kickstarter&lt;/a&gt;?)... This actually got one of my votes.&lt;br /&gt;
&lt;br /&gt;
There were a lot of pitches to provide match up services for sports enthusiasts, I counted at least 4. These were interesting to me as I know a French guy (hey, Alex, if you&#39;re reading!) who&#39;s had some success with this in Canada for ice hockey. Check out&amp;nbsp;&lt;a href=&quot;http://hockey-community.com/&quot;&gt;Hockey Community&lt;/a&gt;! Like I say interesting but i din&#39;t vote for any of them as I didn&#39;t want to encourage competition for my friend (who I think should branch out to other sports ;))&lt;br /&gt;
&lt;br /&gt;
A cool sounding app called &lt;a href=&quot;http://ohheyworld.com/&quot;&gt;OhHeyWorld&lt;/a&gt; got my second vote. With one click it lets you notify friends and family when you arrive at a destination by checking in by email, facebook, twitter, etc all at once. I really liked this but it didn&#39;t get so many other votes so happily the guy pitching it ended up on our team :)&lt;br /&gt;
&lt;br /&gt;
My final vote though went to a Googler who wanted to build an app on top of Google Hangouts to match coaches, music teachers, etc to people online for live lessons via video. 2 things peaked my interest. I&#39;ve had this conversation before, particularly with musicians. And second it would be nice to learn something about integrating with Google Hangouts.&lt;br /&gt;
&lt;br /&gt;
I didn&#39;t pitch any of my own ideas, although I kinda wish I had. Next time I will... and there will be a next time :)&lt;br /&gt;
&lt;br /&gt;
So with all voting completed the pitches were narrowed down to 20. By which time the Google Hangout idea had merged with another to provide business mentoring over video conferencing, inspired by &lt;a href=&quot;http://www.quora.com/&quot;&gt;Quora&lt;/a&gt;&amp;nbsp;(of which I&#39;m largely unaware, but have just signed up). This is what I ended up working on with 7 other cool guys. We were 5 business guys, 2 developers and 1 designer (I think). Heavy on the business side and it showed after the first day. I&#39;m not sure how many visions there were or how many times we pivoted (being 1 of the 2 techies I was pretty much head down coding the whole time - hoping that it was in the right direction) but at the end of the night on Saturday the cracks were starting to show. It was time for rest.&lt;br /&gt;
&lt;br /&gt;
The next morning, although we were down one business guy who I think was unimpressed by the lack of focus and constant direction changing, there was definitely more commitment to get things done and to try and ship, after all we only had till 4pm.&lt;br /&gt;
&lt;br /&gt;
We seemed to have a single vision now and we set about building it up and applying copy, etc. We needed a presentation and we needed some kind of validation. To be honest we already had some validation. All the pivoting the day before had come from surveying conference participants and collecting feedback. Ok, we didn&#39;t get out of the building physically but we did sell the expertise of one of our team members something like 7 times for $5 (Now he has to do some video conferences with the people who stumped up the cash). This wasn&#39;t even with conference folks, these were real people on the interwebs. We sold him through &lt;a href=&quot;http://fiverr.com/&quot;&gt;fiverr&lt;/a&gt;&amp;nbsp;at an admittedly knock down price for his real estate know how and you may say that we only validated that people will buy gold if we sell for the price of coal. I disagree though, we validated that people are willing to pay for live interactive video sessions in which they can learn something... and they actually paid, not just promise to pay or expressed an interest.&lt;br /&gt;
&lt;br /&gt;
This was our eventual proposition (I almost typed final but there may be more pivots to come) and 5Live was born. We will provide a market place to match up those with skills/knowledge to those who want to have those skills/knowledge. Sessions can be scheduled by the skilled for free and spots can be reserved by the young padowans for 5 euros/dollars or less. Then at the designated time each will click on some button and enter into a live interactive video conference through which knowledge will be imparted. The subsequent revenues will then be distributed back to the skilled.&lt;br /&gt;
&lt;br /&gt;
I see it as a place where everyone is equal and sharing their wisdom with each other. Perhaps in the evening instead of watching TV. I see it as a natural progression from broadcast TV through social video like YouTube to the next wave of social knowledge sharing where you can ask your questions live. It&#39;s Etsy meets YouTube meets fiverr meets Quora (if I understand Quora correctly). This vision may not be the same as the other founders and may change once it&#39;s tested (will change!) but right now it looks like it has legs.&lt;br /&gt;
&lt;br /&gt;
So at the end of the weekend what did we have?&lt;br /&gt;
&lt;br /&gt;
Third place!! Yay :)&lt;br /&gt;
&lt;br /&gt;
We were pushed out by a very worthy non-profit, charity/donation app called Easygiving who took first place for allowing people to easily manage and adjust monthly charity plans and donation distribution. And a service for helping you transfer your apps between mobile phone platforms when you switch to Android and can&#39;t find that app you loved so much on your iPhone (or vice versa) called Aloha. Kudos to them :)&lt;br /&gt;
&lt;br /&gt;
But we still believe in our thing! And to prove it here are the slides, a video and a link so you can see more (if the link is dead then it probably means we changed the name and hit the big time - you should have been here last week ;))&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/open?id=0B980GRf5rpazN3I4bWF5WEFLNmM&quot;&gt;Slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fivelive.herokuapp.com/&quot; target=&quot;_blank&quot;&gt;5Live site&lt;/a&gt;&amp;nbsp;(minimum viable product?)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/UJg3Ev2uci8?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/7590963396319431349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/startup-weekend-amsterdam-5live-crew.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7590963396319431349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7590963396319431349'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/07/startup-weekend-amsterdam-5live-crew.html' title='Startup Weekend Amsterdam - The 5Live Crew'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-4209522200788719570</id><published>2012-06-30T12:40:00.002+02:00</published><updated>2012-06-30T12:40:40.351+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Delighting customers"/><category scheme="http://www.blogger.com/atom/ns#" term="Magic Boundary"/><category scheme="http://www.blogger.com/atom/ns#" term="Magic Frontier"/><category scheme="http://www.blogger.com/atom/ns#" term="mysteries"/><category scheme="http://www.blogger.com/atom/ns#" term="puzzles"/><category scheme="http://www.blogger.com/atom/ns#" term="Radical Management"/><category scheme="http://www.blogger.com/atom/ns#" term="Scrum"/><category scheme="http://www.blogger.com/atom/ns#" term="Steve Denning"/><title type='text'>On Puzzles and Mysteries</title><content type='html'>&lt;br /&gt;
While reading Steve Denning&#39;s &amp;nbsp;&lt;a href=&quot;http://www.amazon.com/Leaders-Guide-Radical-Management-ebook/dp/B0043M4ZPW/ref=tmm_kin_title_0/186-6454583-5068461?ie=UTF8&amp;amp;m=A1HC3MLVT7QPHY&quot;&gt;&quot;The Leader&#39;s Guide to Radical Management&quot;&lt;/a&gt;&amp;nbsp;this morning, I was introduced to an interesting distinction between puzzles and mysteries. I&#39;m not sure this would be a dictionary type of distinction but certainly a useful one. Steve asserts that a puzzle is a problem for which there is a known (or at least knowable) solution. Even though that solution may be challenging to apply it is at least plannable. Traditional management and waterfall style methods are a good fit for puzzles, not surprising as that is exactly the kind of problem that they evolved to solve.&lt;br /&gt;
&lt;br /&gt;
Mysteries, on the other hand, are problems that are new. That no one has solved before. They are not really knowable (at least in advance) as they are unique. The solution is going to be hard to find and will have to be uncovered a piece at a time with each successive discovery leading the investigation like clues in a good mystery novel :)&lt;br /&gt;
&lt;br /&gt;
This idea seems to be basically the same as the difference between complicated and complex in complexity theory (as I understand it). Puzzles are complicated, mysteries are complex.&lt;br /&gt;
&lt;br /&gt;
In his book, Steve is asserting that the traditional methods of management are aimed at solving the puzzle of efficiently providing goods and services. We have to accept that this is a valuable puzzle to solve, it provides obvious competitive advantages. He further asserts that this does not address the issue of what goods and services to provide and that there is a gap between what customers get and what customers want that is not answered through traditional management. This is where there is an opportunity to exploit another competitive advantage by refocusing the organisation on delighting customers. This seems to be the main driving force for the radical management techniques and I have to agree that this is the new frontier where real gains in competitive advantage can be found.&lt;br /&gt;
&lt;br /&gt;
Steve&#39;s book provides a lot of insight into how an organisation can refocus on this frontier; self organizing teams, leaving decisions to the last responsible moment, iterations and increments, focusing on a minimum marketable product, etc. These are the same principles (and maybe some additional ones) that come from the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;Agile&lt;/a&gt;&amp;nbsp;movement and Scrum.&lt;br /&gt;
&lt;br /&gt;
What interested me this morning though was the nature of this problem of delighting customers. It may be mysterious now but if the solution is Radical Management/Agile/Scrum what happens when everyone is doing it. Will the problem become a puzzle, what will the next frontier be?&lt;br /&gt;
&lt;br /&gt;
I think the answer is no. Delighting customers is not the problem that is solved by these new practices, it is the result of solving some other problems. It is a moving target, the key is in finding the problems/mysteries that then lead to customer delight. Delight comes from having a problem solved that you didn&#39;t even know you had. This may be leading to a delighting customers arms race as mysteries are found and converted to puzzles but that doesn&#39;t sound so bad.&lt;br /&gt;
&lt;br /&gt;
In statistics there is a concept of a non-stationary time series (I know a little about this as it was the subject of my final year dissertation at college). This is a series of data over time that is by it&#39;s nature not possible to model as it changes behaviour (technically variance) over time. Such activity is found in stock market prices where feedback in the system is a factor. While there are people making a lot of money out of quantitative analysis (predicting the future by analysing the past data) the problem is that the activity that results from applying a model may change the model.&lt;br /&gt;
&lt;br /&gt;
My feeling is that delighting customers follows the same pattern. Once customers figure out what it is that&#39;s delighting them they will no longer be delighted and will look for something more/different (I hope mainly different rather than more as that&#39;s what makes chasing these problems interesting).&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&quot;&lt;span style=&quot;background-color: white; color: #454545; font-family: &#39;Times New Roman&#39;, Times, serif; font-size: 17px; line-height: 19px;&quot;&gt;Any sufficiently advanced technology is indistinguishable from magic.&lt;/span&gt;&quot;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b style=&quot;background-color: white; color: #454545; font-family: &#39;Times New Roman&#39;, Times, serif; font-size: 15px; line-height: 19px; text-align: -webkit-auto;&quot;&gt;&lt;a href=&quot;http://www.quotationspage.com/quotes/Arthur_C._Clarke/&quot; style=&quot;color: purple;&quot;&gt;Arthur C. Clarke&lt;/a&gt;&lt;/b&gt;&lt;span style=&quot;background-color: white; color: #454545; font-family: &#39;Times New Roman&#39;, Times, serif; font-size: 15px; line-height: 19px; text-align: -webkit-auto;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;i style=&quot;background-color: white; color: #454545; font-family: &#39;Times New Roman&#39;, Times, serif; font-size: 15px; line-height: 19px; text-align: -webkit-auto;&quot;&gt;&quot;Profiles of The Future&quot;, 1961 (Clarke&#39;s third law)&lt;/i&gt;
&lt;/div&gt;
&lt;br /&gt;
The problems we solve that delight people are the magic that then quickly depreciate to the status of advanced technology (sorry, advanced technology, you&#39;re just not as cool as magic). Magic (and delight) is a moving boundary.&lt;br /&gt;
&lt;br /&gt;
So why am I worried about this? Well, I&#39;m sure that there will be something new after Radical Management/Agile/Scrum but for now I wanted to reassure myself that these are the tools we need now to keep chasing the magic boundary which is still far ahead of us. When we catch it (or get close to it as traditional management has gotten us close to the magic of efficiency) we will likely need to adjust &amp;nbsp;our focus on a new magic boundary and with that will come new techniques and practices.&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Apologies to Steve Denning if I have failed to get what he wanted to say in his book or in fact completely misrepresented him in this post. Suffice to say that everything written here is my own understanding and I do not wish to put words in anyone&#39;s mouths. Also, I&#39;m less than a third of the way through the book so there is likely more in it than I have gotten out of it so far.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/4209522200788719570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/on-puzzles-and-mysteries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4209522200788719570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4209522200788719570'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/on-puzzles-and-mysteries.html' title='On Puzzles and Mysteries'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-6938044181637206520</id><published>2012-06-29T15:56:00.002+02:00</published><updated>2012-06-30T11:12:11.220+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Eclipse"/><category scheme="http://www.blogger.com/atom/ns#" term="junit dependencies"/><category scheme="http://www.blogger.com/atom/ns#" term="osgi console"/><category scheme="http://www.blogger.com/atom/ns#" term="plugins"/><title type='text'>Gotcha!</title><content type='html'>&lt;p&gt;
So I almost ditched the OpenTV IDE again! Nothing is ever easy. I have been busy building the eclipse plugin to complement the OOOCode libraries I have been making, and everything was going great, until I tried to actually deploy the plugin in the OpenTV IDE...
&lt;/p&gt;
&lt;p&gt;
Nothing, nada, zip. It just doesn&#39;t show up and nowhere does it report any errors!
&lt;/p&gt;
&lt;p&gt;
All morning I spent cursing this hacked together, Frankenstein, eclipse monstrosity. This afternoon, though, I have to apologise so we can move on together in harmony.
&lt;/p&gt;
&lt;p&gt;
So what&#39;s the story...
&lt;/p&gt;
&lt;p&gt;
Well i&#39;m still a bit peaved that when eclipse plugins don&#39;t load, there is no obvious error reported anywhere, but eventually I found a comment in a forum suggesting the use of the OSGI console to load the plugin and diagnose it manually. Easy, I just have to launch the OpenTV IDE with the -console option.
&lt;/p&gt;
&lt;p&gt;
Sure enough a console launches alongside the editor. Next I tried...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;?&lt;/b&gt; - Yay! Lot&#39;s of handy help.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;diag com.pghalliday.ooocode&lt;/b&gt; - Boo! bundle cannot be found&lt;/li&gt;
&lt;li&gt;&lt;b&gt;install com.pghalliday.ooocode&lt;/b&gt; - Boo! invlid URL and stuff&lt;/li&gt;
&lt;li&gt;&lt;b&gt;install file:plugins/com.pghalliday.ooocode_1.0.0.201206281825.jar&lt;/b&gt; - Yay! bundle installed&lt;/li&gt;
&lt;li&gt;&lt;b&gt;diag com.pghalliday.ooocode&lt;/b&gt; - Oh... turns out my plugin is dependent on the org.junit bundle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So that was it. In my eagerness to have everything unit tested and to adopt test driven development I had fallen into a trap. My deployable jar file also includes the unit tests and is thus dependent on the JUnit bundle. Now I have to get Eclipse to export a jar file without the unit tests (for now i have worked around the problem by copying the org.junit bundle from the JEE Eclipse distribution to the OpenTV IDE plugins folder as well).
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/6938044181637206520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/gotcha.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6938044181637206520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6938044181637206520'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/gotcha.html' title='Gotcha!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3436441988778627759</id><published>2012-06-27T19:14:00.001+02:00</published><updated>2012-06-30T11:13:26.637+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C Preprocessor"/><category scheme="http://www.blogger.com/atom/ns#" term="Macros"/><category scheme="http://www.blogger.com/atom/ns#" term="Object Oriented C"/><category scheme="http://www.blogger.com/atom/ns#" term="OOOCode"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenTV"/><category scheme="http://www.blogger.com/atom/ns#" term="Test Driven Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Variadic"/><title type='text'>OOOCode - Part 2</title><content type='html'>&lt;p&gt;
Phew, a lot has happened since my last post on this subject. After much wrangling with the C preprocessor I have a working pattern which I&#39;m mostly happy with. It currently includes support for the following...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Classes&lt;/li&gt;
&lt;li&gt;Private data&lt;/li&gt;
&lt;li&gt;Public methods&lt;/li&gt;
&lt;li&gt;Private methods&lt;/li&gt;
&lt;li&gt;Multiple interfaces&lt;/li&gt;
&lt;li&gt;A unit test framework&lt;/li&gt;
&lt;li&gt;Some eclipse file templates&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Still to do (in no particular order)...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Performance profiling&lt;/li&gt;
&lt;li&gt;Exception handling&lt;/li&gt;
&lt;li&gt;Improve unit test automation&lt;/li&gt;
&lt;li&gt;Eclipse wizards&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Things that I&#39;m not quite sure about...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not sure if I really needed to implement the unit test stuff as classes and interfaces but it has an elegance&lt;/li&gt;
&lt;li&gt;Don&#39;t much like having multiple calling conventions for public methods, private methods and interface methods&lt;/li&gt;
&lt;li&gt;No support for inheritance - is it really needed anyway?&lt;/li&gt;
&lt;li&gt;No support for up casting and figuring out what type something is at run time - this may become more of an issue when thinking about exception handling&lt;/li&gt;
&lt;li&gt;Currently only support a single constructor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
This state can be found on GitHub &lt;a href=&quot;https://github.com/pghalliday/OOOCode/tree/1cdd5f7c59789c95dd9792eaa8bbacc516e410c5&quot;&gt;here&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
So how does it look right now (after all there is no documentation ;))
&lt;/p&gt;

&lt;h1&gt;Create an application that runs unit tests&lt;/h1&gt;

&lt;p&gt;
After generating your own application as described in &lt;a href=&quot;http://stuffpetedoes.blogspot.nl/2012/06/ooocode-part-1.html&quot;&gt;OOOCode - Part 1&lt;/a&gt; copy in the OOOCode/src/OOOCode directory from the above github project and add it and its subdirectories to the OpenTV options include paths.&lt;/p&gt;
&lt;p&gt;
Then create a Main.c as below...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/3004047.js?file=Main.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
The above code achieves the following...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Records the memory available at start up&lt;/li&gt;
&lt;li&gt;
Creates a debug output object using the OOOConstruct macro
&lt;ul&gt;
&lt;li&gt;In this case an OOODebug class is used instead of direct calls to O_debug as in tests for the unit test classes themselves it is necessary to use mock objects&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Creates a debug reporter object&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Unit test reports need to go somewhere, this class dumps them to debug output&lt;/li&gt;
&lt;li&gt;The debug instance is cast to an IDebug interface using the OOOCast macro, in this way it is possible to pass in a mock object when needed&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Calls the OOOUnitTestsRun method passing in the reporter to run the tests&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The debug reporter is cast to an IReporter interface using the OOOCast macro, this will allow the unit test framework to be extended later with different reporter objects (eg. over HTTP, etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Then the instantiated objects are destroyed using the OOODestroy macro and the memory is checked to ensure that the tests and the unit test framework used did not leak&lt;/li&gt;
&lt;li&gt;The last part (while loop) just ensures that the VSTB does not exit so we can see  the test report in the debug output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
So there are some key concepts introduced here...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOOConstruct - use this to construct an instance of a class, the first parameter is the class name, additional parameters are passed into the constructor as arguments&lt;/li&gt;
&lt;li&gt;OOOCast - use this to cast an instance of a class to an interface, the first parameter is the interface name, the second parameter is the class instance&lt;/li&gt;
&lt;li&gt;OOODestroy - use this to destroy an instance of a class and free it&#39;s memory, the only argument is the class instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
However, this will not yet compile. The function OOOUnitTestsRun is a special function that is generated by the OOOUnitTestsRun.h header file using xmacros. It generates an array of tests to run and runs them based on the contents of another header file: OOOTests.h
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=OOOTests.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
This initial OOOTests.h is empty and so this application does not yet run any tests. Now the application can be compiled (assuming that the OOOCode source has been added to the include paths).
&lt;/p&gt;
&lt;p&gt;
NB. The OOOTests.h file does not have an include guard and this is deliberate. An include guard would prevent the xmacros that use it from working. For more details on the xmacro pattern see &lt;a href=&quot;http://www.drdobbs.com/cpp/184401387&quot;&gt;this drdobbs article&lt;/a&gt;
&lt;/p&gt;

&lt;h1&gt;Adding a test for MyClass&lt;/h1&gt;

&lt;p&gt;
First update OOOTests.h...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=OOOTestsWithMyClass.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Once again this will not compile, but hey, we&#39;re doing test driven development.
&lt;/p&gt;
&lt;p&gt;
Add the MyClass.Test.h header...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.Test.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Still this will not compile, but note that the OOOTest macro call does not have a semicolon on the end - this is important. This just declares the test it does not yet compile because the test has not been implemented. Other tests can be declared with other names by adding further OOOTest calls (without semicolons)
&lt;/p&gt;
&lt;p&gt;
Add the MyClass.Test.c file...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.Test.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Now it gets a little bit more interesting and in fact should compile and run again. When it is run this code will print the &quot;MyClass test&quot; string to the debug in an xml test report format signifying that it is just information. The important concepts that we now have are...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Declare tests with calls to OOOTest in unguarded headers that are included in OOOTests.h&lt;/li&gt;
&lt;li&gt;Implement tests using the OOOTest macro as defined in OOOUnitTestDefines.h so that they look like functions&lt;/li&gt;
&lt;li&gt;
We can ouput information to the test report using the OOOInfo macro (this is actually a variadic macro that behaves like printf). Two other similar macros are also available in test implementations...
&lt;ul&gt;
&lt;li&gt;OOOWarning - adds a warning to the test report&lt;/li&gt;
&lt;li&gt;OOOError - adds an error to the test report&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Adding MyClass&lt;/h1&gt;

&lt;p&gt;We are going to add a class that takes an integer in the constructor and exports a method to retrieve that integer. So lets first write some more of the test. We update MyClass.Test.c as follows...&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.TestWithMethod.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Again this will not compile but we can see how we want our class to behave...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We include the class header (does not yet exist)&lt;/li&gt;
&lt;li&gt;We construct an instance of the class&lt;/li&gt;
&lt;li&gt;We check the retrieval of the integer constructor parameter&lt;/li&gt;
&lt;li&gt;We destroy the instance of the class&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The key concepts are...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The memory allocated in a test must be freed in the test, the unit test framework does check for memory anomalies and adds them to the test report&lt;/li&gt;
&lt;li&gt;Public methods are called with the OOOCall macro, the first argument is the instance, the second argument is the method name, additional arguments would be the parameters for the method&lt;/li&gt;
&lt;li&gt;OOOCheck is used to test a condition that must be true for the test to pass, it can be called as many times as you like but if the condition resolves to FALSE then an error entry will be added to the test report along with the file, line and condition that failed, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Add MyClass.h...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Now things are getting really interesting. Still this will not compile as we do not have an implementation for MyClass but lets go through what&#39;s happening here in the header...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have an include guard - that&#39;s fine here :)&lt;/li&gt;
&lt;li&gt;The OOCode.h header is included to enable all the OOOCode goodness ;)&lt;/li&gt;
&lt;li&gt;The name of the class is #defined as OOOClass - this is used inside other macros as the class name and simplifies those macro calls&lt;/li&gt;
&lt;li&gt;The class is declared using the OOODeclare macro, it takes the constructor arguments as parameters&lt;/li&gt;
&lt;li&gt;A list of implemented interfaces is given using the OOOImplements block, this must be present even if it is empty as in this case&lt;/li&gt;
&lt;li&gt;A list of public methods is given using the OOOExports block, in this case one method is exported using OOOExport&lt;/li&gt;
&lt;li&gt;The declare block is closed and importantly OOOClass is #undef&#39;d so that other classes can be declared&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Let&#39;s go through those macro calls in a bit more detail...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOODeclare - actually declares the type and the constructor hence the addition of the constructor arguments&lt;/li&gt;
&lt;li&gt;OOOImplements - starts the structure defining the public interfaces avialable (OOOImplement will be detailed later)&lt;/li&gt;
&lt;li&gt;OOOImplement - finalizes the interfaces structure&lt;/li&gt;
&lt;li&gt;OOOExports - starts the vtable structure providing access to public methods&lt;/li&gt;
&lt;li&gt;OOOExport - adds a public method to the vtable, the first argument is the return type, the second argument is the name of the method, any further arguments will be the parameters for the method (in this case there are none)&lt;/li&gt;
&lt;li&gt;OOOExportsEnd - finalizes the vtable structure&lt;/li&gt;
&lt;li&gt;OOODeclareEnd - this finalizes everything and defines a public structure used to access the public methods and interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Now we&#39;re also ready to add the implementation, so create the following MyClass.c file...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
So what&#39;s this all about then...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Include the MyClass.h header&lt;/li&gt;
&lt;li&gt;#define OOOClass to the name of the class, again this is so that other macro calls can use it and their interfaces are thus simplified (it would be nice if macros could define other macros internally, but hey ho...)&lt;/li&gt;
&lt;li&gt;Declare the private data fields using OOOPrivateData - just one integer field&lt;/li&gt;
&lt;li&gt;Implement the destructor function with OOODestructor - in this case it is empty as no additional memory is allocated when constructing objects of this class&lt;/li&gt;
&lt;li&gt;Implement a method using OOOMethod - this one just returns the integer field accessed through a call to the OOOF macro&lt;/li&gt;
&lt;li&gt;Implement the constructor using OOOConstructor - in the constructor it is also necessary to map any internal functions to external methods and interfaces, in this case...&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;OOOMapMethods is used to open a list methods to map to the exported vtable&lt;/li&gt;
&lt;li&gt;OOOMethodMapping is used to map the getMyField method to the first entry in the vtable - the compiler will pick up any type incompatibilities here&lt;/li&gt;
&lt;li&gt;The mapping is closed with OOOMapMethodsEnd&lt;/li&gt;
&lt;li&gt;Lastly the constructor assigns the nMyField parameter to the nMyField private data entry (again using the OOOF accessor macro)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;

&lt;p&gt;
Again let&#39;s look at these new macros...
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OOOPrivateData - starts a new private data structure, this should only appear once&lt;/li&gt;
&lt;li&gt;OOOPrivateDataEnd - closes the private data structure, fields in the structure should be placed between these 2 macros in the same format you would use for a struct (it is a struct!)&lt;/li&gt;
&lt;li&gt;OOODestructor - this starts the destructor method, destructors take no additional arguments, this should only appear once&lt;/li&gt;
&lt;li&gt;OOODestructorEnd - this ends the destructor method, it actually also frees the class instance which is why you don&#39;t have to do it yourself. The curly braces between these 2 macro calls in this case a re purely a matter of style and optional, they would only be required if it were necessary to declare any local variables in the destructor method. I use them anyway because it makes the implementation look more like a standard C method (a bit)&lt;/li&gt;
&lt;li&gt;OOOMethod - this starts a method implementation, the first argument is the return type, the second is the method name, any additional arguments will be passed into the method. The method is effectively private until it is mapped to the class or an interface vtable (the macro declares it static)&lt;/li&gt;
&lt;li&gt;OOOMethodEnd - this closes the method implementation, again the curly braces are mostly optional&lt;/li&gt;
&lt;li&gt;OOOConstructor - this starts the constructor implementation, it should appear only once. The arguments are the constructor parameters&lt;/li&gt;
&lt;li&gt;OOOMapMethods - this starts the class vtable mapping&lt;/li&gt;
&lt;li&gt;OOOMethodMapping - this maps a method to an entry in the class vtable, the only parameter is the method name - this is the private method name as defined in the call to OOOMethod, it does not have to match the exported method name in the vtable defined in the header. It is important to add the methods to the mapping in the same order that they are added to the vtable in the header using calls to OOOExport&lt;/li&gt;
&lt;li&gt;OOOMapMethodsEnd - this closes the vtable mapping&lt;/li&gt;
&lt;li&gt;OOOConstructorEnd - this closes the constructor implementation&lt;/li&gt;
&lt;li&gt;OOOF - this macro accesses the private fields of the current class instance, the only argument is the name of the field. It is not possible to access fields of instances of other classes but later we will see how to access fields of other instances of the same class&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Adding IMyInterface&lt;/h1&gt;

&lt;p&gt;
We will now add an interface that defines a single method that returns an integer. Again let&#39;s start with the test and update MyClass.Test.c as follows...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/3004047.js?file=MyClass.TestWithInterface.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Only a small change but again this will not compile...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We added a new check, casting the instance to IMyInterface and calling the getData interface method using the OOOICall calling convention - in the test I have assumed that getData will be mapped to retrieving the constructor parameter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Only one new macro has been introduced here...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOOICall - this macro must be used when calling methods on interface instances, it is much the same as OOOCall in that the first argument is the interface instance, the second argument is the interface method name and any additional arguments are passed through as parameters to the implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
To make this compile we will have to add IMyInterface.h and update MyClass to implement the interface...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3004047.js?file=IMyInterface.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
This is pretty similar to the pattern used to declare the class...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is an include guard&lt;/li&gt;
&lt;li&gt;OOOCode.h is included&lt;/li&gt;
&lt;li&gt;This time we specify the interface name in a #define called OOOInterface&lt;/li&gt;
&lt;li&gt;The interface vtable is then started with a call to the OOOVirtuals macro&lt;/li&gt;
&lt;li&gt;Methods are added to the vtable using calls to the OOOVirtual macro&lt;/li&gt;
&lt;li&gt;The vtable is then closed and OOOInterface is #undef&#39;d so that other interfaces can be declared&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
So the new macros are...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOOVirtuals - starts the interface vtable&lt;/li&gt;
&lt;li&gt;OOOVirtual - declares a method entry in the vtable, the first argument will be the return type, the second argument is the method name and any additional arguments will be the parameters for the method. Any method implementing this virtual method will have to have the same signature and the compiler will check&lt;/li&gt;
&lt;li&gt;OOOVirtualsEnd - closes the interface vtable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This still won&#39;t compile so next we update MyClass.h...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3005134.js?file=MyClass.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Again a small change...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The interface header has been added&lt;/li&gt;
&lt;li&gt;An OOOImplement call has been added to the OOOImplements block to add the interface to the declaration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Just one new macro then...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOOImplement - this adds the interface to the interface table, the only argument is the name of the interface&lt;li&gt;
&lt;/ul&gt;

&lt;p&gt;
This will compile but the test will fail. In fact the test should crash with a NULL pointer exception as the method has neither been implemented or mapped to the interface. We need to update MyClass.c too...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3005134.js?file=MyClass.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Now the code will both compile and the tests will run successfully! (assuming I transcribed everything correctly).
&lt;/p&gt;
&lt;p&gt;
There are 2 additions here...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The method has been implemented as getData and this method just calls the other method using the private method calling convention, OOOC&lt;/li&gt;
&lt;li&gt;
The interface vtable has been mapped in the constructor
&lt;ul&gt;
&lt;li&gt;The interface name is given in the OOOInterface #define to simplify the other macro calls&lt;/li&gt;
&lt;li&gt;The interface vtable mapping is started with a call to OOOMapVirtuals&lt;/li&gt;
&lt;li&gt;The getData method is mapped using a call to the OOOVirtualMapping macro&lt;/li&gt;
&lt;li&gt;The mapping is closed with a call to OOOMapVirtualsEnd and OOOInterface is undef&#39;d so that other interfaces can be mapped&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
So the new macros we have used are...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OOOC - this macro accesses the private methods of the current class instance, the first argument is the name of the method and any additional arguments are passed through as parameters to the method. It is not possible to access private methods of instances of other classes but later we will see how to access methods of other instances of the same class&lt;/li&gt;
&lt;li&gt;OOOMapVirtuals - this starts the interface vtable mapping&lt;/li&gt;
&lt;li&gt;OOOVirtualMapping - this maps a method to an entry in the interface vtable, the only parameter is the method name - this is the private method name as defined in the call to OOOMethod, it does not have to match the exported method name in the vtable defined in the interface header. It is important to add the methods to the mapping in the same order that they are added to the vtable in the interface header using calls to OOOVirtual&lt;/li&gt;
&lt;li&gt;OOOMapVirtualsEnd - this closes the interface vtable mapping&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Adding copy and isEqual methods&lt;/h1&gt;

&lt;p&gt;
As a final example and to round out the macro examples let&#39;s see how we can add additional methods to copy and compare instances of MyClass. Of course, we start with a test so let&#39;s update MyClass.Test.c...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3005134.js?file=MyClass.Test.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
The following changes were made...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A new instance of MyClass, pMyClassCopy, is generated through a call to a new copy method&lt;/li&gt;
&lt;li&gt;We check that the new copy is equal to the original&lt;/li&gt;
&lt;li&gt;We check that the new copy returns the same value from getMyField&lt;/li&gt;
&lt;li&gt;We check that the copy method didn&#39;t cheat and that the copy is a different instance (pointer address)&lt;/li&gt;
&lt;li&gt;We remember to clean up the new instance too&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Once again our code does not compile, but that&#39;s ok. We need to update MyClass.h to export the new methods...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3005134.js?file=MyClassWithCopy.h&quot;&gt;&lt;/script&gt;
&lt;p&gt;
This will now compile but, as with the interface implementation, the test will crash when it gets to the copy call as the method has not been implemented and mapped in the vtable. Anyway let&#39;s see what we&#39;ve done...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two new calls have been made to OOOExport to export the copy and isEqual methods&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now we implement and map the methods in MyClass.c...
&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/3005134.js?file=MyClassWithCopy.c&quot;&gt;&lt;/script&gt;
&lt;p&gt;
Yay, sucess! The code compiles, runs and the tests pass. We added 2 new methods and mapped them so what&#39;s new in this...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the compare method we used a new macro, OOOPCall, this is more efficient than OOOCall and can also be used to access unmapped methods in a class. The first argument is the class instance, the second is the method name and any additional arguments will be passed into the method. In this case OOOC could not be used as we wanted to call a method on another instance&lt;/li&gt;
&lt;li&gt;Notice that the additional mappings in OOOMapMethods are preceded by commas - this is because they result in static initialiser elements in a structure. The same applied to the virtual mappings if there are more than one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
So what haven&#39;t we seen? Well, two additional things spring to mind...
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is also possible to access fields on other instances of a class. This is achieved through calls to OOOField, like OOOPCall this can only be used in the class implementation and the first parameter will be the instance, the second parameter is the field name. We could have used this in place of OOOPCall above but it is a matter of style to use the accessor method instead (performance optimisations could dictate otherwise though)&lt;/li&gt;
&lt;li&gt;If it is necessary to access the current instance (perhaps to return from a method or pass into another method) then it is always available in the methods, constructor and destructor through the OOOThis pointer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So that&#39;s it. Although this will all probably change in the next 5 minutes. If you&#39;re interested then keep an eye on this blog and the GitHub repository.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3436441988778627759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/ooocode-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3436441988778627759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3436441988778627759'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/ooocode-part-2.html' title='OOOCode - Part 2'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-6574004043875298278</id><published>2012-06-23T10:32:00.000+02:00</published><updated>2012-06-25T16:41:40.950+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C Preprocessor"/><category scheme="http://www.blogger.com/atom/ns#" term="Constants"/><category scheme="http://www.blogger.com/atom/ns#" term="Macros"/><category scheme="http://www.blogger.com/atom/ns#" term="OOOCode"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenTV"/><category scheme="http://www.blogger.com/atom/ns#" term="Variadic"/><title type='text'>A Macro Interlude</title><content type='html'>&lt;h1&gt;Or... Traversing Macro Pasting Hell&lt;/h1&gt;

&lt;p&gt;
Full disclaimer: This article used to be very different but was also complete tosh. The code I wrote based on its assumptions and misinformation was working fine for days and then broke around 5 minutes after posting the article when I discovered a new use case. This new article addresses that use case and the subsequent solution
&lt;/p&gt;

&lt;h3&gt;Macro pasting&lt;/h3&gt;

&lt;p&gt;
The C preprocessor has a handy (if not essential) operator for pasting 2 tokens together, &lt;b&gt;##&lt;/b&gt;. I use it all over the place in my OOOCode project to generate class and function names, etc using macros. It can be used like this...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=Paste.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Now consider the following...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=PasteBroken.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
In this second example I have passed a macro in as an argument to the PASTE macro and as a result it does not get expanded. In order to fix this it is necessary to add a level of indirection...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=PasteFixed.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;As an aside, this same problem (and solution) occurs with the quoting operator, &lt;b&gt;#&lt;/b&gt;, too.&lt;/p&gt;

&lt;h3&gt;Variadic macros and swallowing extra commas&lt;/h3&gt;

&lt;p&gt;
Now it gets interesting as the pasting operator can also be used in variadic macros to swallow commas when no arguments are provided...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=VariadicMacro.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Handy, yeah? Well sort of. The problem is that this still exhibits the same problems as above when macros are used as arguments...
&lt;/p&gt;

&lt;h3&gt;Macro pasting variadic hell&lt;/h3&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=FailsToExpand.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
The above code does not compile as the second macro call does not get expanded. So I tried this...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=FailsToSwallowComma.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
I&#39;m not sure if this would work in other environments but the C Preprocessor that comes with the OpenTV IDE doesn&#39;t swallow the comma in this case.
&lt;/p&gt;

&lt;p&gt;
This gave me a big problem. I can either support macros as arguments or zero length argument lists... but not both :(
&lt;/p&gt;

&lt;p&gt;
Believe me I tried a great many more constructions involving the &lt;b&gt;##&lt;/b&gt; operator and various indirections but to no avail. It just wasn&#39;t happening. Eventually (it was quite long time that may even have involved praying as I was a long way into my OOOCode stuff and this was pretty key) I came across a different solution involving detecting empty argument lists. Doing this is not simple and definitely not something I want to get into here, but just know that in the following example the &lt;b&gt;ISEMPTY&lt;/b&gt; macro expands to 1 if the argument list supplied is empty or 0 if not...
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2977939.js?file=Solution.c&quot;&gt;&lt;/script&gt;

&lt;p&gt;
For the &lt;b&gt;ISEMPTY&lt;/b&gt; macro stuff, special thanks have to go to Jens Gustedt and this article:
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/&quot;/&gt;http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/&lt;/a&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/6574004043875298278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/macro-interlude.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6574004043875298278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/6574004043875298278'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/macro-interlude.html' title='A Macro Interlude'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-7789679751858845490</id><published>2012-06-17T11:52:00.000+02:00</published><updated>2012-06-27T13:33:07.245+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Object Oriented C"/><category scheme="http://www.blogger.com/atom/ns#" term="OOOCode"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenTV"/><title type='text'>OOOCode - Part 1</title><content type='html'>This is a continuation of the following post on Object Oriented C&lt;br /&gt;
&lt;p&gt;&lt;a href=&quot;http://stuffpetedoes.blogspot.nl/2012/06/object-oriented-c-part-2.html&quot;&gt;Object Oriented C - Part 2&lt;/a&gt;&lt;/p&gt;
First thing is to get the existing pattern example into an OCode project and stick that up on GitHub. I don&#39;t like the default OpenTV IDE project templates as they actually require multiple Eclipse projects and due to the nature of the OpenTV hacked Eclipse cannot be built and run from a command line. This creates obvious problems when trying to set up a continuous integration environment. However for these purposes a standard OCode template will suffice.&lt;br /&gt;
&lt;br /&gt;
To do this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I created an OOOCode directory and checked out the OOOCode git repository to it.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
I opened the OpenTV IDE and selected &amp;nbsp;the new OOOCode directory as the workspace location&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJT3M7rWu61mJxD1wsGqqTtC3YJiWV9xz6GRWwjG1jn6iV_fHyrr4eHpEbjFTyq5ZcO1fhyphenhyphenoI_mC1ssA5p-ewnMCZ01OLfS1UELqTYuGtVkzAld-VXKBIxWhaFqUI6KMjmGzdk3xZ-azrX/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;145&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJT3M7rWu61mJxD1wsGqqTtC3YJiWV9xz6GRWwjG1jn6iV_fHyrr4eHpEbjFTyq5ZcO1fhyphenhyphenoI_mC1ssA5p-ewnMCZ01OLfS1UELqTYuGtVkzAld-VXKBIxWhaFqUI6KMjmGzdk3xZ-azrX/s320/Capture.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
I created a new OpenTV Project called OOOCode in the default location (pressing Finish immediately as I did not want the hello world example code)&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTqXDxycV4kJIGGcAZi3gP3mbUFsSGCuEzbSCDHCXKdKeS0kLMFdvGI9Ly4GKG99xDSybAhxFeQD4JABzxSEQIvZ4oWNX5t6oi8o5dE2r4IofsAdwuJLT3BEDA8PgQ9pYOj9gD9BFrkG1/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTqXDxycV4kJIGGcAZi3gP3mbUFsSGCuEzbSCDHCXKdKeS0kLMFdvGI9Ly4GKG99xDSybAhxFeQD4JABzxSEQIvZ4oWNX5t6oi8o5dE2r4IofsAdwuJLT3BEDA8PgQ9pYOj9gD9BFrkG1/s320/Capture.PNG&quot; width=&quot;293&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This resulted in the following projects being created in my OOOCode directory.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;OOOCode&lt;/li&gt;
&lt;li&gt;OOOCodeDir&lt;/li&gt;
&lt;li&gt;OOOCodeFlow&lt;/li&gt;
&lt;li&gt;OOOCodeRes&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
As pictured:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXxqJpTthpF_9Ctt8rEZt-9t6Tw0n7I3a5J7aT5DnjLmWO0s8NyVvB1ldvF3Th9KbWT2oQLvGL0NZpalyZvunQgbbda72ZAMO4_V8gnBUyDp8SFZyBxPWEv2Kwvhlcf5_c-d5cnlO73_Ff/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXxqJpTthpF_9Ctt8rEZt-9t6Tw0n7I3a5J7aT5DnjLmWO0s8NyVvB1ldvF3Th9KbWT2oQLvGL0NZpalyZvunQgbbda72ZAMO4_V8gnBUyDp8SFZyBxPWEv2Kwvhlcf5_c-d5cnlO73_Ff/s320/Capture.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To build and run the project in the OpenTV Virtual STB.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Choose &quot;Build All&quot; from the &quot;Project&quot; menu.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Select the OOOCodeFlow project and press the Run button.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In the next dialog choose &quot;Local OpenTV Application&quot;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtv-_VXvhNg6Q9S0VJRJKnbjYUDrwdBQnJ8NvempqmPHk225iJfIfNqAcBaMEE8Cvkqcv2vzNq9WCmDyfGun-9FTcibK2QGDN_u1cMbyTjV6vIRI08-7uy4_AJh3CauyLeh-gEDiyULNV/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtv-_VXvhNg6Q9S0VJRJKnbjYUDrwdBQnJ8NvempqmPHk225iJfIfNqAcBaMEE8Cvkqcv2vzNq9WCmDyfGun-9FTcibK2QGDN_u1cMbyTjV6vIRI08-7uy4_AJh3CauyLeh-gEDiyULNV/s320/Capture.PNG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
That&#39;s as much as I&#39;m going to say about the OpenTV IDE for now but next I copied in my existing OO pattern example code and committed it to GitHub. This starting state can be found here:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;https://github.com/pghalliday/OOOCode/tree/9fd2a18d20f5b515a9951a2e3b1c15af06a0ecd6&quot;&gt;https://github.com/pghalliday/OOOCode/tree/9fd2a18d20f5b515a9951a2e3b1c15af06a0ecd6&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Full disclosure... I did fix a couple of issues in the code i originally posted in the gists:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;I missed a parameter in the MyClass constructor&lt;/li&gt;
&lt;li&gt;I forgot that the VSTB exits when the main method exits and as such it can be difficult to check the debug output unless you put a real message loop in and wait for the quit message&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/7789679751858845490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/ooocode-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7789679751858845490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7789679751858845490'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/ooocode-part-1.html' title='OOOCode - Part 1'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJT3M7rWu61mJxD1wsGqqTtC3YJiWV9xz6GRWwjG1jn6iV_fHyrr4eHpEbjFTyq5ZcO1fhyphenhyphenoI_mC1ssA5p-ewnMCZ01OLfS1UELqTYuGtVkzAld-VXKBIxWhaFqUI6KMjmGzdk3xZ-azrX/s72-c/Capture.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-7118133410664969965</id><published>2012-06-17T10:05:00.003+02:00</published><updated>2012-06-23T10:33:38.248+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Object Oriented C"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenTV"/><title type='text'>Object Oriented C - Part 2</title><content type='html'>Now that I have detailed my existing pattern it&#39;s time to start working on an easier to implement/maintain replacement. To do this I need to start thinking about how to test it. After all I am fully embracing test driven development these days.&lt;br /&gt;
&lt;br /&gt;
One thing I forgot of course when detailing the existing pattern is how to use it in an application. I think that part at least is pretty straight forward but just to complete the square, here&#39;s an example main.c:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=Main.c&quot;&gt;
&lt;/script&gt;
&lt;br /&gt;
So here are the tests although I haven&#39;t used the unit test framework I might use ordinarily (I didn&#39;t want to cloud the details and introduce more dependencies). Again I haven&#39;t run this code (currently working in OSx and the OpenTV IDE only runs on Windows) but as soon as I do I&#39;ll correct any mistakes found and likely add it to my previously created project in GitHub (currently lying empty) &lt;br /&gt;
&lt;br /&gt;
One last thing for this post though, I thought of a better name for my project. From Object Oriented OCode we get OOOCode. That&#39;s right... Oooooo, code ;) (or Oh! Oh! Oh! Code - haven&#39;t decided)&lt;br /&gt;
&lt;br /&gt;
Previous link is now almost certainly broken so here&#39;s a new one.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/pghalliday/OOOCode&quot;&gt;https://github.com/pghalliday/OOOCode&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/7118133410664969965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/object-oriented-c-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7118133410664969965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7118133410664969965'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/object-oriented-c-part-2.html' title='Object Oriented C - Part 2'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-1574733759509121521</id><published>2012-06-16T12:46:00.000+02:00</published><updated>2012-06-23T10:33:59.337+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Object Oriented C"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenTV"/><title type='text'>Object Oriented C Reboot</title><content type='html'>As is normally the case I started something and then put it down and did lots of other things instead. In a rare bout of refocusing though I&#39;m picking up the object oriented C (OCode) stuff again.&lt;br /&gt;
&lt;br /&gt;
Previously I got very side tracked into setting up a perfect development environment as I would like to use at work. Something that would be compatible with automated build systems. Furthermore, I started trying to port the subversion externals pattern that I like to use for shared code to Git on GitHub - I quickly discovered that I&#39;m still very much a Git newbie. This was not very lean of me...&lt;br /&gt;
&lt;br /&gt;
So i&#39;m rebooting. This time around I will focus on the task at hand which is to create a simple templating and/or preprocessing system for generating class and interface boiler plate for use in OpenTV applications which are exclusively written in C.&lt;br /&gt;
&lt;br /&gt;
Let&#39;s start with a description of the pattern I currently use to implement classes. This part is simple and the boiler plate is not so bad.&lt;br /&gt;
&lt;br /&gt;
The header:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=MyClass.h&quot;&gt;
&lt;/script&gt;
The implementation:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=MyClass.c&quot;&gt;
&lt;/script&gt;
Excuse any obvious errors, I just typed that out without trying to run or compile it, but i think you can get the idea - nicely encapsulated, right?&lt;br /&gt;
&lt;br /&gt;
So that&#39;s all good. A little boiler plate in exposing opaque types and constructors/destructors but not so bad. The problems/challenges(/opportunities ;)) start when I try to extend this pattern with interfaces. Let&#39;s extend the example with that pattern.&lt;br /&gt;
&lt;br /&gt;
The interface:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=MyInterface.h&quot;&gt;
&lt;/script&gt;
Now we can see some really obvious complexity. Just look at the length of it and it doesn&#39;t even do anything really. Immediately apparent is how much work it would be to add a new method to the interface.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Add a new typedef for the method prototype&lt;/li&gt;
&lt;li&gt;Add a field to the interface structure&lt;/li&gt;
&lt;li&gt;Add an argument to the interface constructor&lt;/li&gt;
&lt;li&gt;Add a redirector method to allow the implementation to be called&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
It&#39;s fiddly work and potentially error prone (and this stuff can be hard to debug). The good news is that interfaces tend to be fairly stable once done as they don&#39;t contain business logic (although they may represent it I guess).&lt;br /&gt;
&lt;br /&gt;
We&#39;re not finished though. The interface has to be implemented by our class for it to be useful.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s the new header for our class:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=MyClassWithMyInterface.h&quot;&gt;
&lt;/script&gt;
&lt;br /&gt;
Notice the addition of a method to get an instance as an instance of MyInterface this is our casting convention.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s the new implementation of our class:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/2940847.js?file=MyClassWithMyInterface.c&quot;&gt;
&lt;/script&gt;
&lt;br /&gt;
That wasn&#39;t so bad, we:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Added a field to the class structure to store the interface instance&lt;/li&gt;
&lt;li&gt;Implemented the interface method&lt;/li&gt;
&lt;li&gt;Constructed an interface instance in the class constructor&lt;/li&gt;
&lt;li&gt;Destroyed the interface instance in the class destructor&lt;/li&gt;
&lt;li&gt;Added the method to implement our casting convention&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Again it was fiddly though and remembering that we have to do these things in every class that implements the interface we are now exposed to following types of errors:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Memory leaks due to forgetting to destroy the interface&lt;/li&gt;
&lt;li&gt;Strange affects from casting incorrectly in method implementations (doesn&#39;t seem likely until you remember that casts are a nightmare for hiding copy paste errors)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;br /&gt;
So let&#39;s review. We now have 3 quite complicated files that are quite hard to maintain. Particularly, changes in interfaces result in a large quantity of refactoring radiating out all over the place. Plus we have to be careful whenever we implement a new instance of an interface. And remember that this example only implements 1 interface method!&lt;br /&gt;
&lt;br /&gt;
This is a barrier to using the pattern which I would like to overcome. Just writing it up took longer than I expected and I have to go out now so I guess there will be a part 2 where I actually get started on how I would like it to look and work :)&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
As an aside the work I have been doing to make OpenTV application generating and testing makefiles using make function implementations will likely be the subject of a future post. As will figuring out how to share code and resources across Git repositories/projects.</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/1574733759509121521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/object-oriented-c-reboot.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1574733759509121521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1574733759509121521'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/object-oriented-c-reboot.html' title='Object Oriented C Reboot'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3317371399588548871</id><published>2012-06-15T13:38:00.000+02:00</published><updated>2012-06-23T10:34:19.161+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Test Driven Development"/><title type='text'>Required watching!</title><content type='html'>&lt;br /&gt;
http://jamesshore.com/Blog/Lets-Play/&lt;br /&gt;
&lt;br /&gt;
Well it might be if it weren&#39;t 197 episodes and counting but this series of videos illustrating test driven development (TDD) in Java and Eclipse are really excellent. I&#39;m currently up to episode 25 (since yesterday... addicted!) and already I have learnt so much about:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;writing tests up front&lt;/li&gt;
&lt;li&gt;emergent design&lt;/li&gt;
&lt;li&gt;AND just how magical eclipse is when it comes to generating code and refactoring in Java&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
I really recommend watching some of these. It starts with a completely blank application so I would go from there.&lt;br /&gt;
&lt;br /&gt;
I really want some of these IDE features in the OCode development we do too. And I can see that there may be some mileage in that.&lt;br /&gt;
&lt;br /&gt;
Now i can&#39;t wait for James&#39; new series that I gladly helped fund on Kickstarter.&lt;br /&gt;
&lt;br /&gt;
http://www.letscodejavascript.com/&lt;br /&gt;
&lt;br /&gt;
2 things that have got me excited recently in one package - TDD and server side Javascript... Yay, Node.js!&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3317371399588548871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/required-watching.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3317371399588548871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3317371399588548871'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/required-watching.html' title='Required watching!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-8909861718948348694</id><published>2012-06-07T13:28:00.002+02:00</published><updated>2012-06-07T13:28:44.855+02:00</updated><title type='text'>Error handling in C</title><content type='html'>&lt;br /&gt;
An interesting and somewhat familiar set of macros for error handling in C:&lt;br /&gt;
&lt;br /&gt;
http://c.learncodethehardway.org/book/learn-c-the-hard-waych21.html
&lt;br /&gt;
&lt;br /&gt;
A possible coding standard. Not with the debug flags (I hate debug builds!) but interesting all the same. I can see this approach getting rid of some of the over indentation caused by checking return values. As a coding standard though, I am resistant to always using the return value of a function as an error code... maybe I shouldn&#39;t be.&lt;br /&gt;
&lt;br /&gt;
The most interesting part is that it looks and behaves like exception handling to an extent. A problem which is altogether too difficult to mess around with in C. However by stopping short of trying to automatically pass you back up the stack perhaps this does capture some of the essence (read value). A good, lean application of the 80/20 rule.&lt;br /&gt;
&lt;br /&gt;
Still, to retrofit this stuff would likely fall short of being lean. Maybe I can mix it into the the Object Oriented C stuff I started working on.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/8909861718948348694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/error-handling-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/8909861718948348694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/8909861718948348694'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/error-handling-in-c.html' title='Error handling in C'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-7164889394964003363</id><published>2012-06-02T11:15:00.003+02:00</published><updated>2012-06-02T11:22:00.922+02:00</updated><title type='text'>Object Oriented C</title><content type='html'>I&#39;m waiting for virus updates to complete and the new windows GitHub client to install - why is my computer so slow today!?&lt;br /&gt;
&lt;br /&gt;
Anyway a chance to write a blog post then.&lt;br /&gt;
&lt;br /&gt;
I&#39;m becoming increasingly agile :) ... no not like a cat :s&lt;br /&gt;
&lt;br /&gt;
Recently I completed my certified Scrum Master and Product Owner training and we&#39;re making great progress at work putting it all into practice. It really has reinvigorated my interest in software development and once again I am reading voraciously on subjects that actually excite me (you&#39;ll maybe shake your head when you realise what those subjects are ;)). Can&#39;t remember having this feeling since I first started coding back in University.&lt;br /&gt;
&lt;br /&gt;
So what&#39;s on my mind today?&lt;br /&gt;
&lt;br /&gt;
Well, I&#39;ve been reading &lt;a href=&quot;http://www.amazon.com/Working-Effectively-Legacy-Code-ebook/dp/B005OYHF0A/ref=tmm_kin_title_0?ie=UTF8&amp;amp;m=A1HC3MLVT7QPHY&quot;&gt;Michael Feather&#39;s &quot;Working Effectively With Legacy Code&quot;&lt;/a&gt; and once again I have found an author who really does reflect, distill and reinforce what I only really knew at the back of my mind. This is great as it gives me more confidence that I&#39;m on the right path but also provides a glimpse of where that path leads.&lt;br /&gt;
&lt;br /&gt;
One place that it leads is to greater use of object oriented principles in our code.&lt;br /&gt;
&lt;br /&gt;
Some background... We write software for the OpenTV middleware in C to run on digital TV set top boxes. This is not object oriented. It isn&#39;t even really C, we can&#39;t use standard libraries and have to write pretty much everything from scratch. This has included basic libraries and a lot of tools and frameworks. Our main focuses at the moment are&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Reduce build times and complexity&lt;/li&gt;
&lt;li&gt;Use more off the shelf and advanced development/debugging tools&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;There is a freely available OpenTV IDE based on Eclipse which is very useful as it also includes a set top box emulator allowing us to step through code (http://community.opentv.com)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Automate builds / implement continuous integration (&lt;a href=&quot;http://jenkins-ci.org/&quot;&gt;Jenkins&lt;/a&gt;)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;This conflicts with the eclipse IDE which is not good with headless builds, we&#39;ve worked around this though, it just means we can&#39;t take advantage of standard OpenTV project templates. No biggy, we know what we&#39;re doing :)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Add a unit testing framework and increase test coverage of legacy code&lt;/li&gt;
&lt;li&gt;Test driven development&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;We have the framework so we have to do this to really reap the benefits in my opinion&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Automate tests&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Very much a TODO - the set top box emulator does not like to run on our continuous integration server unless it is not running as a service and some one is logged on. It uses DirectX :s&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Move away from specification documents to specification by tests.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;We are looking at integrating &lt;a href=&quot;http://fit.c2.com/&quot;&gt;Fit&lt;/a&gt; and &lt;a href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt;&amp;nbsp;to capture business rules and automate acceptance testing&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
So why more OO?&lt;br /&gt;
&lt;br /&gt;
Simple really. We need units to test. We need those units to be independent so that we can develop and verify them quickly. The approaches of TDD and the means of dealing with legacy code to make it more maintainable/manageable require great discipline and effort. We need to make the task less onerous. A major part of doing that is to use interfaces to break dependencies between libraries. There are other options in C (preprocessor for example) and we have to be careful about performance on our platform. But with careful application I am convinced that we will get the best mileage out of a consistent application of OO interfaces.&lt;br /&gt;
&lt;br /&gt;
So today I am going to figure out a good standard pattern for implementing classes and interfaces in C. Probably using the preprocessor to do some of the hard work. Previous attempts have always resulted in a lot of unwieldy repetition that I sometimes think only I understand (making it instant legacy code!).&lt;br /&gt;
&lt;br /&gt;
Ok, installs completed :) &lt;a href=&quot;https://github.com/pghalliday/OpenTvObjectOrientedC&quot;&gt;New git repository created&lt;/a&gt;. I wonder if I&#39;ll just end up reinventing Objective C.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/7164889394964003363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/im-waiting-for-virus-updates-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7164889394964003363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7164889394964003363'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/06/im-waiting-for-virus-updates-to.html' title='Object Oriented C'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-4349336810163650270</id><published>2012-04-04T19:52:00.000+02:00</published><updated>2012-04-04T19:53:37.496+02:00</updated><title type='text'>I&#39;m back! Let&#39;s see how long for :)</title><content type='html'>Wow, we&#39;re well into 2012 already and I haven&#39;t posted anything since 2010!&lt;br /&gt;
&lt;br /&gt;
So what&#39;s changed?&lt;br /&gt;
&lt;br /&gt;
I guess I was too busy doing stuff to blog about it for a while but yeah, quite a bit has changed. I have a lovely girlfriend now (which is probably another reason I haven&#39;t posted) :)&lt;br /&gt;
&lt;br /&gt;
I quit drinking just over a year ago and haven&#39;t looked back on that. Just before my exam for the WSET advanced certificate in wines and spirits (yeah that helped - fail!)&lt;br /&gt;
&lt;br /&gt;
I have taken up tea drinking in quite a serious way (and am now a very fussy tea snob ;))&lt;br /&gt;
&lt;br /&gt;
I took up Ashtanga Yoga, but have lapsed already :o (although still cycling, yay!)&lt;br /&gt;
&lt;br /&gt;
I have a renewed interest in work mostly due to discovering Scrum.&lt;br /&gt;
&lt;br /&gt;
So now my plan is to get back into blogging so perhaps we can expect some stuff about tea and agile development :)</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/4349336810163650270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/04/im-back-lets-see-how-long-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4349336810163650270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4349336810163650270'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2012/04/im-back-lets-see-how-long-for.html' title='I&#39;m back! Let&#39;s see how long for :)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-3313383864825355882</id><published>2010-11-02T01:12:00.000+01:00</published><updated>2010-11-02T01:12:16.898+01:00</updated><title type='text'>Gerrie Knetemann Classic</title><content type='html'>Still catching up on blog posts, I&#39;ve now settled in with a block of stilton, crackers and a pot of honey. Mmm.... not the classic combination of stilton, digestive biscuits and a glass of port but recently I&#39;ve developed a real taste for honey with cheese. I guess most people know that honey works well with goat&#39;s cheese. However, for me a real revelation was tasting a nice mature pecorino with honey blended with truffle oil at my favourite local, Italian wine bar, &lt;a href=&quot;http://www.wijnbardivino.nl/&quot;&gt;Wijnbar Divino&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Anyway, I digress. This post is about cycling (a little). So some friends and I decided to enter a team into the &lt;a href=&quot;http://www.gerrieknetemannclassic.nl/algemeen/&quot;&gt;Gerrie Knetemann Classic&lt;/a&gt;&amp;nbsp;this year. A nice 75km tour around the green heart of Holland. Naturally this meant I needed a new race bike and all the accoutrements, yay :)&lt;br /&gt;
&lt;br /&gt;
So after a bit of research and shopping around I organise a test ride on a &lt;a href=&quot;http://www.stevensbikes.de/2010/index.php?lang=en_US&amp;amp;bik_id=186&quot;&gt;Stevens Aspin&lt;/a&gt; way out on the other side of the water behind centraal station. Believe it or not, this is the first time I&#39;ve taken a ferry over the Ij behind the train station (I&#39;ve lived in Amsterdam for 8 years now!).&lt;br /&gt;
&lt;br /&gt;
And look what&#39;s docked at the ferry terminal on the other side!&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf1qTwf_jp_KhOrHIKubZzlcEZCS4nnVcPrahIacZMNthUrBBDODd6D3ZL-HNEbPQgQHxjuDDsppVMJhGbJMXQZOVB-jcOfN6v_ArKOfvVPVoyo2C_2XhkUP3u0Sbh2J0v5mY-jnAMh_OM/s1600/IMG_0360.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf1qTwf_jp_KhOrHIKubZzlcEZCS4nnVcPrahIacZMNthUrBBDODd6D3ZL-HNEbPQgQHxjuDDsppVMJhGbJMXQZOVB-jcOfN6v_ArKOfvVPVoyo2C_2XhkUP3u0Sbh2J0v5mY-jnAMh_OM/s320/IMG_0360.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Submarine!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;An old Russian submarine... cool! I think it&#39;s been there a while too. It&#39;s been tagged by a local artist :)&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcm9Qs-EjITR6wo4YK2_68W0FlB-qM-jk20hrQhRfJDdRm4lfpiAL62WoURkh-OuTgaSJ8wsdIwQdHEuAqujHBWRFcSjoGKR0el2MMSHew5Bl1CNwTRJoRLuX6fC79jcgJy1Sjt08ZzaXL/s1600/IMG_0357.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcm9Qs-EjITR6wo4YK2_68W0FlB-qM-jk20hrQhRfJDdRm4lfpiAL62WoURkh-OuTgaSJ8wsdIwQdHEuAqujHBWRFcSjoGKR0el2MMSHew5Bl1CNwTRJoRLuX6fC79jcgJy1Sjt08ZzaXL/s320/IMG_0357.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Underwater art?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Anyway, even though it&#39;s raining and it takes some convincing to get the shop to actually let me go out on the bike I make the purchase and get some new cycling gear so i look the part. Just have to pick up the bike the next day from the Haarlemmerstraat shop (couldn&#39;t take it right away as I was on my city bike - but i can walk to their other shop).&lt;br /&gt;
&lt;br /&gt;
A little excited, I head up the next morning on foot and see the cutest thing in a shop window on the way.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6gFQ450fGOsa8pXk9RUDeYK8YBQD4Nj5KyJYn2scLNPJG5Jxt8kQ18zfMJ6t_TMsej2_ykD-ErcBbEkcL3sL9V2Khe1e9UWkg-TWya-O4TVQRAHsJYkEKhF_XeIO1IxQZN5DUlA2vD31W/s1600/IMG_0364.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6gFQ450fGOsa8pXk9RUDeYK8YBQD4Nj5KyJYn2scLNPJG5Jxt8kQ18zfMJ6t_TMsej2_ykD-ErcBbEkcL3sL9V2Khe1e9UWkg-TWya-O4TVQRAHsJYkEKhF_XeIO1IxQZN5DUlA2vD31W/s320/IMG_0364.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Awwww :)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;So sweet, a cat curled up, asleep on top of a big, fluffy teddy bear... in a shop window!! It&#39;s another gloomy, rainy day but it&#39;s hard not to smile at the world sometimes. I snapped a few photos for good measure and headed on to the bike shop.&lt;br /&gt;
&lt;br /&gt;
All&#39;s good and I have the first proper go on my new ride on the 20km commute to the office. Definitely grinning now. For the rest of the week my commutes constitute training for race day.&lt;br /&gt;
&lt;br /&gt;
I&#39;d love to say that it went perfectly but the route was confusingly marked in some places and due to some wildly differing paces our team got a bit split up. A couple of us, thus, ended up taking a couple of wrong turns. At one point following the 100km course for a few kilometres. At the end we&#39;d cycled 80km of a 75km race, oops!&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyYYQ7ZP14BmYjXROXnYx-9ZXiha3NP4PEMFjGap71gckHf7huCsw93edsH-nm7LA5G_vxWbQyWRLhiZK2FsSazpupYZOyquUacvQH3kKwxPJYTsE-kZoKtpWn8r7kqQdH19VyfLOscS4X/s1600/60061_427516372827_562542827_5134161_4861585_n.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyYYQ7ZP14BmYjXROXnYx-9ZXiha3NP4PEMFjGap71gckHf7huCsw93edsH-nm7LA5G_vxWbQyWRLhiZK2FsSazpupYZOyquUacvQH3kKwxPJYTsE-kZoKtpWn8r7kqQdH19VyfLOscS4X/s320/60061_427516372827_562542827_5134161_4861585_n.jpg&quot; width=&quot;213&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Just about to start :)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Next up a great trip to the UK...</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/3313383864825355882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/11/gerrie-knetemann-classic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3313383864825355882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/3313383864825355882'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/11/gerrie-knetemann-classic.html' title='Gerrie Knetemann Classic'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf1qTwf_jp_KhOrHIKubZzlcEZCS4nnVcPrahIacZMNthUrBBDODd6D3ZL-HNEbPQgQHxjuDDsppVMJhGbJMXQZOVB-jcOfN6v_ArKOfvVPVoyo2C_2XhkUP3u0Sbh2J0v5mY-jnAMh_OM/s72-c/IMG_0360.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-7668794307131656596</id><published>2010-11-01T23:31:00.000+01:00</published><updated>2010-11-01T23:31:03.496+01:00</updated><title type='text'>Catching up! Food fest and an important find on a treasure hunt.</title><content type='html'>Been a while since I posted anything here so figured it was time I got my finger out. It&#39;s been a few months of parties, sporting activities and general out-and-about-ness. I&#39;d love to give a full rundown but I think its best to stick to the stuff that&#39;s safe for public consumption ;)&lt;br /&gt;
&lt;br /&gt;
So for this post lets just cover Saturday September 4th. The day of the Haarlemmerstraat Food Festival and the Amsterdam Meetin group treasure hunt. A fine sunny day, I enjoyed a few tasty treats at the food festival in the morning. Some gourmet pizza, some tasty noodles from a Tibetan restaurant&#39;s stall and to top off my lunch a nice, light Pina Colada served in a fresh coconut.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXdsOg2LuIPsXYr_zPiLEEbW1GCEhrOiGi1nE1ISYeUKccsHXJ7AGT42z5jRtxmIULz8PsB0zPIVQwavnvGUyW1CfaPsdZ0238BFfHucBt1zLUslEcqvj-k2XyKNSX2snJ7OaDa81FrXX3/s1600/IMG_0349.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXdsOg2LuIPsXYr_zPiLEEbW1GCEhrOiGi1nE1ISYeUKccsHXJ7AGT42z5jRtxmIULz8PsB0zPIVQwavnvGUyW1CfaPsdZ0238BFfHucBt1zLUslEcqvj-k2XyKNSX2snJ7OaDa81FrXX3/s320/IMG_0349.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Mmm, tasty!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;So i&#39;m walking home with my cocktail when I run into a colleague out with his kids - seriously I&#39;m not usually wandering around amsterdam carrying cocktails with umbrellas and I&#39;m sure this can&#39;t help with my reputation in the office!&lt;br /&gt;
&lt;br /&gt;
The afternoon was fun too, catching up with &lt;a href=&quot;http://www.meetin.org/city/MEETinAMSTERDAM/&quot;&gt;amsterdam meetin group&lt;/a&gt; for a treasure hunt. Good folks and we came second in the final results - winning me a t-shirt. But for me a highlight was coming across this hotel entrance.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMeji_ejf3mwypVRTzbH9cChtu5KK6nYeM87IDzEjp6Hu4EKShTFHURC2vEgrstSyA_ZaqncsBziWqCdPvSrKac_g01rzEfQ1lsYoA3h5OzOR2CAKdYF5y7iQlAxzcaRDXGneiEVajSOXz/s1600/IMG_0353.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMeji_ejf3mwypVRTzbH9cChtu5KK6nYeM87IDzEjp6Hu4EKShTFHURC2vEgrstSyA_ZaqncsBziWqCdPvSrKac_g01rzEfQ1lsYoA3h5OzOR2CAKdYF5y7iQlAxzcaRDXGneiEVajSOXz/s320/IMG_0353.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;A sensible precaution.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Back in February, I was skiing with friends in Switzerland and staying in a very nice hotel between Gstaad and Saanen, the &lt;a href=&quot;http://www.alpinelodge.ch/&quot;&gt;Alpine Lodge&lt;/a&gt;. We had a great stay with great food and wine (most of which we brought with us - but the hotel&#39;s cellar was also very good) and the half in-door, half out-door pool was a great way to relax after a day on the slopes. Less of a highlight though was when I walked into a glass partition in their games room, cutting my eyebrow resulting in some profuse bleeding and a quickly developing black eye. I was concerned that I might need to go to the hospital for stitches and headed for reception to seek a second opinion and a first aid kit. On explaining what had happened the first thing I was asked was, &quot;Is the window damaged?&quot;... Huh? No it wasn&#39;t! Anyway I shall send this picture to them with a note regarding correct health and safety procedures ;)&lt;br /&gt;
&lt;br /&gt;
By the way I have a friend who works at &lt;a href=&quot;http://www.hotelv.nl/hotel_amsterdam/home/&quot;&gt;Hotel V&lt;/a&gt; and by all accounts it&#39;s a very cool place!&lt;br /&gt;
&lt;br /&gt;
So, next up is the Gerrie Knetemann Classic cycle race (ok, more of a tour than a race).</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/7668794307131656596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/11/catching-up-food-fest-and-important.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7668794307131656596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/7668794307131656596'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/11/catching-up-food-fest-and-important.html' title='Catching up! Food fest and an important find on a treasure hunt.'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXdsOg2LuIPsXYr_zPiLEEbW1GCEhrOiGi1nE1ISYeUKccsHXJ7AGT42z5jRtxmIULz8PsB0zPIVQwavnvGUyW1CfaPsdZ0238BFfHucBt1zLUslEcqvj-k2XyKNSX2snJ7OaDa81FrXX3/s72-c/IMG_0349.jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-1707301566229304800</id><published>2010-08-25T17:13:00.002+02:00</published><updated>2010-08-25T17:19:09.086+02:00</updated><title type='text'>VCR Goldmines!</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;br /&gt;
Ok, so I&#39;m at home sick with some lurgy I picked up in London and may not be thinking all that clearly but I wanted to get started on my next electronics project. At the moment the plan is to build a &quot;most useless machine&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;object height=&quot;385&quot; width=&quot;480&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/Z86V_ICUCD4?fs=1&amp;amp;hl=en_US&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/Z86V_ICUCD4?fs=1&amp;amp;hl=en_US&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;480&quot; height=&quot;385&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;br /&gt;
As far as possible I&#39;d like to use recovered parts though. Luckily I&#39;m an accomplished hoarder - I even have difficulty throwing away packaging in case it might be useful.&lt;br /&gt;
&lt;br /&gt;
Now, I&#39;ve read that old VCRs contain a lot of interesting stuff - in particular motors - and what do you know, I have at least 2 sitting around unused upstairs (who uses VCRs these days? I don&#39;t even use DVDs anymore and BlueRay... Pah!).&lt;br /&gt;
&lt;br /&gt;
So here are the little organ donors.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj38rHzNIH0AgkaqW_qSLfLEFDmSPXdmO8NzCjvji6JB9QyQgX2X6Cn-fwMbedHUK2Lk46GXFrKWZIu-WsoPWWPsoX7F8kKZLxgoIwW9DmILjUX9ZtWf4Lj1iMm0yoF6c40W7T-3cFp1o5O/s1600/IMG_0855.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj38rHzNIH0AgkaqW_qSLfLEFDmSPXdmO8NzCjvji6JB9QyQgX2X6Cn-fwMbedHUK2Lk46GXFrKWZIu-WsoPWWPsoX7F8kKZLxgoIwW9DmILjUX9ZtWf4Lj1iMm0yoF6c40W7T-3cFp1o5O/s320/IMG_0855.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Lookin&#39; Sharp, eh ;)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWx17YyI-rVACSOVV_Y4JGfrb_kem5eKmZvToXzQYiV-j5Y-Linv1Yeza-UgBuaKK4nr1-baxxw_C-OKUVV7FTUV4bxxFzWHlmlxbMHWyz3653WmPIbs5NAZaDHWHc2c6MaKF4xnlI_klx/s1600/IMG_0856.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWx17YyI-rVACSOVV_Y4JGfrb_kem5eKmZvToXzQYiV-j5Y-Linv1Yeza-UgBuaKK4nr1-baxxw_C-OKUVV7FTUV4bxxFzWHlmlxbMHWyz3653WmPIbs5NAZaDHWHc2c6MaKF4xnlI_klx/s320/IMG_0856.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Don&#39;t worry, it&#39;s just a routine procedure...&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;And in case anyone&#39;s interested, you might be able to make out model numbers in these pics.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoYw7_HmOj8jDIO4_uIeXr5DtYZmvMegATUaNCGHWw2idnov9JgdVwROUrEOca_kegBUo0_oZRc9kInb3z0kSdCPUExq-8SoX2-kt-qqIFJRMrukucqjAwsMLxHY59elzWw48Bf4rxpPCG/s1600/IMG_0861.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoYw7_HmOj8jDIO4_uIeXr5DtYZmvMegATUaNCGHWw2idnov9JgdVwROUrEOca_kegBUo0_oZRc9kInb3z0kSdCPUExq-8SoX2-kt-qqIFJRMrukucqjAwsMLxHY59elzWw48Bf4rxpPCG/s320/IMG_0861.jpg&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaotAcoNKcXCe-C4ITyLPfoIF8nCLn_fQcTIgsKLjJLiwh0vegc_U0FLpWpOdSS8qLifo2E517DqQeLmUmHHG2Q1B4LmS6FmPhVpmhqsQ84vKweSSNl4EIScmfBGCF9LSk5QRfdVtsMf4g/s1600/IMG_0862.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaotAcoNKcXCe-C4ITyLPfoIF8nCLn_fQcTIgsKLjJLiwh0vegc_U0FLpWpOdSS8qLifo2E517DqQeLmUmHHG2Q1B4LmS6FmPhVpmhqsQ84vKweSSNl4EIScmfBGCF9LSk5QRfdVtsMf4g/s320/IMG_0862.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
First up is the Panasonic so out comes the screwdriver...&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu6PYVSlw1H9hdit50sPJHJOj25TswlRO2B78HKbdpNCcjrWR2wTch48E2OgMEdBghY0sWAWMC4WHzpc205i1YWSlyoZEwMIciPO79-g2Gj0KDaITznvEMEmH6TqS43k-8gIUk2t26fQto/s1600/IMG_0869.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu6PYVSlw1H9hdit50sPJHJOj25TswlRO2B78HKbdpNCcjrWR2wTch48E2OgMEdBghY0sWAWMC4WHzpc205i1YWSlyoZEwMIciPO79-g2Gj0KDaITznvEMEmH6TqS43k-8gIUk2t26fQto/s320/IMG_0869.jpg&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Oh la la, naked!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilAAR7EvFCh2w2ifDEI3h_u3sQmbiflIodlP2lBh6wi_mmHxMhkVJpbAo0hRKCE49UBt85yL1qc6xLvx144Coi2K8RtsGv9mRf4_tzVazySLuwSOHKKBkIEiAGQeVythA3jbyWiOAo73qF/s1600/IMG_0870.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilAAR7EvFCh2w2ifDEI3h_u3sQmbiflIodlP2lBh6wi_mmHxMhkVJpbAo0hRKCE49UBt85yL1qc6xLvx144Coi2K8RtsGv9mRf4_tzVazySLuwSOHKKBkIEiAGQeVythA3jbyWiOAo73qF/s320/IMG_0870.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;And there&#39;s a tape in it - probably just porn!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXw_c39oqmqF6irSC9jIbKDzgYQONo5SZvFOcbtNT3_ytfiDkyz1tqwTXXggrQxiDcdczgvkCm7nD9-RKn2JjoY7Ptkm7DLHBHzUcdLBswxsp4hlcCU02SIZThkUdCniqNC9Hwx_ILE3zG/s1600/IMG_0873.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXw_c39oqmqF6irSC9jIbKDzgYQONo5SZvFOcbtNT3_ytfiDkyz1tqwTXXggrQxiDcdczgvkCm7nD9-RKn2JjoY7Ptkm7DLHBHzUcdLBswxsp4hlcCU02SIZThkUdCniqNC9Hwx_ILE3zG/s320/IMG_0873.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Now things are looking interesting - this spinning drum both&lt;br /&gt;
&amp;nbsp;reads and writes magnetic tape - magic!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Ok, so I run into a slight hitch here as something is broken and when I try powering up and ejecting the tape nothing happens. I&#39;ll figure that out later but for now I can turn my attention to the Sharp...&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPBAQtxDxAwMxwu3LWZQSCvyYSFtVl0LnGCZkNvaPfrVd491rQclqguZl-XtJGMG1vIPir8qPtY_-x0-hozEDFbbFbAcc22a0q7_Fe87qiof_9c7YdbBHPW2YY3SIxLAHOtvZOha5L91a-/s1600/IMG_0877.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPBAQtxDxAwMxwu3LWZQSCvyYSFtVl0LnGCZkNvaPfrVd491rQclqguZl-XtJGMG1vIPir8qPtY_-x0-hozEDFbbFbAcc22a0q7_Fe87qiof_9c7YdbBHPW2YY3SIxLAHOtvZOha5L91a-/s320/IMG_0877.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;More brazen nudity!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXkLxmq2_5j5e7M95kPp-w1LpTS7Z6g-XqOuiAIqpOtpu1XqLLigju3H1-amrT6qoXtlOl-YtQa4XRcclWWTxccVfe_LTF76S5Q5Jfj10kzyZ8sGp414UmnT9TFLLnhx1Yf1zhR4WRZPU4/s1600/IMG_0882.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXkLxmq2_5j5e7M95kPp-w1LpTS7Z6g-XqOuiAIqpOtpu1XqLLigju3H1-amrT6qoXtlOl-YtQa4XRcclWWTxccVfe_LTF76S5Q5Jfj10kzyZ8sGp414UmnT9TFLLnhx1Yf1zhR4WRZPU4/s320/IMG_0882.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;I have the Power! (supply)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB9ZRXqNJ1c6_SKowosrz0nQQIIR-YyWnBA9h_vdzutbDoofBr5g9hQwD6J5flX7lG2dGNQVqE9Bbv9qj0kZ_pwNo1OVd4xOqtSmGdPC3NIA_2ZQuHY12Kw1-JyPywgrMInn_2HGy8kLmx/s1600/IMG_0891.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB9ZRXqNJ1c6_SKowosrz0nQQIIR-YyWnBA9h_vdzutbDoofBr5g9hQwD6J5flX7lG2dGNQVqE9Bbv9qj0kZ_pwNo1OVd4xOqtSmGdPC3NIA_2ZQuHY12Kw1-JyPywgrMInn_2HGy8kLmx/s320/IMG_0891.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Skipping forward a bit - how&#39;s that for a nice pile of... erm... useful things?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Well, that was pretty easy and i now have all sorts of potential project parts: motors; gears; pulleys; modulators and demodulators; power supply; magnetic read/write thingy... Awesome!&lt;br /&gt;
&lt;br /&gt;
Back to the panasonic then...&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFiAiof1Rcmxb-010feAQz4PZ7pv7tUGgkbfsIkUTqWJ39nUnpj2Y8VAatABbDeyStXh4p-cRcdeGFuAHWdJ4DrCv9Lg7D0_9V6WFpZyS4PqKl2dEke8OoJZsMF_tMJijFpjAzY9QAJUjm/s1600/IMG_0892.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFiAiof1Rcmxb-010feAQz4PZ7pv7tUGgkbfsIkUTqWJ39nUnpj2Y8VAatABbDeyStXh4p-cRcdeGFuAHWdJ4DrCv9Lg7D0_9V6WFpZyS4PqKl2dEke8OoJZsMF_tMJijFpjAzY9QAJUjm/s320/IMG_0892.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Probably the most interesting pieces all come out as 1 unit - will want&lt;br /&gt;
&amp;nbsp;to take a closer look at this before ripping it apart :)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Seems the Panasonic is built in a much more modular fashion and with many fewer screws. In fact, things seem to have been snapped together like a big interlocking puzzle. This makes it a little tougher to dismantle without applying a modicum of force resulting in some small pieces of broken plastic - nothing to be concerned about though.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3IBSUdQofS9pw-2K1Q2dfwIvXPv-JVczXx-8DDFoixIX8SuOVQIJZ6CabVZjC8CpHbBOsHVSw7G9e40nsY6DL04mWusOum8rmpP5B9RVjvpdmRCIZB9i03jlvUatkuqysDqIdKinMAwrQ/s1600/IMG_0896.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3IBSUdQofS9pw-2K1Q2dfwIvXPv-JVczXx-8DDFoixIX8SuOVQIJZ6CabVZjC8CpHbBOsHVSw7G9e40nsY6DL04mWusOum8rmpP5B9RVjvpdmRCIZB9i03jlvUatkuqysDqIdKinMAwrQ/s320/IMG_0896.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Hmm, main board doesn&#39;t seem to be held in with screws...&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiF2uuR_Q6AgGUgJJlPRsEN24r7DkQ8WVxIPxnwqOY9wftJxBjiLu0S8kYa1qYNCSMtHxyazESYhYRFQf1leurE9iwQl3QvdVl-LVk6rZKuZfzkCJRmIgApKIL3uYIckEHBBjGo69T8oPO/s1600/IMG_0897.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiF2uuR_Q6AgGUgJJlPRsEN24r7DkQ8WVxIPxnwqOY9wftJxBjiLu0S8kYa1qYNCSMtHxyazESYhYRFQf1leurE9iwQl3QvdVl-LVk6rZKuZfzkCJRmIgApKIL3uYIckEHBBjGo69T8oPO/s320/IMG_0897.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;... careful and strategic application of brute force does the job!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8qOG69KjAdZzKet9jrrPz3QqBYBULdynMOV1KHpc-sIBv1jIREaUw-ifvF5mTqxMPKqHnaM7rmiMm8zITrp7Tgm4hK6aR0YPQI76RX7NSePDW6iKJYUge-TysYSymieGP273-cw80EGx/s1600/IMG_0900.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8qOG69KjAdZzKet9jrrPz3QqBYBULdynMOV1KHpc-sIBv1jIREaUw-ifvF5mTqxMPKqHnaM7rmiMm8zITrp7Tgm4hK6aR0YPQI76RX7NSePDW6iKJYUge-TysYSymieGP273-cw80EGx/s320/IMG_0900.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Nice, another interesting looking power supply :)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;So, I&#39;ve got 2 interesting piles of parts now and I&#39;ve already had a go at applying power to the Panasonic&#39;s eject mechanism - wondering if it can form a part of my &quot;most useless machine&quot; - and the motor still works. So the previously encountered eject issue will likely be inconsequential :)&lt;br /&gt;
&lt;br /&gt;
That&#39;s it for now, further updates to follow I&#39;m sure. In the meantime... why are you reading this! Seriously if you got this far we need to talk - I think you may have issues ;)&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/1707301566229304800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/08/vcr-goldmines.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1707301566229304800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/1707301566229304800'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/08/vcr-goldmines.html' title='VCR Goldmines!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj38rHzNIH0AgkaqW_qSLfLEFDmSPXdmO8NzCjvji6JB9QyQgX2X6Cn-fwMbedHUK2Lk46GXFrKWZIu-WsoPWWPsoX7F8kKZLxgoIwW9DmILjUX9ZtWf4Lj1iMm0yoF6c40W7T-3cFp1o5O/s72-c/IMG_0855.JPG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6900110617341786018.post-4304644265532079528</id><published>2010-08-23T23:41:00.000+02:00</published><updated>2010-08-23T23:41:42.454+02:00</updated><title type='text'>Polo, canal concerts and a little shopping fun</title><content type='html'>&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;It&#39;s been a busy weekend for me.&amp;nbsp;&lt;a href=&quot;http://www.sail2010.nl/&quot;&gt;Sail 2010&lt;/a&gt;&amp;nbsp;was in town but i didn&#39;t really see much of that. I saw a few ships when travelling in and out of town - I&#39;m just not sure it&#39;s very exciting unless you get to have a go with them. Plus it&#39;s very busy and I&#39;m not a big fan of crowds!&lt;br /&gt;
&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;So what I actually did on Saturday was book myself in for a&amp;nbsp;&lt;a href=&quot;http://learn.polo.nl/&quot;&gt;polo clinic in Wassennaar&lt;/a&gt;. Now, I can&#39;t claim to be the greatest horseman in the world. In fact I only started learning to ride last August and hadn&#39;t been on a horse since December. Plus all my experience so far has been in an arena, learning dressage. I&#39;ve decided dressage is quite boring!&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;That said, I&#39;m not averse to a little danger. I like to ride my bike to work in all weathers - even in blizzards and on snow and ice. One of the reasons I haven&#39;t been on a horse this year till now is that I broke my collar bone learning to ski earlier this year - but that&#39;s cool now as they put me back together with titanium :)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;So when friends suggested that polo possibly&amp;nbsp;wasn&#39;t the safest thing for an accident prone chap to do, that really just made me grin and want to do it more.&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;My main worry was that they would take one look at me and realise what kind of horseman I was and not let me near any of the ponies! However, it did say on the website that no previous riding experience was required (this made me suspicious that we would just be spending 2 hours on a wooden horse but the course summary suggested not).&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;So it turns out that the polo club is a lot more relaxed than the manege I go to for dressage lessons. An amusing indication was when we were told that it wasn&#39;t necessary to have special insurance to play polo as the polo association in the Netherlands had resisted having polo classified as a sport!&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Anyway things start out with a quick presentation about polo. Karin the club manager gave this (and the rest of the clinic) but from some slides prepared by someone else - I&#39;m not sure she&#39;d seen them before to be honest. The first few were skipped through disinterestedly and can be summarized thusly - polo is posh, you need lots of horses and sometimes elephants, lots of champagne gets drunk at polo matches and polo is posh (I kinda knew this - but it still looks fun so I don&#39;t care)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Next were some slides about the 3 or 4 clubs in the Netherlands and the 3 or 4 major polo events (I actually went to the &lt;a href=&quot;http://www.amsterdampolotrophy.com/&quot;&gt;Amsterdam Polo Trophy&lt;/a&gt; last year in the Bos - it&#39;s free and quite fun and yes a lot of champagne was drunk).&amp;nbsp;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxtSFq-I1tbaIXAxJKkLv0Qj7rXnCqa-z-ReULyJlVhNsIAkmv10c0l9_gQCSjctySPTHmyC4SOGzqWfXQo7e5vxoQWCtzwvPhRZwBVL1FRdW-pGpafTGz8WybkJWiwftMdqrPjcF-7rt-/s1600/IMG_0019.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxtSFq-I1tbaIXAxJKkLv0Qj7rXnCqa-z-ReULyJlVhNsIAkmv10c0l9_gQCSjctySPTHmyC4SOGzqWfXQo7e5vxoQWCtzwvPhRZwBVL1FRdW-pGpafTGz8WybkJWiwftMdqrPjcF-7rt-/s320/IMG_0019.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Amsterdam Polo Trophy, 2009&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Then there were some slides about horses and rules and stuff - naturally this went in one ear and out the other as by this point I just wanted to start hitting balls with mallets!&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;We start out with little tiny mallets practicing stood on the ground - Karin has to remind me that it&#39;s not golf and that the ball will be to the side of me when I&#39;m sat on a horse. Still this isn&#39;t so tough and we&#39;re soon smashing oddly shaped balls all over the place (polo balls are not exactly perfect spheres, they seem to have flattened sides which I don&#39;t think can only be explained by having been hit around - i was going to ask about this but forgot). Of course then we have to go wander around to collect the balls as next we will try the same thing with full size mallets while standing on plastic patio chairs!&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;We practice a few different shots. The mallet is always held in the right hand so there are basically 4 standard strokes - forehand on the right side (goes forward), backhand on the right side (goes backward), forehand on the left side (involves leaning over to the other side and hitting backward) and the backhand on the left side (again leaning around and this time hitting forward). The bigger mallets are much heavier! It quickly becomes apparent that you need to control the momentum - again this is a little like golf and it&#39;s necessary to let the mallet follow through in a natural arc as trying to stop it is pretty tough on the old arm. You see experienced players actually swing the mallet through in full circles after making hits to release the energy. So after some practice on these shot types it&#39;s time to grab some ponies :)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;There are 5 of us there for the clinic but unfortunately only 3 ponies available so we&#39;ll have to take turns practicing while mounted. Karin asks who wants to be first and as is natural when volunteers are asked for, no one wants to stick there hand up... well except me :) So when it&#39;s noticed that 2 others also have their hard hats on already we have our first 3 volunteers and it&#39;s off to the stables.&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2tH8sKAQSgz54gN0-4kdK8nAD-3wMp0FxdeZMu_1jFwn1JCs8z17CAefu3jmaxnEa9ik4YtLGe2mHqIaJAZjBRRUVKlI4feXX8MOl7D9X5yrXfdXDSnDdCI3Yn2qedf32G9rw04SmDlzN/s1600/IMG_0843.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2tH8sKAQSgz54gN0-4kdK8nAD-3wMp0FxdeZMu_1jFwn1JCs8z17CAefu3jmaxnEa9ik4YtLGe2mHqIaJAZjBRRUVKlI4feXX8MOl7D9X5yrXfdXDSnDdCI3Yn2qedf32G9rw04SmDlzN/s320/IMG_0843.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;OMGPonies!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Phew, I haven&#39;t forgotten everything and the pony I get is great (pictured above). She actually listens to me and is not the slightest bit twitchy - I feel bad that I can&#39;t remember her name but hey, I&#39;m a guy ;)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Polo ponies are pretty cool, you have to give big signals as they&#39;re used to having their riders moving around a lot on top of them. They also get confused if you hold the reins with 2 hands so you have to stick to just the left hand. But once you get going they are very responsive, changing direction and speed very quickly (starting to sound like an auto review!) :)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;I&#39;d love to say that I was charging around smashing balls all over the place but the reality is I was mostly walking and trying to line up my shots. There was some trotting and even a little cantering but i&#39;m not sure I actually made contact with the ball except while walking. I Don&#39;t have any pictures of myself on the horse so this blurry picture of one of my fellow students will have to do (I really have to work on my photography skills!).&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnUqb_YDBVV9tkYab1DwKRo_xFPgh-IDRkot2SM30iqZ8GPd7xBuO0PpmJ7bVchct2dJdd5LgyS0pyMYNeOaZOXlxtXlszPTaXMYFER0xmFtL_h7X3xSUBcpHVBZ6WNTDB6lB5Gb4s7v-/s1600/IMG_0845.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnUqb_YDBVV9tkYab1DwKRo_xFPgh-IDRkot2SM30iqZ8GPd7xBuO0PpmJ7bVchct2dJdd5LgyS0pyMYNeOaZOXlxtXlszPTaXMYFER0xmFtL_h7X3xSUBcpHVBZ6WNTDB6lB5Gb4s7v-/s320/IMG_0845.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;I think she missed :o&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;This is great fun and i&#39;m soon tired and hand my pony over to someone else to have a go but after a short while I get to have another go myself on a different pony (actually the one pictured above again). Don&#39;t remember the name of this one either (it was probably something dutch sounding) but she seems to be a lot more highly strung than the first. She definitely won&#39;t stay still as I mount her and once on I obviously pulled a little tightly on the reins as she walks backward into one of the plastic patio chairs. At first I&#39;m not sure what&#39;s going on as she&#39;s jumping around and feels like she&#39;s about to rear up (apparently it looked that way from the ground too). I feel really bad when I realise she has a leg stuck in a chair and is trying to shake it off, not really sure what i can do to help so I just loosen the reins and make sure I don&#39;t fall off. Thankfully she clears the chair eventually and doesn&#39;t appear to be injured! We have a gentle walk and trot round and I hit very little as the legs and arms are now tired (you have to stand up in the stirrups and lean over to hit the ball which is both tricky and quite hard work after a while).&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;So that was my introduction to polo and I enjoyed it a great deal - I just wish it wasn&#39;t so pricey. The 2 hour clinic (which actually lasted a little longer I think) was €150 which I think is roughly 3 times the price of dressage lessons but then maybe 3 times the fun too :)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;What else then. Well after such a nice afternoon there was a pleasant evening back in Amsterdam. As well as Sail 2010 the &lt;a href=&quot;http://www.grachtenfestival.nl/&quot;&gt;Grachtenfestival&lt;/a&gt; has been going on all week culminating in a concert on the Prinsengracht outside the Pullitzer hotel. Debussey, some opera and a pianist playing on a temporary stage floating in the canal surrounded by Amsterdammers in their boats and many others crowded on the bridges and the sides of the canal.&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ2mQMRsqeCVNtRwk23QEtxbpmwbdwICnGAuY3HBV25dxP8bxKVSqoM9hGxT6-n7Ai_P4VQVOtckCParAhdXyJqdSOFYb5rsVYa8os-MmsVZ9jYbSxrb7J0fzoIeIDb6EpJK3kAyozWBJQ/s1600/IMG_0345.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ2mQMRsqeCVNtRwk23QEtxbpmwbdwICnGAuY3HBV25dxP8bxKVSqoM9hGxT6-n7Ai_P4VQVOtckCParAhdXyJqdSOFYb5rsVYa8os-MmsVZ9jYbSxrb7J0fzoIeIDb6EpJK3kAyozWBJQ/s320/IMG_0345.JPG&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;There&#39;s a canal under there somewhere&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;As I mentioned earlier, I&#39;m not a big fan of crowds but it&#39;s nice to watch for an hour or so before my friend and I nip down the road for a few glasses of wine at &lt;a href=&quot;http://www.vyne.nl/&quot;&gt;Vyne&lt;/a&gt;. I enjoyed some very nice Puilly Fume and some Meersault while still able to hear most of the concert in the background. Life is good and it turns into a late night after another friend joins us :)&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;Monday now (Sunday was a blow out as I developed a chest infection that I think I caught visiting the London office Thursday and Friday) and I needed to visit the supermarket (still suffering and home from work). So remembering my &lt;a href=&quot;http://stuffpetedoes.blogspot.com/2010/08/stupid-shopping-game.html&quot;&gt;shopping list fun&lt;/a&gt; here&#39;s what I dropped off - paying homage to the double rainbow meme.&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdzm-BqvYAQVxx69k8nL5Or1F9ZL4lFw3LNkj03imW7iwALH22D2SRxDXASkhakOdy77McsA7fSyOMhGk__MzIwB01R8n55PN1Iw4nSxvt5lg9mP3RHV2kOUj55iyZLEHpSeRTvt76Q1vG/s1600/IMG_0852.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdzm-BqvYAQVxx69k8nL5Or1F9ZL4lFw3LNkj03imW7iwALH22D2SRxDXASkhakOdy77McsA7fSyOMhGk__MzIwB01R8n55PN1Iw4nSxvt5lg9mP3RHV2kOUj55iyZLEHpSeRTvt76Q1vG/s320/IMG_0852.jpg&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Albert Heijn, Elandsgracht, 23rd August 2010, 1500&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stuffpetedoes.blogspot.com/feeds/4304644265532079528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/08/polo-canal-concerts-and-little-shopping.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4304644265532079528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6900110617341786018/posts/default/4304644265532079528'/><link rel='alternate' type='text/html' href='http://stuffpetedoes.blogspot.com/2010/08/polo-canal-concerts-and-little-shopping.html' title='Polo, canal concerts and a little shopping fun'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/04252795506872923952</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxtSFq-I1tbaIXAxJKkLv0Qj7rXnCqa-z-ReULyJlVhNsIAkmv10c0l9_gQCSjctySPTHmyC4SOGzqWfXQo7e5vxoQWCtzwvPhRZwBVL1FRdW-pGpafTGz8WybkJWiwftMdqrPjcF-7rt-/s72-c/IMG_0019.JPG" height="72" width="72"/><thr:total>0</thr:total></entry></feed>