<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='rssxsl.xslt' version='1.0'?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>secretGeek</title> 
<link>http://secretGeek.net/index.asp</link> 
<description>secretGeek - dot Nuts about dot Net!</description> 
<copyright>Copyright 2007 Leon Bambrick</copyright>
<language>en-au</language> 
<managingEditor>LeonBambrick@NoSpamGMAIL.com (Leon Bambrick)</managingEditor> 
<webMaster>LeonBambrick@NoSpamGMAIL.com (Leon Bambrick)</webMaster>
<atom:link href="http://secretGeek.net/rss.asp" rel="self" type="application/rss+xml" /> 
<image>
<title>secretGeek</title>
<url>http://secretGeek.net/secretgeek2_noT.gif</url>
<link>http://secretGeek.net/index.asp</link>
<width>49</width>
<height>33</height>
<description>secretGeek - dot Nuts about dot Net!</description> 
</image>
<item>
  <title>A Computer Simulation of Creative Work, or 'How To Get Nothing Done'</title>
    <link>http://www.secretGeek.net/pathos.asp</link>
    <description>
      <![CDATA[<blockquote>
<p>
Every year is getting shorter, never seem to find the time<br />
Plans that either come to naught or half a page of scribbled lines<br />
</p>
<footer><a href='http://en.wikipedia.org/wiki/Time_(Pink_Floyd_song)'>Time</a>, Pink Floyd</footer>
</blockquote>

<p>According to the available data, I'm a hard-working and creative person. Yet my productive output tends to hover just above nil. My feelings are generally in line with Roger Water's lyric, quoted above. Why? What causes the gap between work and productivity? But more importantly: can a computer simulation shed light on the underlying problem?</p>
<p>I set about modelling my personal productivity, with javascript and <a href='http://www.flotcharts.org/'>flot</a>.</p>
 
<p>Here's how the model works:</p>
<blockquote>
<p>Every <a href='http://secretgeek.net/code_commute.asp'>bus</a> trip I work and work and work, always on what is the most pertinent task for the project I am working on.</p>
<p>But as I work, I sometimes think of new projects. I immediately (and at no cost) add those projects to my backlog, then continue with my current task.</p>
<p>As soon as I finish a task, I look over my set of all next actions and choose whichever one feels most interesting at that point in time (modelled as a random selection)</p>
</blockquote>
<p>You can play with this simulation yourself:</p>
<br />
<p><a href='http://secretGeek.net/pathos/' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Creative Dilligence Simulator</a></p>
<br />

<p>The parameters are configurable. By default each project contains 10 tasks (these are mini-projects really). And each time I do a task there is a 25% chance I'll think of a new project.</p>
<p>The results of the simulation are woeful!</p>
<p>Here's an example:</p>
<img src='http://secretGeek.net/image/pathos_200r.png' style='margin:20px'/>
<p>After a year of bus trips, I've done enough hard work that I could've completed 20 projects. Instead I've only finished only 2 (emphasized by the green arrow). Re-running it, I sometimes complete as many as 3 or as little as 0. Meanwhile my backlog of work is big enough to keep me busy for years to come.</p>
<p>As simplistic as the model is, it already makes me feel uncomfortable with its home truths. I know this feeling all too well. Hard work, but it's like spinning your wheels while stuck in mud. I know that my time is spent always on tasks I consider worthwhile, yet I'm still getting nothing done.</p>

<p>Here's the shocking thing. This low productivity is not caused by all the usual culprits we list when discussing 'procrastination'. This isn't because of low motivation or excessive distraction. This isn't because of fear (the alleged mind killer) -- it's not fear of shipping, fear of criticism, fear of success, or any other paralysing phobia.</p>

<h2>Getting 'Things' Done versus Getting 'Projects' Done</h2>
<p>This is the difference between utilization and productivity. High utilization can be just busy work.</p>
<p>This is purely organisational pathology, and 100% curable.</p>
<p>The immediate question is what to do about it. Now the modelling becomes fun.</p>
<p>If I can decrease my ability to think of new projects, down to around 10 percent (approximately 1 new project idea for 10 tasks done), then I manage to ship more projects.</p>
<img src='http://secretGeek.net/image/pathos_200r_10.png'  style='margin:20px'/>
<p>At the end of the year I've now completed between 8 and 20 projects. Yay. But now a new problem arises: I frequently run out of work to do. Many bus trips I just sit there, twiddling my thumbs, staring out the window. For me, that's a terrifying prospect, a sort of waking death. But in any case, I think it's outside my control. This continual thinking up of new projects (albeit <a href='http://dod.codeplex.com'>stupid STUPID projects</a>) is just a fact of life. You might as well ask a cat to stop following a laser pointer.</p>
<p>The trick instead is to come up with a new strategy for picking tasks. When I finish one task and it's time to move onto another, I need to be far more careful about which task I work on next. </p>
<p>So I implemented a strategy called 'stick to a project'. In this strategy, I keep working on my current project until that project is done. The results are much more satisfying. I still end up with a giant backlog of work -- but the amount of projects that I've shipped is now exactly in line with the effort I've put in.</p>
<img src='http://secretGeek.net/image/pathos_200s.png'  style='margin:20px'/>

<br />
<br />
<p>That's all I needed to get out of the model -- and at this point I can stop modelling and return to doing.</p>
<p>But it's also just the tip of what the model shows you. Different people have different fears and different desires. Depending on your personal preferences different results are optimal. You might be driven by any of these:</p>
<ul><li>Fear of drowning in work (minimize backlog)</li>
<li>Fear of running out of work (maximize backlog)</li>
<li>Love of a big backlog  (maximize backlog)</li>
<li>Hate working on the same thing all the time (continual switching)</li>
<li>Fear of negative feedback after releasing work (minimize project completion)</li>
<li>Desire to release work constantly (maximize project completion)</li>
</ul>
<p>Play with the numbers, you'll see how to get what you want. Or copy the code and change the model to reflect your own behaviour.</p>

<p>That link again:</p>
<p><a href='http://secretGeek.net/pathos/' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Creative Dilligence Simulator</a></p>

<br />

<h2>Models are not reality</h2>

<p>In practice, things get a lot messier. Projects have variable sizes. Projects grow as you work on them. Some projects *should* be abandoned, not stuck to. (<em>If a job's not worth doing, it's not worth doing properly</em>). 
<p>The model is very simple but it was complex enough to demonstrate something useful to me, so I'm happy to publish this as is.</p>
<p>Now I must get back to the gormless and unstoppable implementation of whatever addle-brained scheme has floated to the top of my steaming heap of incomplete mini-projects. Wish me well.</p>
]]>
    </description>
    <pubDate>Mon, 06 May 2013 12:46:15 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/pathos.asp</guid>
  </item>
<item>
  <title>NimbleText 1.9 -- BoomTown!</title>
    <link>http://www.secretGeek.net/nt_19.asp</link>
    <description>
      <![CDATA[<p>I put out a new <a href='http://NimbleText.com/'>NimbleText</a> a few days ago.</p>
<p>The release notes are <a href='http://NimbleText.com/Version/Notes#1.9.0.35134'>here</a>, but do you want the minutely-detailed and wildly self-indulgent story <em>behind</em> the release notes? Of course you do!</p>

<p>Along with a spattering of smaller improvements, the main innovation is that you can now expose your settings (and quickly change them) from the toolbar.</p>

<p>I wanted this for a while, but couldn't find the right way to let the user configure it. Finally, with inspiration from Windows 7, I came up with using a pin/unpin metaphor, inside the Options form, like so:</p> 
<img src='http://secretGeek.net/image/nt_options_pin.png' style='margin:20px'/>

<p>Coming up with this design was surprisingly difficult. Some of the designs I rejected were:</p>
<p>Some people asked for a "view" menu where you check or uncheck the options you want to have appear on the toolbar. Here's a quick mockup:</p>
<img src='http://secretGeek.net/image/nt_options_viewmenu.png' style='margin:20px'/>
<p>This concept was broken for two reasons.</p>
<p>First, it looks like you're turning the option itself on or off -- not turning on whether or not the option is shown in the toolbar.</p>
<p>Second,  if you were to click one of those menu items, thus toggling its checked state, this would also have the undesirable side effect of closing the menu. So if you wanted to show or hide three settings you'd need to re-open the menu three times, for a total of six-clicks. Annoying behavior! (Incidentally my <a href='http://TimeSnapper.com/NextAction'>NextAction</a> tool suffers this problem, embedding so many settings in deeply-nested context menus that collapse whenever you click them. Overriding this behaviour is problematic!)</p>
<p>So the new plan was to put checkboxes of some sort inside the Options form, adjacent to each option. But take a look at <em>this</em> mockup:</p>

<img src='http://secretGeek.net/image/nt_options_pincheck.png' style='margin:20px'/>
<p>Again it's easy to think that clicking the new checkbox will cause the option to be turned on. I wasn't going to implement this or anything like it. Then I noticed the way application icon pinning works in Windows, from 7 onwards.</p>

<img src='http://secretGeek.net/image/nt_pin.png' style='margin:20px'/>

<p>It's an elegant solution, maybe the nicest touch in Windows since they <a href='http://secretgeek.net/ms_search.asp'>shot the dog</a>.</p>
<p>So I had my big-chief-graphic-design-intern (i.e. Me) whip out a dodgy mockup, ran it over to my main opinion-deflection-test-subject (i.e. <a href='http://i-think22.net/'>Rhys</a>) and after a few short bursts of shouting the project was green-lighted and implementation began.</p>
<p>Here's the mockup with which I got approval from the board:</p>

<img src='http://secretGeek.net/image/nt_options_pinmockup.png' style='margin:20px'/>

<p>If it seems weird to agonize over a small feature like this, I could point out not only a <a href='http://secretgeek.net/ts_sghetti.asp'>long</a> <a href='http://secretgeek.net/readonly_gray.asp'>history</a> of <a href='http://www.secretgeek.net/merc_hints.asp'>such</a> behavior from myself, but also I can provide evidence that i'm a bit of a toolbar fetishist, having written 6 articles on the topic previously:</p>

<ul>
<li><a href='http://secretgeek.net/vs_toolbar_st.asp'>Rethinking Toolbars in Visual Studio (or any IDE)</a></li>
<li><a href='http://secretgeek.net/Too_Many_Arrows.asp'>Too Many Damn Arrows in VS.Net!</a></li>
<li><a href='http://secretgeek.net/diffmerge_UX.asp'>Suggested User Experience Improvements for DiffMerge</a></li>
<li><a href='http://secretgeek.net/qt_shortcuts_vs.asp'>Quick Tip: Show Shortcut Keys in Visual Studio</a></li>
<li><a href='http://secretgeek.net/KeyTraino.asp'>KeyTraino</a></li>
<li><a href='http://secretgeek.net/metanote_1.asp'>Your next text editor is... MetaNote!</a>
</ul>


<p>What UX have you agonised over lately?</p>
]]>
    </description>
    <pubDate>Sat, 20 Apr 2013 00:47:27 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/nt_19.asp</guid>
  </item>
<item>
  <title>Line Endings.</title>
    <link>http://www.secretGeek.net/lineendings.asp</link>
    <description>
      <![CDATA[ 
<img src='http://secretGeek.net/image/LineEndings.png' alt='3 people arguing over line endings.' style='margin:20px'></img>

<p>I had a lengthy article here -- browsers, typewriters, javascript blah blah blah, cultural tolerance to backward incompatability in Mac and Microsoft worlds, blah blah blah -- but really, the <a href='http://www.hanselman.com/blog/YoureJustAnotherCarriageReturnLineFeedInTheWall.aspx'>Hanselman pretty much beat me to it</a>, and all I've got left is a cartoon.</p>


<p><small>((As a derivative of <a href='http://www.emacswiki.org/emacs/TabsSpacesBoth'>a GPL'd work ("Tabs."|"Spaces."|"Both.")</a>,) The above image is licensed to you under version 2 of the <a href="http://www.gnu.org/">GNU</a> <a href="http://www.emacswiki.org/GPL">General Public License</a>.)</small></p>
]]>
    </description>
    <pubDate>Mon, 15 Apr 2013 10:39:23 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/lineendings.asp</guid>
  </item>
<item>
  <title>**This** is how you pivot</title>
    <link>http://www.secretGeek.net/piranha_pivot.asp</link>
    <description>
      <![CDATA[ 
<p>Startups love to talk about 'Pivoting' -- those sudden changes in strategy, right angle turns that take you from obscurity to success.</p>

<p>"Burbn" pivoted from a location-checkin app to a stylized photo sharing app and became billion-dollar company, Instagram!</p>
<img src='http://secretGeek.net/image/Doug_and_Dinsdale Piranha.png' style='border:1px solid #BBB;background-color:white; padding:20px;margin-left:20px;margin-top:0px;margin-right:5px;float:right;' alt='Doug and Dinsdale Piranha' />

<p>But to find the masters of pivoting, we need look no further than the monty python sketch, <a href='http://www.montypython.net/scripts/piranha.php'>the piranha brothers</a>. This is pivoting done *right*!</p>

<blockquote><p>
At the age of fifteen Doug and Dinsdale started attending the Ernest Pythagoras Primary School in Clerkenwell. When the Piranhas left school they were called up but were found by an Army Board to be too unstable even for National Service. Denied the opportunity to use their talents in the service of their country, they began to operate what they called 'The Operation'. They would select a victim and then threaten to beat him up if he paid the so-called protection money.
</p></blockquote>

<p>This must not have been a particularly succesful strategem, for we are about to learn that the Piranha Brothers chose to 'pivot'.</p>

<blockquote><p>
Four months later they started another operation which the called 'The Other Operation'. In this racket they selected another victim and threatened not to beat him up if he didn't pay them.
</p></blockquote>

<p>This strategy also met with limited success and another pivot was in order.</p>

<blockquote><p>
One month later they hit upon 'The Other Other Operation'. In this the victim was threatened that if he <em>didn't</em> pay them, they <em>would</em> beat him up.</p>
<p><em>This</em> for the Piranha brothers was the turning point.
</p></blockquote>
]]>
    </description>
    <pubDate>Sat, 16 Mar 2013 00:24:49 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/piranha_pivot.asp</guid>
  </item>
<item>
  <title>Art of the command-line helper</title>
    <link>http://www.secretGeek.net/nt_commandline.asp</link>
    <description>
      <![CDATA[ 
<p>The scariest code I ever wrote is the dialog in <a href='http://NimbleText.com/'>NimbleText</a> that helps you use the command-line. </p>

<p>Much smack has been written in the past about confusing command-line helpers in other apps, so I set out to build this dialog with great trepidation in my heart.</p>

<p><a href='http://jcooney.net/'>Joseph Cooney</a> has laid into two particular apps, a <a href='http://www.jcooney.net/post/2006/10/29/Developer-UI.aspx'>gui for wget</a>, and a <a href='http://www.jcooney.net/post/2008/01/28/Developer-UI-the-gathering.aspx'>gui for robocopy</a>. Even <a href='http://www.codinghorror.com/'>Jeff Atwood</a> had <a href='http://www.codinghorror.com/blog/2006/11/this-is-what-happens-when-you-let-developers-create-ui.html'>a stab at wGetGui</a>.</p>

<p>Here's what they looked like:</p>
<a href='http://secretGeek.net/image/wGetGui.png' style='margin-left:40px'><img src='http://secretGeek.net/image/wGetGui_th.png' alt='gui for wGet' /></a>
<a href='http://secretGeek.net/image/robocopydeveloperuiv2.png' style='margin-left:40px'><img src='http://secretGeek.net/image/robocopydeveloperuiv2_th.png' alt='gui for robocopy' /></a>
<br /><br />
<p>And here's a typical user response upon first encountering such a command-line helper:</p>
<img src='http://secretGeek.net/image/omg_wtf.gif' style='padding:40px'/>
<p>I downloaded both these apps and tried them out.</p>
<p>Okay, the kindest thing you can say is that they are <em>comprehensive</em>, and with their use of tooltip text they do offer a little more help than the screenshots would suggest.</p>
<p>But they still give an immediate slap in the face to the end user. Something I want to steer away from.</p>
<p>So command-line helpers are a challenge. And to increase the pressure a little more: the command-line feature in NimbleText is only unlocked if you <a href='http://nimbletext.com/Home/Purchase'>buy</a> a license. If I'm expecting this feature to be worth money, they I <em>really</em> have to not screw it up.</p>
<h2>What I did.</h2>
<p>The first thing was to use descriptive labels, instead of verbatim option names. Instead of having a checkbox named "<code>--rawdata</code>" I'd have a label that said "Raw data". While this is only marginally more readable, it hopefully decreases the effect shown above.</p>
<p>Next I added a textbox at the foot of the form, where the command-line you've created is written, live, so you can see the output of your furious clicking.</p>
<p>There's a button for save, so you can save your command-line straight to a batch file. (It works from powershell too).  A copy button, to put the command-line into your clipboard, and an execute button, which launches a <code>cmd.exe</code> process, and tries out the command-line immediately.</p>
<p>Other than that, I just sweated the small stuff. Alignment, spacing, capitalization, tab order, tool tips, everything as consistent as possible.</p>
<p>What I probably failed to do was give The Dialog any breathing space.</p>
<p>(And looking at the screenshot now I see a slight inconsistency with spacing, which should be fixed by the time you look at the application itself.)</p>
<p>Here's what I came up with:</p>
<a href='http://NimbleText.com/Help/Commandline/' style='padding:40px'><img src='http://secretGeek.net/image/nt_commandline.png' /></a>
<p>Any suggested improvements? Please send them in.</p>
]]>
    </description>
    <pubDate>Thu, 07 Mar 2013 10:52:31 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/nt_commandline.asp</guid>
  </item>
<item>
  <title>Go and read a book.</title>
    <link>http://www.secretGeek.net/read_a_book.asp</link>
    <description>
      <![CDATA[
<p>I <a href='https://twitter.com/secretGeek/status/306676666187538432'>tweeted this</a> yesterday, but wanted to discuss it in a little more than 140 chars</p>

<blockquote><p>"Reading a book" is a classic important but non-urgent
task. When your lifestyle lacks any book time, you know you're in the
wrong quadrant.</p></blockquote>

<img src='http://secretGeek.net/image/MerrillCoveyMatrix.png' alt='Merril Covey Matrix'  style='border:1px solid #CCC;margin:20px;margin-top:0px;float:right;background-color:white' />

<p>This is a reference to the <a
href='http://czarto.com/2012/04/24/four-quadrants-of-time/'>four
quadrants matrix (urgency versus importance)</a> from the book <a
href='http://amazon.com/exec/obidos/ASIN/0684802031/secretgeek-20'>'First
Things First'</a> by
<a href='http://en.wikipedia.org/wiki/Stephen_Covey '>Stephen
Covey</a> et al.</p>

<p>The idea is that many of the things we do can be ranked as either
important or unimportant, and as urgent or non-urgent.</p>

<p>It's a neat and enlightening concept, but there's something utterly
impractical about it.</p>

<p><a href='https://twitter.com/DanPuzey/status/306678017718112256'>A response</a> from <a href='https://twitter.com/DanPuzey'>Dan Puzey</a> summed it up well:</p>

<blockquote><p>The real problem is that "organizing my life into
quadrants" always seems a non-important non-urgent task...</p></blockquote>

<p>Maybe that's why I've always felt uneasy about the four quadrants idea.</p>

<p>Don't spend time categorizing everything into one quadrant or the
other. Don't get caught up in grandiose and abstract questions like "Do I have my
life values in order? Am I doing first things first every day?"</p>

<p>Just ask yourself the simple, practical question  "Have I read any
good<sup id="fnref:cb"><a href="#fn:cb" rel="footnote">1</a></sup> books lately?"</p>

<p>Your answer sums up a hell of a lot about how you're life is going. If
you find you're not reading any good books, then you know right away
that your life is out of balance.</p>

<p>Now stop staring at your navel, and go read <a href='http://amazon.com/exec/obidos/ASIN/0440180295/secretgeek-20'>Slaughterhouse-Five</a>.</p>


<hr />

<div class="footnotes">
<ol>
<li id="fn:cb">
<p>If all you've read lately are comic books, by the way, then the answer to
the question is an emphatic 'No'.<a href="#fnref:cb" rel="reference">&#8617;</a></p>
</li>
</ol> 

<hr />
<p>Image from <a
href='http://en.wikipedia.org/wiki/File:MerrillCoveyMatrix.png'>Wikipedia:
Merrill Covey Matrix</a></p>
<p>Bonus unrelated wikipedia link: <a
href='http://en.wikipedia.org/wiki/Four-quadrant_movie'>Four-Quadrant
movie</a>.</p>
]]>
    </description>
    <pubDate>Thu, 28 Feb 2013 10:57:34 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/read_a_book.asp</guid>
  </item>
<item>
  <title>Slurp up mega-traffic by writing scalable, timeless search-bait</title>
    <link>http://www.secretGeek.net/snb_seo.asp</link>
    <description>
      <![CDATA[<p><em>In which I follow the advice of Patrick McKenzie to try and get my little software products into the eyeballs of a whole new audience.</em></p>

<img src='http://secretGeek.net/image/snb.png' style='float:right;margin:15px' alt='sunday night blues, micro-Isv style' />
<p>So, it was one of those lazy Sunday evenings when a microIsv guy does what he does best: he looks through the Google Analytics of his products, desperately trying to work out why he is not yet a millionaire, desperately trying to find what tiny tweak he can apply that will ensure he has no need to head to work in the morning, or ever again. (This is known as '<em>Sunday evening blues, microIsv-style</em>')</p>

<p>When I looked at the search traffic for both sites (<a href='http://TimeSnapper.com/'>TimeSnapper</a> and <a href='http://NextAction.com/'>NextAction</a>), something leapt out at me, the way a tiger in the wilds of India might jump out at a plump looking passerby.</p>

<p>The only search terms people were using to find TimeSnapper were terms like "TimeSnapper", "Time Snapper" or related mis-spellings of the product name.</p>
<p>Noticeably absent from the keyword traffic was every single person in the world who hadn't already heard of the product from some other source. No one looking for <a href='http://TimeSnapper.com'>"I just lost all my work, how do I get it back?"</a> or <a href='http://TimeSnapper.com'>"How do I make timesheets easier?"</a> or <a href='http://TimeSnapper.com'>"How can I understand my own bad habits?"</a> or <a href='http://TimeSnapper.com'>"Continuous Screenshot Taking"</a> and so on for a million other search terms. (Hint: I just demonstrated the SEO technique of google-bombing oneself ;-) ). So my website -- That Dilligent Little 24 Hours a Day 7 Days a Week Sales Guy, wasn't drumming up one <strong>iota</strong> of new sales.</p>

<p>And the same for NimbleText. A tiny trickle of people would turn up, but only via search terms like "NimbleText", "Nimble Text" or "World's Simplest Code Generator" (the product's original name) -- and <strong>no one else</strong>.</p>

<p>So I asked myself, as I sat there on that uneventful Sunday eve: How do I make it happen?</p>

<p>In times like this, I always turn to the writings of <a href='http://www.kalzumeus.com/'>Patrick Mckenzie</a> (aka Patio11 on twitter and Hacker News). <a href='http://www.kalzumeus.com/2010/01/24/startup-seo/'>For SEO he recommends</a> writing 'evergreen' and 'scalable' content. </p>

<p>'Evergreen' content is timeless content: stuff that isn't dependent on today's news cycle or the latest fashion.</p>
<p>'Scalable' content is the sort of content you can write a lot of. The sort of guff that doesn't take a great deal of soul searching.</p>

<p>In relation to NimbleText I easily came up with a basic idea for 'scalable' content generation. Normally, when writing about NimbleText I think about the features, and there's a finite amount I can write. If instead I were to write a short article on every possible specific situation where NimbleText could be used, then you'd be looking at a limitless source of article topics. Think of every type of code it can generate, every example piece of HTML it can produce, every piece of SQL it can concoct, you would be looking at an endless stream of simple, albeit quite repetitive articles. You could churn out such articles at a pretty fast rate. (NimbleText itself could even help with this task.)</p>

<p>Articles such as <a href='http://NimbleText.com/HowTo/GenerateInsert'>'How do I generate insert statements?'</a> may not be the sort of thing that sets the world on fire -- they're never going to attract a viral influx of rabid fans -- but hopefully they'll pander to some fine strange of the long tail of search traffic, and, over time, bring in a trickle of fresh visitors, potential paying customers.</p>

<p>This strategy is a sure winner from an SEO point of view. Wikipedia is essentially nothing but a giant engine built for the creation of Scalable Evergreen content. No wonder it takes first place for just about any search you perform.</p>

<p>So here's the short list of NimbleText-related articles I've written on the bus, since coming up with this strategy:</p>

<h2>SQL Master Class (for NimbleText)</h2>
<ul>
<li><a href='http://NimbleText.com/HowTo/GenerateInsert'>How to Generate Insert Statements</a></li>
<li><a href='http://NimbleText.com/HowTo/GenerateUpdate'>How to Generate Update Statements</a></li>
<li><a href='http://NimbleText.com/HowTo/GenerateINStatement'>How to Generate SQL 'IN' Statements</a></li>
<li><a href='http://NimbleText.com/HowTo/GetColumns'>How to List the Columns of a Table, Quickly!</a></li>
<li><a href='http://NimbleText.com/HowTo/ExtractColumns'>Extracting a list of columns from a block of text</a></li>
<li><a href='http://NimbleText.com/HowTo/GenerateViews'>How to Generate Views the easy way</a></li>
</ul>
<p>It takes less than one bus ride to write such an article, and they're only getting easier. I've got a backlog of thirty such topics and I'm sure with a more concentrated effort I could grow this to many more. Is it worth it? I'm unconvinced, but I'll look at the analytics over time and see what happens.</p>

<p>I've been running this experiment for a few weeks now. Already i've started to see people arrive from new search queries, suited to the articles I've written. The volumes are hardly mega, but the littlest steps bring the most satisfaction.</p>
]]>
    </description>
    <pubDate>Sun, 24 Feb 2013 11:35:41 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/snb_seo.asp</guid>
  </item>
<item>
  <title>Do *NOT* try this Hacking Script at home</title>
    <link>http://www.secretGeek.net/hack_system.asp</link>
    <description>
      <![CDATA[ 
<p>From <a href='http://stackoverflow.com/a/1466449'>this answer</a> at stackoverflow, I read:</p>

<blockquote><p>I saw this one in a bollywood movie. Our hero was busy romancing with his gf until his friend informs him about upcoming college exams. So, he decides to get examination papers by hacking into his college network. This is how he goes about it:</p>

<p>Enters Lab. Opens up a command prompt window. Types - Hack System</p>

<p>And that's it!!...A window pops up- System Hacked</p>

<p>He gets access to all papers and returns to his gf for a romantic song :)</p>
</blockquote>

<p>Mind blown. I just had to try it out:</p>

<blockquote><pre>
C:\temp>copy con hack.bat
@echo %* hacked!!!!
^Z
        1 file(s) copied.

C:\temp>hack system
system hacked!!!!

C:\temp>hack internet
internet hacked!!!!

C:\temp>hack FBI
FBI hacked!!!!
</pre></blockquote>

<p>Drunk with power, yet trembling in terror; I'm sitting here with the door barricaded, certain the feds are going to burst through the door at any moment.</p>
<p>Do *not* try this at home.</p>
]]>
    </description>
    <pubDate>Fri, 22 Feb 2013 22:46:50 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/hack_system.asp</guid>
  </item>
<item>
  <title>The 'Should I automate it?' Calculator</title>
    <link>http://www.secretGeek.net/automate_it.asp</link>
    <description>
      <![CDATA[<a href='http://NimbleText.com/automate'><img src='http://secretGeek.net/image/automate_calc.png' alt='Should I automate it?' style='border:1px solid #CCC;margin:10px;float:right;' /></a>

<p>Here's a clever calculator that let's you answer the age-old question: "is this thing worth automating?"

<p>I put this together a few days ago and I just keep needing to use it! Situations keep coming up where I'm gobsmacked to find that our 'gut-feel' about the relative merits of two approaches is just not borne out by the simplest back-of-the-napkin calculation.</p>

<p>The neat thing about this calculator is that it distills the choice down to its most crucial elements, so you can come up with an answer very quickly.</p>

<p>Once you've plugged in some values and gotten your answer, you can easily share it with those chumps in management or with a clever colleague -- click the 'Save this result' button, and you'll be given a url that you can send around, preserving all the values you plugged in, allowing others to tinker with your calculation and verify everything for themselves. (Implementing that bit was the funnest of the fun. Remind me to show you the 'GetHashyCode' extension method.)

<p>When you take a moment to play with the figures, there's a bunch of things that leap out at you.</p>

<p>First up -- this rather obvious result:</p>

<blockquote><p>"If you're only going to do it once, it's not worth automating."</p></blockquote>

<p>That might be quite a shock to some of my automation-happy friends, but I'm afraid the result is unequivocal.</p>

<p>Second: it's <em>amazing</em> how much value you can add by automating something that happens a lot.</p>

<p>Imagine your company has a timesheeting system that takes 10 minutes longer to complete than it should. It's used every week by 20 people, so in the next 2 years it will be filled out approximately 2000 times. You work out a way to save those 10 minutes.... how much effort should you put into making this improvement? Should you bail out if you can't fix it in 1 day? 2 days? 3 days? <a href='http://nimbletext.com/Automate/-1285475212'>Here are the figures</a>. It turns out the break even point is 430 hours of work -- around 11 weeks! So yes, if it's going to cost you a whole day of work to improve the timesheeting system -- go ahead and do it! You'd be insane not to!</p>

<a href='http://www.inventions.org/culture/african/matzeliger.html'><img src='http://secretGeek.net/image/matzeliger.png' alt='Jan Ernst Matzeliger (1852 - 1889) Inventor and Businessman' style='border:1px solid #CCC;margin:10px;float:right;' /></a>
<p>Of course, the benefits of automation are more than just the time it can save. When a task becomes free to do it changes the nature of the value proposition. Read about the amazing impact of <a href='http://www.inventions.org/culture/african/matzeliger.html'>Jan Ernest Matzelinger</a> -- a brilliant automator who revolutionised the shoe industry.</p>

<h2>The calculator could be simpler, or it could be more complex.</h2>

<p>A simpler version would remove the 'hourly rate' fields -- so the answer would be in just hours.</p>

<p>A slightly more complex version would allow there to be a different hourly rate for the person who cleans up when manual work goes wrong. This is realistic. Clean up crews can be expensive. Also the costs of maintaining the automation could be factored in. Cheap automation solutions tend to be very brittle.</p>

<p>Okay -- I'm all out of discussion about this little tool. <a href='http://nimbletext.com/Automate/'>Use it</a>, share it, automate something today.</p>
<p style='clear:right'>&nbsp;</p>
 
]]>
    </description>
    <pubDate>Thu, 07 Feb 2013 10:19:17 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/automate_it.asp</guid>
  </item>
<item>
  <title>aaron swartz: the early works</title>
    <link>http://www.secretGeek.net/vintage_swartz.asp</link>
    <description>
      <![CDATA[<img src='http://secretGeek.net/image/aaron2002_webcam.jpg' 'webcam photo from 2002 -- http://www.aaronsw.com/weblog/000373' style='border:1px solid #CCC;margin:10px;float:right;'>

<p>I can't stop thinking about, wondering about, caring about, reading about the tragic life of <a href='http://en.wikipedia.org/wiki/Aaron_Swartz'>Aaron swartz</a>. There's a lot I want to write. I think I could fill a book just trying to process what it means, what is an appropriate response, what's it all about. But I'm not going to attempt that.</p>

<p>I've been reading <a href='http://www.aaronsw.com/weblog/'>Aaron's blog</a>, on and off, for over ten years. Ten years is a long time. And by my own estimates, those <em>particular</em> 10 years were the longest in history.</p>

<p>Long ago I printed out his <a href='http://www.aaronsw.com/weblog/productivity'>HOWTO: Be more productive</a> for multiple re-reads and have returned to it many times since. </p>

<p>I wanted to go back, right back, and try to work out the earliest stuff of his that I read. And I wanted to watch the progression of his ideas as they emerged.</p>

<p>From his blog <a href='http://www.aaronsw.com/weblog/'>'raw thought'</a> -- there's a link to 'Older Posts' which takes you to <a href='http://www.aaronsw.com/weblog/archive'>'the archive'</a> (grouped by theme). </p>

<p>From there is a link to 'Full Archives' which takes you to the reverse-chronological <a href='http://www.aaronsw.com/weblog/fullarchive'>archives</a>.</p>

<p>These stretch back to May 2005  (the oldest entry on that page is about <a href='http://www.aaronsw.com/weblog/whaaaa'>a server crash</a> after which he had to restart his blogging. Under the so called 'Full archives' section there's no link to anything prior to May 2005.</p>

<p>Now I'm certain he was blogging long before that -- I'm certain I was reading his blog long before that.</p>

<p>Is the stuff before that server crash lost? I hoped not, so I set about locating it.</p>

<p>I clearly remember his <a href='http://www.aaronsw.com/weblog/000931'>powerpoint remix</a> (from 2003!) - it got published in a book of Joel Spolsky's - and I soon tracked that down.</p>

<p>Taking a look at the url suggests a numbered blogging system (from Dave Winer's Radio Userland), and from there it's easy to find all of his prior blog entries.</p>

<p>After a bit of binary searching I found what looks like Aaron's first <a href='http://www.aaronsw.com/weblog/000081'>Hello, world</a>, with article id of '81'.</p>

<p>So I wrote a powershell script to download everything (I hardly think aaronsw would object !!) and found that the articles go from number 81 up to 1691, with a few gaps.</p>

<p>Here's the script.</p>

<blockquote><pre>
# Downloads aaron's early stuff
# i've done this the hard way because i didn't have time to do it the easy way.

$client = new-object System.Net.WebClient

$nums = 81..1691

#detected up to 1691  (April 26, 2005)
$nums | % {
	$url = [string]::Format( "http://www.aaronsw.com/weblog/{0:000000}",$_)
	$path = join-path $(get-location) ([string]::Format("aaronsw_{0:000000}.html",$_))
	Write-Host "downloading " $url " to " $path
	$client.DownloadFile( $url, $path )
	
	#sleep for 4 seconds before grabbing, to give the server time to exhale.
	Start-Sleep -s 4
}

</pre></blockquote>

<p>Then I wrote a script to walk through those files and create an archive page in the same style as Aaron's other archive pages.</p>

<p>It's not pretty code, it got the job done...</p>

<blockquote><pre>
dir .\aaronsw_*.html | % {

    #extract the filenumber out of the name... i should've made this easier.
	$num = $_.Name.Split("_")[1].Split(".")[0] 
	
	#calculate the target url for this file
	$url = [string]::Format("http://www.aaronsw.com/weblog/{0}",$num)
	
	#load the file 
	$article = gc $_.Name

	#grab the title
	$titleRegex = [regex]'h1&gt;(.*)&lt;/h1&gt;'
	$title = $titleRegex.Match($article).Groups[1].Value
	
	#grab the time
	$timeRegex = [regex]'&lt;p class="posted"&gt;posted ([^(]+) \('
	$time = $timeRegex.Match($article).Groups[1].Value
	
	#output the url, title and time, as html
	$item = [string]::Format('&lt;p&gt;&lt;a href="{0}"&gt;{1}&lt;/a&gt; ({2})&lt;/p&gt;',$url,$title,$time)
	$item &gt;&gt; archivePreCrash.html
}
</pre></blockquote>


<p>So the result is this fairly complete list of pre-server crash articles:</p>
<p>&nbsp;</p>
<p><a href='http://secretGeek.net/content/archivePreCrash.html' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>aaronsw archive: early works</a>
</p>
<p>&nbsp;</p>
<p>Now this takes us up to April 2005. And the post-crash articles start in May 2005, so it probably means that everything's accounted for, except maybe a month's worth of blogging. There are some missing articles within that period, and some lost stuff. I can see that he restored it from the <a href='http://archive.org/web/web.php'>wayback machine</a> where possible, but sometimes there was nothing to grab.</p>

<p>There are a lot of gems in there (and of course a bit of drivel: this starts when he was 15). I was going to pull out a few quotes, but I'd rather let you do that for yourself. He was a thoughtful guy. It'd be great if he was still around.</p>
]]>
    </description>
    <pubDate>Sat, 19 Jan 2013 12:24:12 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/vintage_swartz.asp</guid>
  </item>
<item>
  <title>Finding (and removing) duplicate files on your hard drive</title>
    <link>http://www.secretGeek.net/dupes.asp</link>
    <description>
      <![CDATA[<p>I generally hold to the philsophy that <a href='http://secretgeek.net/mailboxlimits.asp'>hard drive space is cheap</a>, and your time is too valuable to waste on optimising hard drive space.</p>

<p>But one of those fun holiday activities, reserved for times when procrastination is at its peak, is to thoroughly clean up a hard drive and make extra room available.</p>

<p>My usual technique is to use <a href='http://www.uderzo.it/main_products/space_sniffer/index.html'>SpaceSniffer</a> (found courtesy of <a href='http://www.hanselman.com/tools'>Scott Hanselman's tool list</a>) but this time around I suspected that the biggest waste of space was caused by duplicate files (particularly music and photos) taking up a lot of space.</p>

<p>When confronted with a simple problem, the smart guys look for pre-existing solutions. But not me.</p>

<p>I like to employ something I call the '<em>my way is the best way</em>' philosophy. Other people call it '<em><a href='http://en.wikipedia.org/wiki/Not_invented_here'>not invented here</a></em>' syndrome, but I prefer to call it '<em>my way is the best way</em>' because... well, <em>my way is the best way</em>.</p>

<img src='http://secretGeek.net/image/Pai_Mei_beard.jpg' alt='thinking about duplicate files' style='border:24px solid #000;margin:10px;float:right' />

<h2>Analysis is more fun than Action</h2>

<p>Most of the duplicate-finding tools in this category have a feature where they will automatically delete all but one copy of each duplicate file found. That's not something I'm willing to do, at least not automatically. What I wanted to do was to create the full list of files, and then analyse it, for example in <a href='http://NimbleText.com/'>NimbleText</a>. I wanted to create the list of files and then stand back, thoughfully stroking my long beard, just like Pai Mei from Kill Bill.</p>

<p>So I embarked on a special project, codenamed <code>Dinomopabot</code>, a name recommended by my 5 year old daughter who is very clever at these things. The final result is now named '<code>Dupes.exe</code>': a command line tool for finding duplicate files on your hard drive.</p>



<br />
<p>You can browse, clone or fork the source-code, at Bitbucket:</p>
<p><a href='https://bitbucket.org/secretgeek/dupes' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>'Dupes' sourcecode</a></p>
<br />

<br />
<p>Or download the executable, ready for use:</p>
<p><a href='https://bitbucket.org/secretgeek/dupes/downloads/Dupes.exe' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Download 'dupes.exe'</a></p>
<br />

<p>Here's the built-in help text:</p>



<blockquote>
<pre>
<strong>Dupes</strong> Find duplicate files, by calculating checksums.

Usage: <strong>Dupes.exe</strong> [options]
Tip: redirect output to a .csv file, and manipulate with NimbleText.

Options:
  -p, --path=VALUE           the folder to scan
  -s, --subdirs              include subdirectories
  -f, --filter=VALUE         search filter (defaults to *.*)
  -a, --all                  show ALL checksums of files, even non-copies
  -?, -h, --help             show this message and exit
</pre>
</blockquote>

<p>For each file it encounters, <code>Dupes</code> generates a sha256 checksum, with which to compare files. They're short and catchy, they look like this:

<blockquote>
<pre>
271EC103B44960B6A4C6A26FE13682A855133D3D95AC8ED81D7C90FA41571D1F
</pre>
</blockquote>

<p>Cute hey? Almost <a href='http://secretgeek.net/hotguids/'>adoption-worthy</a>.</p>

<p>And for every member of a duplicate file set that the tool encounters, it spits out a row with four columns, separated by bar symbols ('|')</p>
<p>The four columns are:</p>

<blockquote>
<pre>
CheckSum       Sha256 checksum of the file. (Hint: sort by this to get all duplicates together)
DuplicateNum   0 for the first file in the duplicate set, 1 for the second file, etc.
Filesize       In bytes. (Hint: sort by this, if you want to tackle big files first)
Path           Full path and filename for this duplicate.
</pre>
</blockquote>

<p>So you run <code>dupes.exe</code> and direct the output into a textfile (using <code>&gt; [filename]</code>), and from there you can manipulate it (with NimbleText for example), to create a batch file that carefully deletes all the hand-picked, unwanted duplicates of your choice.</p>


<p>Here's an example of a NimbleText pattern you could use with the output of Dupes. This will create a batch file that deletes all but the first copy of each file:</p>

<blockquote>
<pre>
&lt;% if ($1 &gt; 0) { 'del ' + $3 } %&gt;
</pre>
</blockquote>

<p>That pattern is just a piece of embedded javascript (you can embed javascript in NimbleText patterns) that says "if column 1 is greater than Zero, then output the text 'del ' plus the text from column 3." Column 1 is the duplicate number, so it will be greater than zero for all but the first instance of the file. And column 3 is the full path and filename of the duplicate.</p>

<p>Thank you. I hope someone finds this thing useful. Also, please imagine suitably gigantic and terrifying disclaimers attached to this code. I wrote it after all.</p>

]]>
    </description>
    <pubDate>Thu, 10 Jan 2013 21:27:11 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/dupes.asp</guid>
  </item>
<item>
  <title>Harvey, a .net chat server built with RabbitMQ</title>
    <link>http://www.secretGeek.net/harveymq.net.asp</link>
    <description>
      <![CDATA[<img src='secretGeek.net/image/harvey_img.jpg' title='Harvey, you know, like the Rabbit in the movie' style='float:right; padding:10px;'/>

<p>I've turned into a rabbid <a href='http://www.rabbitmq.com/'>RabbitMQ</a> fan in the last week or two, though so far I've only scratched the surface of what this thing does.</p>

<p>Below I'm going to walk through the code for a chat service, built with .net, that uses RabbitMQ for sending and receiving messages. But first a short discussion of Message Queues, RabbitMQ, and how to get this rabbit up and running.</p>

<p>A lengthy discussion is out of scope for this bus ride, but basically:</p>
<p>A <a href='http://en.wikipedia.org/wiki/Message_queue'>message-queue</a> is a piece of middleware for asynchronous communication. (System A sends messages to System B).</p>

<p>MQ's can be optimized for performance, reliability, scalability or any other <a href='http://secretgeek.net/core51.asp'>'*ility'</a> you can think to mention.</p>

<p>There's lots of them, they make different trade offs. Originally they were expensive proprietary technologies (e.g IBM's MQ-Series) - but along with the rise of <a href='http://en.wikipedia.org/wiki/Message_queue#Standards_and_Protocols'>standards in this area</a> there have arisen various compelling open source offerings.</p>

<p>RabbitMQ is built on Erlang. I don't want to digress into sounding like one of those <a href='http://buffered.io/'>Erlang-douchebags</a>, but Erlang is a good match for an MQ.</p>

<p>Erlang's initial purpose was to create telecommunications software that was (a) super reliable and (b) hot-swappable. That's a perfect fit for MQ software. 
It can spin up extra processes without all the heavy lifting of using extra threads, so where a normal OS thread allocates a few megs of memory, Erlang gets away with a few bytes. Extraordinary stuff.</p>

<p>Having said that, the biggest problem with RabbitMQ is that it's built on Erlang. Thus, to install it on your Enterprise-controlled Servers at BigCo you'll need to get Corporate IT's permission to install yet another VM/Platform. Good luck sweet talking those guys. They do *love* to kick up a fuss.</p>

<h2>Up and running with RabbitMQ in Under 3 minutes</h2>

<p>Everything I'm going to cover in this section is covered in <a href='http://lostechies.com/derekgreer/2012/03/05/rabbitmq-for-windows-introduction/'>part 1</a> of <a href='http://lostechies.com/derekgreer/tag/rabbitmq/'>Derek Greer's RabbitMQ for windows series</a>. So I'll go extra quick.</p>


<p>	To setup a host server for your chatting you'll need to...</p>
	
	<ol><li>Install erlang: <a href='http://www.erlang.org/download.html'>http://www.erlang.org/download.html</a> </li>
    <li>Set the <code>ERLANG_HOME</code> environment variable to point to the erlang folder under program files. e.g. <code>C:\Program Files\erl5.9.2</code></li>
    <li>Install rabbitMQ: <a href='http://www.rabbitmq.com/download.html'>http://www.rabbitmq.com/download.html</a></li>
    <li>Enable the rabbitmq management plugin. from an <strong>elevated</strong> cmd prompt:<br /> 
    &nbsp;&nbsp;&nbsp;&nbsp;Go to rabbit's <code>sbin</code> folder, e.g. <code>%programfiles%\RabbitMQ Server\rabbitmq_server-2.8.7\sbin</code>, and run:<br /> 
    <code>&nbsp;&nbsp;&nbsp;&nbsp;rabbitmq-plugins.bat enable rabbitmq_management</code></li>
    <li>To activate the management plugin, stop, install and start the rabbitmq service:<br />
    <code>&nbsp;&nbsp;&nbsp;&nbsp;rabbitmq-service.bat stop <br />
    &nbsp;&nbsp;&nbsp;&nbsp;rabbitmq-service.bat install <br />
    &nbsp;&nbsp;&nbsp;&nbsp;rabbitmq-service.bat start  </code><br />
    <li>Finally, visit http://localhost:55672/mgmt/ and see that your rabbitMQ instance is alive.</li>
</ol>
<p>It's *that* simple.</p>
<p>Worlds easier than most other installs. Much easier than installing a database, or keeping Adobe Reader up to date.</p>

<p>The only other thing you need do to become a certified .net RabbitMQ developer is use nuget to add a reference to the <a href='http://www.rabbitmq.com/dotnet.html'>RabbitMQ.client</a> package.</p>

<img src='image/harvey_scrn.png' title='Harvey, chat client screenshot' style='float:right; padding:10px;'/>

<h2>Introducing Harvey (the simple .net chat client)</h2>


<br />
<p><a href='https://bitbucket.org/secretgeek/harvey/src' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Harvey Source Code Here.</a></p>
<br />


<p>Once your rabbitMQ service is up and running, every one on your network can grab Harvey.exe and join in one colossal chat room for all their communication purposes. Every message is delivered to every listener.</p>
<p>The architecture is simple. When you run Harvey.exe it creates two channels, one for sending, one for receiving. The send channel is connected to a fan-out exchange on the server. Each snatchy client also creates its own queue on the server (identified by a guid), which is bound to the afore mentioned fan-out exchange. Thus, when any client sends a message, every client receives it.

<p>Let's step through it.</p>
<style>
.prettyprint{border:0px solid #FFF !important;margin:5px}
</style>

<h3>Set up a channel to the fanout exchange</h3>
<p>(Just let it wash over you, this will all make sense by the end)</p>
<p>In <code>form_load</code> we setup everything we need for sending messages. We need a channel to the exchange. The exchange is of type 'fanout' meaning it will send all messages to all queues that are bound to it.</p>
<p>When we 'declare' the exchange, the exchange will be created on the server if it doesn't already exist. Otherwise we will use the existing exchange that has already been declared for us.</p>
<p>In <code>form_load</code>:</p>
<blockquote>
<pre class="prettyprint">
<code>
            var connectionFactory = new ConnectionFactory
            {
                HostName = "localhost",
                Port = 5672,
                UserName = "guest",
                Password = "guest",
                VirtualHost = "/"
            };

            connection = connectionFactory.CreateConnection();
            channelSend = connection.CreateModel();
            channelSend.ExchangeDeclare(exchangeName, ExchangeType.Fanout, false, true, null);
</code>
</pre>
</blockquote>

<h3>Sending a message</h3>
<p>Assuming we have a textbox (txtMessage) for entering the message we want to post, here's what happens when we click send:</p>
<blockquote>
<pre class="prettyprint">
<code>
            string input =  txtUserName.Text + " > " + txtMessage.Text;
            byte[] message = Encoding.UTF8.GetBytes(input);
            channelSend.BasicPublish(exchangeName, "", null, message);
            txtMessage.Text = string.Empty; 
            txtMessage.Focus();
</code>
</pre>
</blockquote>
<p>That was nice, but we probably want to receives messages back as well -- a chat is not just one way.</p>

<h3>Set up a channel to your own queue, for receiving.</h3>
<p>We declare a queue, a brand new queue that no one has declared before, and bind it to the fanout exchange.</p>
<p>So messages sent to that exchange will go to this queue, on the server. And we've got a channel to the queue.</p> 
<p>(This bit also happens in <code>form_load</code>)</p>
<blockquote>
<pre class="prettyprint">
<code>
            channelReceive = connection.CreateModel();
            channelReceive.QueueDeclare(clientId, false, false, true, null);
            channelReceive.QueueBind(clientId, exchangeName, "");
</code>
</pre>
</blockquote>

<h3>Receiving a message...</h3>
<p>The very next thing we do in <code>form_load</code>, is start a thread for listening to messages on that channel:</p>
<blockquote>
<pre class="prettyprint">
<code>
            receivingThread = new Thread(() => channelReceive.StartConsume(clientId, MessageHandler));
            receivingThread.Start();
</code>
</pre>
</blockquote>
<p>(Note, forgetting to call .Start() cost me more debugging time than anything else in this whole learning experience)</p>
<p>The following '<code>StartConsume</code>' extension method was lifted from <a href='http://lostechies.com/derekgreer/2012/05/29/rabbitmq-for-windows-headers-exchanges/'>one of Derek Greer's RabbitMQ articles</a>:</p>
<p>We block the thread waiting for a <code>Dequeue</code> to happen.</p>
<blockquote>
<pre class="prettyprint">
<code>
        public static void StartConsume(this IModel channel, string queueName, Action&lt;IModel, DefaultBasicConsumer, BasicDeliverEventArgs> callback)
        {
            QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel);
            channel.BasicConsume(queueName, true, consumer);

            while (true)
            {
                try
                {
                    var eventArgs = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
                    callback(channel, consumer, eventArgs);
                }
                catch (EndOfStreamException)
                {
                    // The consumer was cancelled, the model closed, or the connection went away.
                    break;
                }
            }
        }
</code>
</pre>
</blockquote>

<p>And the 'MessageHandler' delegate, above is as follows:</p>


<blockquote>
<pre class="prettyprint">
<code>
        public void MessageHandler(IModel channel, DefaultBasicConsumer consumer, BasicDeliverEventArgs eventArgs)
        {
            string message = Encoding.UTF8.GetString(eventArgs.Body) + "\r\n";

            txtConversation.InvokeIfRequired(() =>
            {
                txtConversation.Text += message;
                txtConversation.ScrollToEnd();
            });
        }
</code>
</pre>
</blockquote>

<p><code>InvokeIfRequired</code> is just a useful winforms extension method for hopping from a background thread onto the gui thread, taken from <a href='http://stackoverflow.com/questions/2367718/c-automating-the-invokerequired-code-pattern'>this stackoverflow question</a>, and implemented as follows:</p>

<blockquote>
<pre class="prettyprint">
<code>
        public static void InvokeIfRequired(this Control control, MethodInvoker action)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(action);
            }
            else
            {
                action();
            }
        }
</code>
</pre>
</blockquote>


<h2>Further reading:</h2>

<p><a href='http://videlalvaro.github.com/2011/05/rabbitmq-chat-post-mortem.html'>This guy used a similar architecture</a> to what i went with. It's just the simplest architecture imaginable, and he handled 2000 messages a second from a very minimal piece of hardware.</p>
<p>Simon Dixon's article - <a href='http://simonwdixon.wordpress.com/2011/05/08/getting-started-with-rabbitmq-in-dotnet/'>Getting Started With RabbitMQ in .net</a></p>
<p>Mike Hadlow has written 'an easy to use .net api for RabbitMQ' called <a href='https://github.com/mikehadlow/EasyNetQ'>EasyNetQ</a>. One to watch.</p>
<p>As recommended above, Derek Greer has an <a href='http://lostechies.com/derekgreer/tag/rabbitmq/'>Excellent Series on RabbitMQ for Windows</a></p>
<p><a href='http://www.rabbitmq.com/devtools.html#dotnet-dev'>Further links to .net development with RabbitMQ</a></p>

 ]]>
    </description>
    <pubDate>Mon, 19 Nov 2012 11:05:41 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/harveymq.net.asp</guid>
  </item>
<item>
  <title>LeonBambrick.com</title>
    <link>http://www.secretGeek.net/lb_dotcom.asp</link>
    <description>
      <![CDATA[<p><em>I'm not just a person, I'm a dot com.</em></p>
<p>When my website was stolen, and I thought I'd never get it back, I started making plans to re-launch somewhere else. Hence, I acquired the domain LeonBambrick.com.</p>
<p>That domain has sat dormant for over a year, until the last week or two, when I decided to put up a list of my online projects, in an easy to digest, html5-friendly, form.</p>
<p>Since you're not doing anything else at the moment, go and have a look:</p>
<br />
<p><a href='http://LeonBambrick.com' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Visit LeonBambrick.com</a></p>
<br />
<p>It's animated using <a href='http://isotope.metafizzy.co'>'isotope'</a>  -- an exquisite jQuery plugin for magical layouts.</p>
]]>
    </description>
    <pubDate>Mon, 12 Nov 2012 10:08:14 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/lb_dotcom.asp</guid>
  </item>
<item>
  <title>So your domain has been stolen. What now?</title>
    <link>http://www.secretGeek.net/hijack_checklist.asp</link>
    <description>
      <![CDATA[ 

<span style='float:right; background:black'><table><tr><td style='background:black'><a href='http://WhoTalking.com/'><img src='http://secretGeek.net/image/whotalking.png' alt='WhoTalking.com' style='float:right;border:1px solid #CCC;margin:10px;'  /></a><br /><center style='clear:right'><small style='color:#FFF'>WhoTalking.com. Taken! Then taken back.</small></center><br /></td></tr></table></span>

<p>I was recently contacted by a local entrepeneur, Michael Q, after his internet domain was <strong>taken</strong> in circumstances similar to <a href='http://www.secretgeek.net/sg_hijack_2.asp'>my own</a>.</p>

<p>An intruder gained entry to his email account and used that to get enough information to transfer ownership of his domain away from his registrar.</p>
<p>His registrar was "crazy domains" (in my case it was 'Go Daddy') and the gaining registrar was a french registrar, bookmyname.com (in my case it was WebNames.ru, a russian registrar).

<p>Michael and I wrote back and forth a lot over the next few days. I gave him as much advice as I could, and he kept me informed about his progress. On about the fifth day I got the excellent news that he was back in charge of his domain again.</p>
<p>Michael wrote a complete chronology of the incident: <a href='http://www.webstriking.com/domain-name/how-i-lost-my-domain-name-and-how-i-got-it-back'>How I Lost My Domain Name and How I Got it Back</a></p>

<p>And here's my own step by step guide to what happens and what to do if your domain is hijacked, based on my experience and Michael's:</p>

<h2>Losing and Regaining Your Domain, Step by Step</h2>

<ol>
<li>Notice a warning in your gmail account that you've logged in using an unknown means from a distant location. Your spidey senses will begin tingling.</li>
<li>Check for deleted emails -- find one from your domain registrar, saying you've transferred away from them. This will include details of the gaining registrar.</li>
<li>Panic and or freak out completely at this point.</li>
<li>Check for email rules that automatically delete any emails from the losing or gaining registrar. take screenshots of and then remove those rules.</li>
<li>Secure your gmail account. change your password, change all your security questions and answers, change your recovery email address, disable any third party apps from accessing it, and disable pop and imap access. Start using <a href='http://support.google.com/accounts/bin/answer.py?hl=en&answer=180744'>2-step verification</a>.</li>
<li>Think about all of the other things you store in your email account. Other passwords in particular. Start the long process of resetting every password you have. Put it in priority order. Use a proper password management system (e.g. <a href='http://pwsafe.org/'>password safe</a>) so that all passwords are unique, complex and as long as possible.</li>

<li>Now, and only now, is it time to stop panicking.</li>
<li>All registrars are ICANN accredited businesses. They must abide by a code of practice, or they will lose their accreditation. One of the rules is that a domain can't hop to a new registrar for another <a href='http://www.icann.org/en/resources/registrars/transfers/text'>60 days</a>. So breathe a sigh of relief and realise that you have 60 days to regain control of your domain.</li>
<li>Contact your registrar and inform them that your domain has been hijacked and moved to the gaining registrar. Tell them it is a "disputed transfer", and that you want to fill out their disputed transfer away form. See if they have one (they should).</li>
<li>Contact the gaining registrar -- it's their co-operation that will matter the most. Be nice to them. You may need to register at their site, go ahead and do this.</li>

<img src='http://secretGeek.net/image/breadhead33.jpg' title='sadly lacking the fish and the wine' style='float:right;padding:4px; padding-left:30px;padding-right:10px' />


<li>Tell them your domain was hijacked from the losing registrar and moved to them.<br /><br />
To establish your identity you may need to send them a scanned copy of your identification (drivers license, passport). It's a scary thing to do, but seems to help, so go ahead and do this if they ask for it.<br /><br />
(It may also, for reasons that are beyond the scope of this article, help to send them a photo of yourself with <a href='http://419eater.com/html/kothapalli_rao.htm'>a loaf of bread on your head</a>)<br /><br />Tell them when you first got the domain, what it was used for. Direct them to the <a href='http://archive.org/web/web.php'>way back machine</a> screenshots of your use. If you don't speak their language you may need to find someone to help translate, or fall back to google translate.</li>



<li style='clear:right'>If you receive emails from the thief, take screenshots but do not respond. You have nothing to gain by responding. If however you do respond, I suggest you say some scary cold blooded shit like Liam Neeson's character in <a href='http://www.imdb.com/title/tt0936501/'>Taken</a>. His message was perfectly direct:

<img src='http://secretGeek.net/image/liamneeson_taken.jpg' title='liam neeson demonstrates his unique phone mannerism' style='float:right;padding:4px; padding-left:30px;padding-right:10px' />
<br /><br />
<blockquote>
I don't know who you are. I don't know what you want. If you are looking for ransom I can tell you I don't have money. But what I do have are a very particular set of skills. Skills I have acquired over a very long career. Skills that make me a nightmare for people like you. If you let my website go now, that'll be the end of it. I will not look for you, I will not pursue you. But if you don't, I will look for you, I will find you and I will kill you.</blockquote><br />

On second thoughts, killing people and even threatening to kill people, are considered a tad illegal in most jurisdictions. So you might want to write that email and then delete it without sending it. A better tactic is to try and draw out the hijacker. Ideally you'll get him to explicitly ask you to give him <em>money</em> to get <em>your</em> website back. People have used emails like this as part of the evidence they provide to the gaining registrar.</p>
</li>


<li style='clear:right'>Once the gaining registrar has established the facts, you should get your domain back. You may not be able to transfer it to the registrar of your choice until the 60 days have elapsed. You may need to wait while <em>they</em> wait for the hijacker to respond to their questions. Naturally the hijacker isn't going to have a very good story, and may simply fail to reply to their questions. But even this takes time. Patience is necessary. Remember you have 60 days.</li>




</ol>


<p>That's all I've got. If something like this happens to you, or has happened to you, I wish you the best of luck.</p>
]]>
    </description>
    <pubDate>Thu, 01 Nov 2012 12:34:50 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/hijack_checklist.asp</guid>
  </item>
<item>
  <title>kv can remember it for you, wholesale</title>
    <link>http://www.secretGeek.net/kv.asp</link>
    <description>
      <![CDATA[<img src='http://secretGeek.net/image/kv.jpg' title='kv' alt='kv' style='float:right; padding:10px;'/>

<p>I've started using a groovy little command-line utility found on the internet, and I have to say I am totally enamored of it.</p>

<p>It was brought to my nebulous attention by my conspirator <a href='http://www.i-think22.net/'>Rhys</a>, who has it in his '<strong>util</strong>' folder of little tools, which I've <strong>hg clone</strong>d onto my own machine and en-pathed.</p>

<p>The tool in question is <a href='http://kv.codeplex.com'>'kv'</a>,  which is short for 'KeyValue'. You can get it here:</p>

<br />
<p><a href='http://kv.codeplex.com' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>kv.codeplex.com</a></p>
<br />


<p>Imagine you have a lot of ugly things to remember. I know you do.</p>

<p>For example you may need to remember (and frequently type out) the name of your 'dev' server, prod server, staging server, test server and so on. </p>

<p>Get kv to remember it for you!</p>

<p>At a prompt, type:</p>

<blockquote><pre>
kv dev MaxServer0412_Tangerine</pre>
</blockquote>

<p>Now we've stored the rather cumbersome and hard to remember value 'MaxServer0412_Tangerine' against the nice little key name, 'dev'.</p>

<p>So when you type:</p>

<blockquote>
<pre>kv dev</pre>
</blockquote>

<p>Two things will happen: the value will get written out into the console. Okay, sure, whatever. But far better than that: the value will get put into your clipboard.</p>

<p>Rhys uses this to store his jargon file. He works in an industry with a lot of domain specific jargon. Every time he hears a new abbreviation that the business people expect him to know, he adds it to his <code>kv</code> stash.</p>

<p>Also - the values don't have to be simple things. They can be gigantic stuff, for example: the complete works of shakespeares. You can pipe a value, or an entire file into the kv command, just give it a key to use.</p>
<blockquote>
<pre>type 'completeWorks_of_shakespeare.txt' | kv shakes</pre>
</blockquote>
<p>If you want it to forget one its keys, use the -r switch:</p>

<blockquote><pre>kv -r shakes </pre>
</blockquote>


<h2>Provenance</h2>

<p>The tool itself is based on '<a href='https://github.com/stevenleeg/boo'>boo</a>' by stevenleeg which is itself based on <a href='https://github.com/holman/boom'>boom</a> by Zach Holman.

<p>It's clearly better than both of those as it has an even shorter name. None of this three or four letter nonsense. Two letters. That's enough.</p>

<p>Here's the help it provides at the commandline:</p>

<blockquote><pre>
&gt;kv -?

kv -- a command-line key-value store integrated with the clipboard.
inspired by: https://github.com/stevenleeg/boo

usage:

kv name fred smith
saves the value, 'fred smith' under the key, 'name'

kv name
retrieve the value 'fred smith' straight to your clipboard.

kv
lists all keys

kv -r name
will remove the key 'name' (and its value) from your store

</pre></blockquote>

<p>And two more tips, for super users:</p>

<p>1. You can also pipe a value in, e.g.
<blockquote><pre>
echo Hello Fred | kv Greeting
will store 'Hello Fred' under the key 'Greeting'
type File.xml | kv myFile
will store the content of 'File.xml' under the key 'myFile'
</pre></blockquote>

<p>Even though, as I say, I found this after it was recommended by a friend, I have to admit that it's my own tool. I wrote it last year in an hour or so, as a simple demo of a little interface I was dabbling with at the time, called <a href='http://stashy.codeplex.com/'>stashy</a>. I immediately forgot about it until Rhys rediscovered it.</p>

<h2>Utils Folders! Utils Folders! Utils Folders! Utils Folders!</h2>

<p>Rhys's '<code>util</code>' folder is a thing of joy. I think he should make it globally available so people everywhere can clone it, fork it and so on.</p>

<p>I even have a name for it: Rhys's Pieces. Clever hey, Rhys?</p>

<p>Got any little tools in your own utils folder?</p>
<p>Or any way you share your utils folder?</p>
<br />
<hr />
<p><small>[Image above is of a <a href='http://en.wikipedia.org/wiki/Kliment_Voroshilov_tank'>KV Tank (Kliment Voroshilov)</a>, no relation.]</small></p>
]]>
    </description>
    <pubDate>Sun, 21 Oct 2012 11:25:23 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/kv.asp</guid>
  </item>
<item>
  <title>Hello IT Department</title>
    <link>http://www.secretGeek.net/hello_it_department.asp</link>
    <description>
      <![CDATA[ 
<p>At one time in my long and extraordinary career (<em>*cough* <strong>today</strong> *cough*</em>), I had a problem where an offshore IT department stopped replying to my emails. They had closed a support request as complete when it wasn't, and they ignored my every plea to have it reopened. Here's the email I sent, which successfully reopened the thread of communication.</p>

<blockquote>
<p><code>From:</code> Leon<br />
<code>To:</code> IT Support<br />
<code>Subject:</code> <strong>IT Service Desk request number SR0154899389 completed</strong><br />
<br />
<code>Message:</code><br />
<br />
Please reopen this ticket.<br />
<br /> 
It has been marked as complete but it is not complete.<br />
<br /> 
I have written asking for this to be reopened four times now with no response.<br />
<br /> 
Here is a picture of David Boon.<br />
<br /> 
<br />
<img src='http://secretGeek.net/image/ozbrothers.png' /><br />
The pool we are running in the office suggests that I will need to send this email eight times before I do get a response.<br />
<br /> 
Since my money is on just sending it four times, you could help a brother out and respond to me this time. Then I win!<br />
<br /> 
(actual picture may not be David Boon)<br />
</p>



</blockquote>



<p>You are welcome to reuse it if your plight resembles mine.</p>
<p>Don't worry if you don't know who David Boon is. It kind of helps if you don't. Random inclusion of an unrelated photo seems to be the key factor in inspiring a call to action. I must A/B test this idea against several indifferent IT departments.</p>
<p><small>(Image of <a href='http://en.wikipedia.org/wiki/Rob_Sitch'>Rob Sitch</a> as an Oz Brother, courtesy of <a href='http://www.champagnecomedy.com/forum/showthread.php?t=2311&page=6'>champagne comedy forum</a>).</small></p> 
]]>
    </description>
    <pubDate>Wed, 10 Oct 2012 11:23:32 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/hello_it_department.asp</guid>
  </item>
<item>
  <title>Dialog Between a Man and His Vista Laptop</title>
    <link>http://www.secretGeek.net/man_and_vista.asp</link>
    <description>
      <![CDATA[<img src='http://secretGeek.net/image/vista_shutdown_th.jpg' alt='original article before discard' style='float:right;margin:20px;margin-left:20px;margin-top:0px' />
<p>While continuing the cleanup instigated by the <a href='http://secretgeek.net/Task_hoard.asp'>previously mentioned documentary</a>, I threw out quite a lot of stuff.</p>
<p>One piece of paper had the following dialog that I transcribed before discarding. It concerns a man and his Vista laptop.</p>

<blockquote>
&mdash;Hello laptop.<br />
&mdash;Hello user!<br />
&mdash;I'd like to change some settings, can I open the control panel?<br />
&mdash;[long, long pause] No problem!<br />
&mdash;I want to change what happens when I close the lid. What happens currently?<br />
&mdash;[extended pause] Well that depends if I'm on a battery or plugged in.<br />
&mdash;Why, what's the difference?<br />
&mdash;[assume long pauses unless told otherwise] Well, if I'm on battery and you close the lid, I go into sleep mode.<br />
&mdash;And? If you're plugged in?<br />
&mdash;Well, if I'm plugged in and you close the lid, I go into sleep mode.<br />
&mdash;That's the same isn't it?<br />
&mdash;Well, I kill a few apps, just to spice it up.<br />
&mdash;I see. So what <em>is</em> sleep mode?<br />
&mdash;It's a low power mode where applications are paused.<br />
&mdash;Suspended?<br />
&mdash;No, that's suspend.<br />
&mdash;What's suspend?<br />
&mdash;It's a bit like hibernate.<br />
&mdash;Oh. What exactly is <em>hibernate</em>?<br />
&mdash;Well... it's somewhat similar to sleep.<br />
&mdash;What's the specific difference between all of those?<br />
&mdash;Hmmm. Well, let me see. It's very... There's... Well Okay. I'm not completely sure myself. So I just delete a few extra files to make it convincing. Ah, anyway, you were wanting to change a setting?<br />
&mdash;Frankly, I'm a little concerned now. But all I want to do is make sure that if I just close the lid, and if you're plugged in to a power supply, then I want you to just do nothing.<br />
&mdash;Nothing?<br />
&mdash;Just pretend like nothing's happened. Pretend I haven't event touched the lid.<br />
&mdash;Can I kill some apps?<br />
&mdash;No.<br />
&mdash;Delete a few smallish files?<br />
&mdash;No.<br />
&mdash;Move the swap file around on disk. Jiggle it a bit?<br />
&mdash;Not even that.<br />
&mdash;What if I 'clean up' the registry or terminate some services?<br />
&mdash;No, not that either.<br />
&mdash;Nothing fancy at all?<br />
&mdash;Nothing.<br />
&mdash;Okay, Sir. It's your dime.<br />
&mdash;So when I shut the lid, while you're plugged in to a power supply, what are you going to do?<br />
&mdash;Nothing much.<br />
&mdash;Nothing much?<br />
&mdash;Okay, nothing at all. I'm going to pretend you haven't even touched the lid and that you're still watching very closely. I <em>can</em> do this. I'm a pretty sophisticated operating system you know. I'm not some version two or three operating system. I am Windows Vista, the most eagerly anticipated operating system in the history of windows operating systems. All of this tricky 'do nothing stuff' is considered elementary to a system like me. Go ahead.<br />
&mdash;Okay here we go.<br />
&mdash;No problem! Bring it on.<br />
&mdash;You're definitely ready?<br />
&mdash;Ready as ever. A little bit excited actually.<br />
&mdash;Here goes.<br />
Man gingerly closes the lid. Without a pause we hear the hard drive grind to a halt. Lights flicker out.<br />
[man performs a facedesk]<br />
</blockquote>
 
]]>
    </description>
    <pubDate>Fri, 21 Sep 2012 11:20:37 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/man_and_vista.asp</guid>
  </item>
<item>
  <title>NimbleText 1.6, Codename Jetboat</title>
    <link>http://www.secretGeek.net/nimbleText_jetboat.asp</link>
    <description>
      <![CDATA[ 
<p>Jetboat, the mildly anticipated new release of <a href='http://NimbleText.com'>NimbleText</a> is out now.</p>

<p>If you don't already use NimbleText every single day then you're missing out. NimbleText is a tool for manipulating little bits of data, for formatting text, for performing ad-hoc code generation. It's a versatile little tool that every programmer, DBA, sysadmin, knowledge worker and techie should keep within reach. <a href='http://nimbletext.com/Home/Help'>Here's a two minute guide.</a></p>


<br />
<p><a href="http://nimbletext.com/Download/NimbleText.exe" style="font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;">Download NimbleText</a></p>
<br />

<p>Here's a quick rundown of the new features:</p>
<h2>Header Variables</h2>
<p> You can now refer to the first row of the data from inside any row, using a '<code>$h</code>' pattern.


<p>The new feature works like this. Say you have some simple data that includes a header row:</p>
<blockquote>
<pre>name, age
Jim, 126
Jenny, 4</pre>
</blockquote>
<p>Within your pattern you can refer to the first item in the header as <code>$h0</code>, and the second item as <code>$h1</code>, and so on. Like this:</p>
<blockquote>
<pre>
Pattern:
$each+
The person with $h0 $0 has $h1 $1
</pre>
</blockquote>

<p>The result will be:</p>

<blockquote>
<pre>The person with name Jim has age 126
The person with name Jenny has age 4</pre></blockquote>

<p>This basically means you can stash 'global variables' into the first row and access them in your pattern. Which means you can reuse your patterns more often.</p>

<h2>Counting from the right.</h2>

<p>Sometimes the data you are parsing is 'jagged' meaning different rows have a different number of columns. This can happen for a variety of reasons. In NimbleText we can't pick and choose the data we are handed. We just do our best to handle for what we get.</p>
<p>When you have jagged data, you often want to read the last column, or the second last column: basically you want to count the columns starting from the left. For example, here's some sporting data:</p>

<blockquote>
<pre>
Name, Scores (ascending)
Stu, 0, 0, 1
Jim, 1, 2, 2, 3, 8  
Stacey, 0, 0, 1, 3, 3, 9, 9
</pre>
</blockquote>

<p>Notice there is a different number of scores for each player. If you only want the last score you can use a <em>negative</em> index to count from the right:</p>

<blockquote>
<pre>$each+
The best score for $0 is $-0</pre></blockquote>

<p>Returns:</p>
<blockquote>
<pre>
The best score for Stu is 1
The best score for Jim is 8
The best score for Stacey is 9
</pre>
</blockquote>

<p><a href='http://nimbletext.com/Download/NimbleText.exe'>Download it now</a>, or <a href='http://nimbletext.com/Live'>use the online version</a>.</p>
<p>Release notes are <a href='http://nimbletext.com/Version/Notes#1.6.0.39846'>here.</a></p>
]]>
    </description>
    <pubDate>Fri, 07 Sep 2012 13:50:48 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/nimbleText_jetboat.asp</guid>
  </item>
<item>
  <title>On Task Hoarding and Todo Bankruptcy</title>
    <link>http://www.secretGeek.net/Task_hoard.asp</link>
    <description>
      <![CDATA[ 

<a href='http://secretGeek.net/Task_hoard.asp'><img src='http://secretGeek.net/image/channel4_richardwallace2_th.jpg' title='rich amonst his hoard' style='float:right; padding:10px;' /></a>

<p>Last week I watched a British Channel 4 documentary about a chronic hoarder named <a href='http://www.dailymail.co.uk/news/article-2076822/Richard-Wallace-hoarded-rubbish-seen-space.html'>Richard Wallace</a>. Fascinating stuff.</p>

<p>This was a man who hadn't had a bath in years because his bath, like everything else in his house, was covered to the ceiling in piles of collected junk. To get from one room to the next he would have to swim over the top of his junk pile, ducking under the top of the doorway. And yet he was a fairly normal guy. He wasn't like some angry Smaug, fighting to protect his golden hoard. He had a well developed sense of humour, and you could carry out a normal conversation with the guy.</p>

<p>Yet he had a profound lack of insight. Despite his incredible existence (he slept in a chair, his bed was covered in ceiling-high junk), he didn't see see that he had a psychological syndrome. Pay attention to this, because it's kind of the point: He didn't believe he had an excessive hoarding habit, he felt his real problem was a shortage of storage.</p>
<p>I think what scared me was that he was a little like me. Or a little like you. So it got me thinking about my own hoarding tendencies.</p>
<p>It's normal to do some amount of collecting. I've always done a little here and there. I have boxes and boxes of books under the house. I have a record collection somewhere. I have a jar of buttons (more on that later). But all of that is under control. (After watching the documentary I immediately threw away a box of msdn magazines that I've been holding onto for too long.)

<a href='http://secretGeek.net/Task_hoard.asp'><img src='http://secretGeek.net/image/Smaug_Tolkien2.jpg' title='smaug and his hoard' style='float:right; padding:10px; clear:right' /></a>

<p>Instead, there is a completely <em>different</em> form of hoarding I engage in, that <em>has</em> gotten out of control.</p>
<p>The thing <em>I</em> collect is incomplete projects. Unfinished work.</p>

<p><em>My list of incomplete projects is my own personal crazy hoard.</em></p>
<p>To get from one task to the next, I need to swim over the ceiling-high pile of incomplete tasks, stacked up from every stray project idea I've ever had.</p>

<p>Like a crazy hoarder I mistake the root cause of my growing mountain of incomplete work. The hoarder thinks he has a storage problem (when he really has a 'throwing things away problem'). I say I am 'time poor' as if the problem is that poor me is given only 24 hours in a day. It's more accurate to say... what exactly? It seems crazy for a crazy person to use his own crazy reasoning to diagnose his own crazy condition. Maybe I too easily add new projects to my list, or I am too reluctant to exit from unsuccessful projects. Perhaps I am too reluctant to let a task go, to ship what I've done. They're never perfect, never good enough.</p>
<p>And I know I'm not alone in making the easy claim that I am 'time poor'. So many people claim to be time poor, when really we are poor at prioritizing, or poor at decisiveness, or don't know how to say 'no' (...to other people, to our own ideas).</p>
<p>If only I had a hidden store of time, or if only I had magical organisation tools, or if only I could improve my productive throughput, then, only then would I be able to get things done, to consolidate the growing backlogs and todo lists into one clear line of work, and plough through it like an arctic ice breaker carving its way through a sheet of ice.</p>
<p>So I have to declare todo bankruptcy. Throw everything out and start again.</p>
<p>I've gone back to the <a href='https://trello.com/'>trello</a> boards and slashed and pruned and archived and revised and reordered until the whole todo landscape started to make sense. I've dragged in items from other sources (from moleskine's and from starred items in gmail, from 'TODO' comments in my code, from various TODO.txt files buried on my hard-drive... from all over.)

<p>First up, a lot of projects have moved from the maybe pile to the 'never no way' pile.</p>
<p>Example of projects that are officially cancelled as of this moment are:</p>

<blockquote>
<h2>Not To Do</h2>
<ol>
<li>'Cop Dog Buddies' -- movie script about two mismatched police dogs thrown together to hunt down their masters' killers.</li>
<li>'Registry on Rails' -- the web development framework from hell.</li>
<li>Orable -- (pronounced "'orrible") my poor man's oracle IDE</li>
<li>OCD-targeted one-page website "have i left the iron on?"</li>
<li>A life-sized full-body tattoo of my own body, all over my body.</li>
<li>My pro wrestling career</li>
<li>My rap battle ambitions</li>
<li>A range of <a href='http://blog.sqlauthority.com/'>Pinal Dave</a> T-Shirts</li>
<li>Twee -- a micro-blogging service where posts can only be three words long and must be valid dictionary words in your language.</li>
<li>'Vampurr' trilogy -- epic love-triangle between goth-girl tattooist, ear-stretching vampire and shape-shifting battle-cat.</li>
<li>Word as a database -- it's Word. As a database.</li>
<li>Operation Butter-knife</li>
<li>Choosing the right fonts</li>
<li>Operation 'Taser my enemies in the face'</li>
<li>Boss monsters feature in unreleased malware easter egg</li>
<li>'Silmarillion with sock puppets' -- treatment for a feature film</li>
<li>'Top Gut' -- movie script about the fat camp for the fattest of the fat</li>
</ol> 
</blockquote>
<p>Okay, that's a slightly modified version of the real list. The real list is a lot longer and a lot sadder. But the <em>actual</em> thing I'll <em>actually</em> do next is:</p>
<blockquote>
<h2>To Do</h2>
<p>1. Put out NimbleText 1.6.</p>
</blockquote>
<p>People have been nagging me about this for a while, and it's pretty much ready, if I can just stop distracting myself with all the other craziness.</p>
<p>Stay tuned.</p>
]]>
    </description>
    <pubDate>Fri, 31 Aug 2012 06:02:53 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/Task_hoard.asp</guid>
  </item>
<item>
  <title>Developer UI Done Right: Mercurial Commandline!</title>
    <link>http://www.secretGeek.net/merc_hints.asp</link>
    <description>
      <![CDATA[<p>Developer tools are famous for having bad usability. In <a href='http://youmustget.it/Product/Detail/219'>Code Complete</a> Steve McConnell listed this as a case of <a href='http://tvtropes.org/pmwiki/pmwiki.php/Main/TheCobblersChildrenHaveNoShoes'>'the cobbler's children go barefoot'</a>. (A fancier term for the same effect is <a href='http://www.hitfix.com/blogs/the-fien-print/posts/2009-1-23-sundance-reviews-shrink-and-arlen-faber'>'<em>vocational irony.</em>'</a> you know, like House MD).</p>
<p>But here's a case where User Experience in a very <em>very</em> developer-specific tool is surprisingly polished, in a way that you wouldn't quite expect.</p>
<p>Follow along if you will...</p>
<p>I'm using mercurial and I decide my work is ready to be pushed. At this point, the stack of tasks in my head (the things I'm trying to achieve) just says "push."</p>
<p>I try to push.</p>

<blockquote>
<pre>
C:...>hg push
pushing to ...
searching for changes
abort: push creates new remote head a751ec334b3e!
<strong>(you should pull and merge or use push -f to force)</strong>
</pre>
</blockquote>

<p>Interesting! It failed, but not in the typical <em>'pages and pages of <span style='color:red'>angry red</span> error messages'</em> way. Instead I get a one line error description and then this delicious hint -- I can use 'pull and merge' to get past the problem.</p>
<p>(Note that I've elided any personal details, and hashes have been modified to protect the innocent)</p>
<p>So now the stack in my head says "pull, merge, push".</p>
<p>So I pull.</p>

<blockquote>
<pre>
C:...>hg pull
pulling from ...
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files (+1 heads)
<strong>(run 'hg heads' to see heads, 'hg merge' to merge)</strong>
</pre>
</blockquote>

<p>This succeeded nicely. But again there is a hint. Having performed the pull, it looks like I need to merge.</p>
<p>The hint reinforces what the previous command told me and helps me to confidently move in the direction I was already headed. (Or: it serves to remind me that I need to merge, in case I had forgotten). The stack in my head now says "merge, push."</p>
<p>I attempt the merge.</p>

<blockquote>
<pre>
C:...>hg merge
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
<strong>(branch merge, don't forget to commit)</strong>
</pre>
</blockquote>

<p>It tells me the merge succeeded. This is pretty spectacular all by itself, but for users of distributed version control systems it's a common enough occurrence, so I'll skip over that bit. Again, I get a neat little hint. It reminds me to commit before I do anything else. So the stack in my head now says "commit, push"</p>
<p>I attempt to commit...</p>


<blockquote>
<pre>
C:...>hg commit
...
</pre>
</blockquote>

<p>This last command gives me only happy messages, which I've not included as they're of no interest. There is no hint what to do this time, as mercurial does not remember that my ultimate goal here was to push. But I haven't forgotten that simple goal. So I try the last remaining step: I push.</p>

<blockquote>
<pre>
C:...>hg push
pushing to ...
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files
</pre>
</blockquote>

<p>And everything is right in the world.</p>

<p>There's something just so neat about the hand-holding that mercurial performs throughout the exercise. I want to pick it up and cuddle it and rub my nose against its little nose.</p>

<p>(of course frequent mercurial users will know shorter and slightly better ways to achieve this same thing, but these little step by step hints are completely adequate for the occasional user like me.)</p>

<p>Now why was all of this amazing? As I said, it's a developer tool, so that's already a good reason to expect poor UI. </p>

<p>But secondly, it's an open source tool. There is a belief that open source software favours usability less than other things.</p>

<p>Third, the hints that were so helpful are a form of <em>documentation</em>. And open source projects very often get criticised for their lack of documentation. Again we have a nice counter example.</p>

<p>Fourth -- it's a commandline tool! A commandline tool! This is a category of software that is not known for being helpful and forgiving to the beginner or infrequent user. Yet mercurial is demonstrating a way in which it is possible to be kind to such users.</p>

<p>All up: I continue to find it nice on a whole bunch of levels. Hat tip to mercurial.</p>

<p>(Next article in this series: "Mercurial And How To Undo a 'hg -forget *' Command, Or, Mercurial, You Evil Unusable Bastard, Why Hast Thou Forsaken Me? Undo! Undo!")</p>
 
]]>
    </description>
    <pubDate>Mon, 16 Jul 2012 11:53:25 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/merc_hints.asp</guid>
  </item>
<item>
  <title>Rediscovering the Amstrad CPC 6128</title>
    <link>http://www.secretGeek.net/amstradBook.asp</link>
    <description>
      <![CDATA[<img src='http://secretgeek.net/image/amstradinstructions.jpg' style='border:1px solid #CCC;margin:15px;margin-top:0px;padding:5px;float:right;background-color:#FFF;' >
 
<p>I recently inherited the original instruction manual from the first computer my family ever owned, the Amstrad CPC 6128 User Instructions.</p>

<p>Flicking through this magnificent compendium has sent me on a serious nostalgia trip. It wasn't long before I downloaded an <a href='http://arnold.emuunlim.com/download/index.html'>Amstrad emulator</a> (<a href='http://www.winape.net/downloads.jsp'>or two</a>) and began to relive some of the programming fun of Amstrad Basic. </p>

<p>The book takes you through every aspect of the computer, the hardware, the operating system, and two programming languages (BASIC <em>and</em> Logo). And it starts from absolute beginner level, in a way that no modern set of instructions ever needs to. Here's an excellent example:</p>
<blockquote><p>
<strong>Important</strong> <br />
When you reach the right hand edge of the screen by entering 40 characters on a line, 
the next character will automatically appear on the following line at the left edge of 
the screen. This means that you should <strong>NOT</strong> press <strong><code>[RETURN]</code></strong> as those of you accustomed to typewriters might press a carriage return towards the right edge of a 
page.</p>
<p>The computer does this automatically for you, and will react to an unwanted 
<strong><code>[RETURN]</code></strong> by printing an error message - usually a <code>Syntax error</code>, either there 
and then, or when the program is run. 
</p>
</blockquote>


<p>...that's not a detail typically cover in a more recent text. And it recurs throughout the early chapters of the book, as they explicitly tell you where to hit return in case you've miraculously forgotten. They only stop adding the word <strong><code>[RETURN]</code></strong> when they get up to teaching you about the <code>return</code> keyword (used after a <code>gosub</code>, for awesome fun times.)</p>

<p>Demonstrating the use of GOTO, GOSUB and RETURN leads to this interesting reflection:</p>
<img src='http://secretgeek.net/image/sector_track_50.png' style='border:1px solid #CCC;margin:15px;padding:5px;float:right;background-color:#FFF;' >

<blockquote><p>See how much tedious typing we've saved ourselves? Well designed subroutines are 
a principal part of computing. They lead to 'structured' programs, and develop good 
programming habits.</p></blockquote>
<p>...all by itself this seems to conflict with the ideas put forth in <a href='http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF'>'Go-to Statement Considered Harmful'</a> but the very next paragraph really takes it up a notch:</p>

<blockquote><p>
Always bear in mind when writing sub-routines, that you do not necessarily have to 
Jump into' the sub-routine at the same point, i.e. its beginning. A sub-routine written 
from lines 500 to 800 can be called by: GOSUB 500, or GOSUB 640, or GOSUB 790. </p></blockquote>

<p>...this isn't what you call the <strong>gold standard</strong> of structured programming. ;-)</p>

<a href='http://xkcd.com/292/'><img src='http://secretgeek.net/image/goto.png' title='queue raptors' style='border:0px solid #000;padding:40px' /></a>


<p>The more I got into it, the more I enjoyed it. I was surprised at how much I'd forgotten, but equally surprised at how ready those memories were to spring back into place. My friend Dr Richard (of <a href='http://www.brisparks.com.au/'>brisbane parks</a> fame) pointed out that by reawakening such old neurons and marking them as new again, the brain is bound to believe that those memories are of very high importance and mark them as always hot. So now it's likely I'll never forget Amstrad Basic again.</p>

 
<img src='http://secretgeek.net/image/amstrad_circle_screen.png' style='border:1px solid #CCC;margin:15px;padding:5px;float:right;background-color:#FFF;' >

<p>One intriguing idea from the Amstrad, which seems to have been abandoned by the side of the information highway, is '<em>the copy cursor</em>'.</p>
<p>Consider this startling example of using '<em>the copy cursor</em>' to correct a typo. Their example builds on this code sample, which has a missing 'r' on line 10:</p>

<blockquote><pre>
10 input "what is you name";a$ <strong><code>[RETURN]</code></strong> 
20 input "what is your age";b <strong><code>[RETURN]</code></strong>
30 print "I must say";a$;" you dont 
look";b;"years old" <strong><code>[RETURN]</code></strong> 
</pre></blockquote>

<p>Here's how a coding ninja would fix that typo, in the copy cursor era:</p>

<blockquote>
<p><strong>Copy Cursor Method</strong><br /> 
The copy cursor is another cursor (in addition to the one already on the screen) which 
comes into view when you hold down <strong><code>[SHIFT]</code></strong> and press one of the cursor keys. It then 
detaches itself from the main cursor and can then be moved around the screen 
independently.</p>
 
<p>To correct the mistakes in line 10 and 30, hold down the <strong><code>[SHIFT]</code></strong> key then press the 
cursor up key until the copy cursor is positioned over the very beginning of line 
10. You will notice the main cursor has not moved, so there are now two cursors on 
the screen. Now press the <strong><code>[COPY]</code></strong> key until the copy cursor is positioned over the 
space between 'you' and 'name'. You will notice that line 10 is being re-written on the 
last line and the main cursor stops at the same place as the copy cursor. Now type in 
the letter 'r'. This will appear on the bottom line only.</p> 

<p>The main cursor has moved but the copy cursor stayed where it was. Now press the 
<strong><code>[COPY]</code></strong> key until the whole of line 10 is copied. Press <strong><code>[RETURN]</code></strong> and this new line 
10 will be stored in the memory. The copy cursor disappears and the main cursor 
positions itself under the new line 1 0. To correct the second mistake, hold down 
<strong><code>[SHIFT]</code></strong> and press the cursor up key until the copy cursor appears over the 
very beginning of line 30.</p> 

<p>Press <strong><code>[COPY]</code></strong> until the copy cursor is positioned over the quotation marks next to 
say. Now press the space bar once. A space wiil be inserted on the bottom line. Hold 
down the <strong><code>[COPY]</code></strong> key until the whole of line 30 is copied, then press <strong><code>[RETURN]</code></strong>. </p>
</blockquote>

<p>(Using an Amstrad emulator with a windows keyboard, I found that the Pg-Dn key acted as the <strong><code>[COPY]</code></strong> key).</p>

<p>But software quality assurance and refactoring magic aren't just left up to the wonderous copy cursor. There's another awesome tip on detecting errors in your code. The trick is to write your code in lowercase and see that the interpreter finds your keywords and shifts them to uppercase:</p>

<blockquote><p>

<strong>IMPORTANT</strong><br />
In the above program, and in later chapters and listings in this manual, BASIC 
keywords will appear in upper case (CAPITAL) letters. This is how keywords 
appear when a program is LISTed by the computer. In general it is preferable 
that you type instructions or programs using lower case (small) letters, since it will 
help you spot typing mistakes when LISTing the program - (because the 
mis-typed BASIC keyword will NOT be converted to upper case). </p></blockquote>

<p>I find something adorable in their vociferous way of describing the technique. The modern age is all too brief in its belting-around-the-headedness-about-the-simple-things. These days it's all <em>"merge this, rebase that, man page if you don't grok"</em> and the eyes are left spinny.</p>

<p>I've had some recent fun building simple programs on the Amstrad (emulators) but there's too much to cover here. I'd like to write a little about it, if I find the time, but that's enough for now.</p>

<p>Just reviewing the book was a joy in itself. Whoever said "nostalgia isn't what it used to be" must've been one of those filthy Commodore 64 programmers, I guess.</p> 
 
]]>
    </description>
    <pubDate>Fri, 25 May 2012 13:36:19 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/amstradBook.asp</guid>
  </item>
<item>
  <title>Just Wally</title>
    <link>http://www.secretGeek.net/justWally.asp</link>
    <description>
      <![CDATA[<p>The apocalypse came suddenly. Some kind of worm, virus, trojan -- some kind of <a href='http://www.goodreads.com/book/show/9763010-zero-day'>Mark Russinovich doomsday scenario</a>. It spread so fast no one had a chance to react. It lit up every computer screen, obliterating every computer user in the world. Every last worker was obliterated, right at their desk. All that remained was a tiny pile of ashes on every seat.</p>
<p>Only Wally was spared. While everyone else was at the desks working, Wally was wandering the halls, holding a coffee cup.</p>
<p><img src='http://secretGeek.net/image/wally_103418_done.strip.gif' style='padding:20px'></p>

<p>'Just Wally' is a cartoon that removes all the unneccessary elements from <a href='http://Dilbert.com'>Dilbert</a>, and leaves just the hero himself, Wally, wandering the empty building, holding meetings with himself, filling his loneliness with imagined interactions.</p>

<p><img src='http://secretGeek.net/image/wally_104571_done.strip.gif' style='padding:20px'></p>

<p>Wally has always been the truest character in Dilbert. I've met a few Dilberts in my time. I've met a few Pointed Haired Bosses. But just about everyone is at least part-Wally. And more than a few have been pure-Wally. You know who you are.</p>


<p>Some people theorise that the true story of 'Just Wally' is that Wally is the one who died. This is his limbo, wandering alone, unable to interact with the living.</p>

<p>Others say Wally has fallen into a coma. This is his extended delusion. He cannot tell dream from reality, sarcasm from seriousness. What exactly is a dream? What exactly is a joke?</p>

<p><img src='http://secretGeek.net/image/wally_109704_done.strip.gif' style='padding:20px'></p>

<p>The words of <a href='http://www.goodreads.com/book/show/5113.Franny_and_Zooey'>JD Salinger</a> are relevant here, as always.</p>

<blockquote><p>"It isn't just Wally. It could be a girl, for goodness' sake. I mean if he were a girl - somebody in my dorm, for example, - he'd have been painting scenery in some stock company all summer. Or bicycled through wales. Or taken an apartment in New York and worked for a magazine or an advertising company. It's everybody, I mean. Everything everybody does is so - I don't know, not wrong, or even mean, or even stupid, necessarily. But just so tiny and meaningless and - sad-making.</p>
<p>And the worst part is, if you go bohemian or something crazy like that, you're conforming just as much as everybody else, only in a different way."</p></blockquote> 


<p><img src='http://secretGeek.net/image/wally_104042_done.strip.gif' style='padding:20px'></p>

<h2>Tiny and meaningless and sad-making.</h2>
<p>Tiny and meaningless and sad-making. 'Just Wally' makes us stop and ponder the futility of everything we do, everything we think and everything we are.</p>

<p><img src='http://secretGeek.net/image/wally_105821.strip_done.gif' style='padding:20px'></p>



<p>In the style of <a href='http://garfieldminusgarfield.net/'>Garfield minus Garfield</a>, Just Wally plays upon the maxim of my old buddy Antoine de Saint-Exupery:</p> 
<blockquote><p>"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away"</p></blockquote>
 
]]>
    </description>
    <pubDate>Sat, 12 May 2012 02:59:08 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/justWally.asp</guid>
  </item>
<item>
  <title>The Correct Order for a First Time Viewing of The Lord Of The Rings</title>
    <link>http://www.secretGeek.net/lotr_chopsuey.asp</link>
    <description>
      <![CDATA[ 
<p>After reading <a href='http://www.hanselman.com'>Scott Hanselman</a>'s post about <a href='http://www.hanselman.com/blog/TheNerdParentsGuideWhenAndHowToIntroduceYourKidsToStarWars.aspx'>introducing your younglings to Star Wars</a>, I was intrigued by the suggested <a href='http://static.nomachetejuggling.com/machete_order.html'>'Machete order'</a>
(courtey of Rod Hilton)</p>

<ul>
<li>4 - Star Wars: A New Hope</li>
<li>5 - Empire Strikes Back</li>
<li>2 - Attack of The Clones</li>
<li>3 - Revenge of the Sith</li>
<li>6 - Return of the Jedi</li>
</ul>

<p>Which lead to deep conversations with myself about which order I should use when introducing my daughers to 'The Lord of the Rings'.</p>

<p>The three films can be arranged into 6 possible non-repeating combinations:</p>

<ul>
<li>Fellowship, Towers, King</li>
<li>Fellowship, King, Towers</li>
<li>Towers, Fellowship, King</li>
<li>Towers, King, Fellowship</li>
<li>King, Fellowship, Towers</li>
<li>King, Towers, Fellowship</li>
</ul>

<p>All of which have their own pluses and minuses, but none of which would qualify as a true 'machete' reordering. </p>

<p>I finally settled on the following order, which you'll agree is the best possible version of events:</p>


<ul>
<li>1. The Two Towers -- A good story always starts in the midst of the action, and leaps past the boring parts.</li>
<li>2. The Hobbit, An Unexpected Journey -- having established the story we now move learn the origin of the Ring and Gollum.</li>
<li>3. How to Train your Dragon -- the loveable Toothless and Hiccup show us that not all dragons are nasty Smaugs.</li>
<li>3a. Read all of the books -- that way you can complain bitterly about the missing 'Scourge of the Shire' segment during:</li>
<li>4. Return of the King, Disc 2 -- 5 minutes of chucking a ring in a pit, a quick eagle ride, and two hours saying goodbye.</li>
<li>5. Return of the King, Disc 1 -- Awesome battle scene. Best war ever.</li>
</ul>

<p>I dub this the Chop-Suey Reordering, and in line with <a href='http://www.theverge.com/2012/5/7/3004697/oracle-google-trial-deadlocked-jury-partial-verdict'>Oracle's copyright on the arrangement of the Java Api's</a>, I claim ownership of this and all derivative reorderings of the LOTR franchise.</p>
]]>
    </description>
    <pubDate>Tue, 08 May 2012 04:22:21 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/lotr_chopsuey.asp</guid>
  </item>
<item>
  <title>A new era for Android.</title>
    <link>http://www.secretGeek.net/android.asp</link>
    <description>
      <![CDATA[ 
<p>Occasionally, marketers send me press releases in the hope I'll blog about them. Ordinarily I refuse to be manipulated by such a ploy, but I thought this one about android was worth a little discussion. 
I've always thought that android phones look interesting but only from the point of view of a tinkerer. This new direction seems to offer something more.</p>

<p>Here's a few relevant excerpts:</p>

<img src='http://secretGeek.net/image/android_icst.png' alt='food phone' style='margin:10px;float:right;' />

<blockquote><p>Android, the world's leading free, open source platform for everything beyond smart phones, and the world's most popular phone amongst Android software developers and Google employees, is proud to announce the discovery of their first Consumer.</p> 
 
<p>The Android developer community first suspected the existence of the Consumer after finding non-Google IP addresses in the log file of an Android Developer Forum. The discovery was
quickly escalated to Google management who sent a rapid response Privacy Intrusion Team to perform expanded analysis of his web searches, browser, email and telephone usage. They were thrilled to discover that the lurker was a genuine Android customer who was neither an Android software developer or a Google employee.</p> 
 
<p>The potential existence of such a Consumer had been hotly debated on Android developer forums for years. But even the most optimistic Android enthusiasts had assumed that the debate was purely theoretical.</p>
 
<p>Google had previously spent millions of dollars placing 'Angry Birds' in their 'Google Play' app store, in the hope that it could potentially attract a Consumer to consider using the Android platform for Consumer Purposes. Google's Privacy Intrusion Team have revealed that analysis of the Consumer's correspondence offer no clear rationale for why he purchased an Android phone from a market place crowded with more suitable offerings. Skeptics have taken this as an indication that the Consumer's existence could be the result of Google Finland's controversial 'tag and release' program where members of the public were anaesthetised, given an Android phone, and released back into the population.</p>
 
<p>This new phase of the Android platform is an exciting time. Predicting an influx of Consumers, developers have quickly raced to make the phone more technically intimidating and to provide an even more fractured range of devices. Google employees remain unaware of anything that has happened to non-Google employees.</p>
 
<p>The Consumer is now considering getting into Android development, and has recently taken a job at Google.</p>
</blockquote>

<p>Crazy times. Next they'll be announcing the discovery of a teenager who wants a Zune.</p>
]]>
    </description>
    <pubDate>Fri, 23 Mar 2012 12:37:13 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/android.asp</guid>
  </item>
<item>
  <title>Mind-boggling Demo of New Gaming Genre, aka Folder-Based Hangman, aka Fun with Recursion</title>
    <link>http://www.secretGeek.net/folderGame.asp</link>
    <description>
      <![CDATA[<p>I had a crazy idea recently for a new game - a game that defines an entire new *genre* of computer game, and a new style of programming computer games. Whether or not this idea will go on to change the way all computer games are written, I will let history decide.<p>

<p>It's such a simple idea that I don't know how it couldn't have possibly existed earlier. It doesn't require
massive graphic capabilities, no CUDA NUMA GPGPGPU and the like -- it's an idea so profoundly simple that you'll
be scraping your jaw off the floor with a spoon before you finish reading this blog post. </p>

<p>You run the 'game' and it sets up a directory structure to represent every possible state of the game. To play the game, you inspect the current folder, look at the currently available sub folders, and choose which one to navigate into. Each sub folder you see represents the next possible state of the game.</p>

<p><strong>There is no executable program running when you are playing. The game is just your act of navigating the folder structure. It's a clever form of madness!</strong></p>

<p>Here's some screenshots that show me playing the game, in a command prompt.</p> 

<p>I've changed my prompt to just a 'greater than' sign, by typing '<code>prompt $g</code>', to make it cleaner. Old-school DOS wizards do this kind of thing all the time. Hipster kids, try and keep up.</p>

<p>First I type '<code>dir /b</code>' to get a clean view of the current folder.<p>
<p> There is only one folder, '<code>__PLAY HANGMAN__</code>' so I navigate into it by typing&nbsp; '<code>cd[TAB][Enter]</code>'. <strong> The game has begun.</strong> </p>
<img src='http://secretGeek.net/image/shot0.png' alt='' style='padding:10px' /><br />
<p>Looking in that folder I see the empty scaffold, three underscores (representing a 3 letter word) and the available letters listed down the left hand side. We're playing with a reduced alphabet to keep the number of permutations within a reasonable amount.</p>
<img src='http://secretGeek.net/image/shot1.png' alt='' style='padding:10px' /><br />
<p>My first guess is the letter 'A'. To make this guess I type '<code>cd A[tab]</code>'. When I type '<code>dir /b</code>' to inspect the new state of the game I see that it was a good guess, as one of the letters of the word has been filled in. Also there is an 'x' next to the 'A' indicating that that letter has been guessed. That's all there is to it. Hear that pop? That was your cerebellum exploding through your temporal lobe.</p>
<img src='http://secretGeek.net/image/shot2.png' alt='' style='padding:10px' /><br />
<p>If I try guessing 'A' again, all I find is a folder containing a file named 'You have already guessed that letter.' To undo my mistake I back out by typing '<code>cd ..</code>' (You could, <em>theoretically</em> use this technique to undo any move, but that would be unsportsmanlike.)</p>
<img src='http://secretGeek.net/image/shot3.png' alt='' style='padding:10px' /><br />
<p>A couple of moves later and I've guessed every letter:</p>

<img src='http://secretGeek.net/image/shot8.png' alt='' style='padding:10px' /><br />
<p>The word is 'CAB'. There's no particular fanfare. Just the word 'WIN' declaring my victory.</p>

<p>Okay, now you've seen the whole thing I hope you're aching to not just download the game, but to write your own entry into this brave new genre. You could do for Gehtto-Folder-Games what John Carmack did for first person shooters!</p> 
<p>I'd love to see an implementation of tic-tac-toe, aka, naughts and crosses. Also, hangman could be minified by using <a href='http://technet.microsoft.com/en-us/sysinternals/bb896768'>junctions</a> (i.e. symbolic links) -- I'd love to see that implemented. The possibilities for new games are pretty much endless. Maybe six or seven.</p>

<p>Okay let me level with you. The mathematics of this idea were just ridiculous. For a full 26 character alphabet, I would've killed my little computer. (Care to accurately calculate how many folders are created for the given alphabet?) It's all based around N-factorial where N is the size of the alphabet. Factorial is not something you want to see in the real world. </p>

<p>I'm on holiday at the moment, so the only computer available to write it on was my dell mini, which doesn't have any serious coding environment. So rather than write it as a console app in visual studio (or even a powershell app) I wrote a javascript page that generates a batch file. It's very niche.</p>

<p>This also turned into an opportunity to learn the ins and outs of getting recursion wrong with javascript. The most common mistake you make with recursion in javascript, it turns out, is forgetting to declare a local variable. This means that the variable becomes global and your recursion goes nuts. Don't make that mistake. When your code is creating subfolders all over your hard drive it's a particularly painful mistake. It took me considerably less time to write the program than it did to debug it, and (considerably*considerably) less time to debug than the time to clean up all the folders left in unexpected places.</p> 
<p>But the funnest bit was the ascii sprite code.</p>

<p>I had one array that showed the final hanged man:</p>
<pre>
var hangyPicture = [
'   _______   ',
'   I     I   ',
'   I     O   ',
'   I   --I-- ',
'   I    I I  ',
'   I         ',
'--===--      '];
</pre>
<p>(Side point... why wasn't my ascii art better than this? Because | and \ are not valid in folder names.)</p>
<p>And I had another array that showed how many misses were required before a given character of the hangyPicture was shown:</p>
<pre>
var hangyMask = [
'             ',
'             ',
'         1   ',
'       33233 ',
'        4 4  ',
'             ',
'             '];
</pre>
<p>Then, with those two arrays in place, I can work out the names of the folders to create. I walk through the mask, one character at a time, and compare the digit I find to the current number of missed guesses. If the digit I find is less than (or equal to) the current number of missed guesses, then I include that character in the folder name, otherwise I mask it out with a space. Ah, I give in -- it's easier to just show the code:</p>

<pre>
for (var h in hangyPicture) {
  // use hangyMask[h] and numberOfMisses to mask chars out of hangyPictures[h] 
  for(var i = 0; i < hangyMask[h].length; i++) {
    if (hangyMask[h][i] == ' ' || hangyMask[h][i] <= numberOfMisses) {
      folders[h] += hangyPicture[h][i];
    } else {
      folders[h] += ' ';
    }
  }
}
</pre>
<p>Okay. Now you've been enlightened with the future of ultra-ghetto folder-based gaming, go ahead and make your own. I can wait.</p> 
<br />
<p><a href="http://secretGeek.net/ghettoHangMan.html" style="font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;">Here's the code</a></p>
<br />
<p>The accompanying program is a piece of javascript that creates a windows <em>batch</em> file. You run the batch file.</p>
 
 
]]>
    </description>
    <pubDate>Sat, 07 Jan 2012 10:57:31 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/folderGame.asp</guid>
  </item>
<item>
  <title>Got CSV in your javascript? Use agnes.</title>
    <link>http://www.secretGeek.net/agnes11.asp</link>
    <description>
      <![CDATA[ 

<img src='http://secretGeek.net/image/logo_r_t_s.png' style='float:right; margin:5px' />

<p>The only things that will survive the forthcoming nuclear+zombie apocalypse are cockroaches, javascript and <a href='http://en.wikipedia.org/wiki/Comma-separated_values' rel='nofollow'>CSV</a>.</p>

<p>So I've written an open source javascript library, <code>agnes.js,</code> that the cockroaches can use for dealing with CSV from javascript. And in the brief pre-apocalypse era you can use it too.</p>


<br />
<p><a href="http://agnes.codeplex.com/releases/view/77617" style="font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;">Download the zip</a></p>
<br />

<p>I've <a href='http://secretgeek.net/csv_trouble.asp'>written before</a> about how CSV starts off looking easy, but quickly descends into a world of insanity. So in javascript land, let <code>agnes</code> handle all the nasty quirks and edge cases (embedded delimiters, qualifiers, nulls and so on).</p>

<p>I wrote a bunch of unit tests to go with it, so you can tell exactly what it does with each weird bit of input you can throw at it.</p>

<p>You can download it from <a href='http://agnes.codeplex.com'>agnes.codeplex.com</a></p>

<p>This was a particularly fun little bus project, and what I like best about <em>agnes</em> is the content you get when you download her.</p>

<p>The <a href='http://secretGeek.net/agnes/readme.html'>readme</a> file has executable examples, that work by having a chunk of code displayed in a div, which is the exact code that is grabbed and executed when you click 'Try it'.</p>

<br />
<p><a href="http://agnes.codeplex.com/SourceControl/BrowseLatest" style="font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;">Browse source code</a></p>
<br />

<p>I like the unit tests that come with it, and the little <a href='http://secretGeek.net/agnes/tests.html'>unit test runner.</a> I could've gone really overboard with it, but I stopped myself before it went too far.</p>

<p>And I like the sample that performs <a href='http://secretGeek.net/agnes/twoWay.html'>Csv to Json conversion</a>, back and forth, back and forth. My favourite part of that is using html entities in the button titles, for left and right arrows.</p>

<br />
<p><a href="http://secretGeek.net/agnes/twoWay.html" style="font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;">Try it out</a></p>
<br />

<p>Now that I've got <code>agnes</code> out of the way, hopefully I can focus on my new bilion dollar idea, <a href='http://youmustget.com'>youmustget.com</a></p>
]]>
    </description>
    <pubDate>Sun, 27 Nov 2011 03:07:28 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/agnes11.asp</guid>
  </item>
<item>
  <title>I went to write down a book name and founded an internet empire instead.</title>
    <link>http://www.secretGeek.net/bought_youmustget.asp</link>
    <description>
      <![CDATA[ 
 
 
<a href='http://www.hammacher.com/Product/Default.aspx?sku=11862' rel='nofollow' style='float:right; clear:right; margin:5px;margin-top:0px;'><img src='http://secretGeek.net/image/tron-motorcycle.jpg' alt='tron motorcycle just 55K' style='border:2px solid #AAA' /></a>
<a href='http://www.facebook.com/pages/LAIKAhouse/162077150510565' rel='nofollow' style='float:right; clear:right;margin:5px;margin-top:50px;'><img src='http://secretGeek.net/image/at-at-dog-costume.jpg' alt='AT AT dog costume you must have' style='border:2px solid #AAA' /></a>
 
<p>Yesterday <a href='http://callvirt.net/blog/'>Joel</a> told me, 'hey you really should read  
<a href="http://www.amazon.com/gp/product/0393072231/ref=as_li_ss_tl?ie=UTF8&tag=secretgeek-20&linkCode=as2&camp=217145&creative=399369&creativeASIN=0393072231">"The Big Short"</a>
 by Michael Lewis' -- and I thought, yes, I'll write that in my list of books I must get and when I have a chance I'll order it and all the other books in my list of books i must get.</p>

<p>Looking through my iphone I was shocked to find I don't even *have* a list of books I must get. I've got a list of which Woody Allen movies I haven't seen, and I have a list of which Jeeves and Wooster books I own (or own twice) so I don't accidentally buy them again (or again again), but no "Books I must get". </p>

<p>And I realised it's not just books that I keep forgetting. It's everything in our stupid materialist world. It's gadgets, music, movies, games, t-shirts, toys, gifts for my wife, baby stuff, apps, power tools -- a whole big fat materialist world full of stuff I must get, that, realistically i'll never get, but which my inner taxonomist wouldn't mind having a list of somewhere.</p>

<p>Suddenly, before I could stop them, my hands had rushed off and spent 9.95 to buy all of the following websites...</p>



<ul>
<li>http://things.youmustget.com</li>
<li>http://books.youmustget.com</li>
<li>http://movies.youmustget.com</li>
<li>http://games.youmustget.com</li>
<li>http://gadgets.youmustget.com</li>
<li>http://apps.youmustget.com</li>
<li>http://stocks.youmustget.com</li>
<li>http://software.youmustget.com</li>
<li>http://dvds.youmustget.com</li>
<li>http://jokes.youmustget.com</li>
<li>http://vaccinations.youmustget.com</li>
<li>http://tattoos.youmustget.com</li>
<li>http://cars.youmustget.com</li>
<li>http://piercings.youmustget.com</li>
<li>http://hookers.youmustget.com</li>
<li>http://starewarsstuff.youmustget.com</li>
<li>http://drugs.youmustget.com</li>
<li>http://websites.youmustget.com</li>
<li>http://cakes.youmustget.com</li>
<li>http://clothes.youmustget.com</li>
<li>http://bikes.youmustget.com</li>
<li>http://girlfriends.youmustget.com</li>
<li>http://babystuff.youmustget.com</li>
<li>http://diseases.youmustget.com</li>
<li>http://travel.youmustget.com</li>
<li>http://tshirts.youmustget.com</li>
<li>http://shirts.youmustget.com</li>
<li>http://wines.youmustget.com</li>
<li>http://beers.youmustget.com</li>
</ul>


<p>...and so on, because i bought <a href='http://youmustget.com/'>'youmustget.com'</a>.</p>

<p>And now I have a slight dilemma. I already own too many urls that I'm not using (this brings my total internet empire to 11.5 sites) And I don't have time to execute on even the simplest ideas in my idea log.</p>

<p>So: how can I crank out a social recommendation/shopping app in under 5 bus trips!?</p>

<p>I want something that produces an output a little bit like <a href='http://www.thisiswhyimbroke.com/'>this is why i'm broke dot com</a> but where the recommendations come from people i respect, and with affiliate dollars flowing into my wallet on every recommended purchase. (And i'd like to come up with a less-sleazy way to monetize, if possible, but I do have to recoup that $9.95 <em>somehow</em>)</p>

<p>I've begun by creating a <a href='https://trello.com/board/things-youmustget-com/4ebb599886788fbdec0be37f'>Trello board</a> to capture all my ideas. I've got details for the home page, a products page, a user page, and a topic page. I've got a backlog of features that I won't implement at first, and I've got a list of ideas for what technology I'll use where. Next I'll put together some screen mockups and put them in front of my <strike>extended team of insult generators</strike> lunch buddies.</p> 
 
<p>In the mean time I'll need to keep a cricket bat handy with which to repel the hordes of nodding VCs.</p> 
<p>Thoughts?</p>
]]>
    </description>
    <pubDate>Sat, 12 Nov 2011 00:39:08 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/bought_youmustget.asp</guid>
  </item>
<item>
  <title>NimbleText: Origins</title>
    <link>http://www.secretGeek.net/nimbletext_origins.asp</link>
    <description>
      <![CDATA[ 
<p>I started shipping <a href='http://NimbleText.com'>NimbleText</a> at the end of January 2011. That's eight months after NimbleText was *almost* ready for release back in May 2010, when I published this roadmap: <a href='http://secretgeek.net/microIsv_ToDoOrNot.asp'>24 things to do, and 100 things *not* to do (yet) for building a MicroISV</a>. Back in May, instead of powering on with the last few tasks, I invested my spare time writing <a href='http://secretgeek.net/dod_intro.asp'>Dos-based web frameworks</a> and <a href='http://secretgeek.net/json_query_5.asp'>5 different json editors</a>. I guess having a new little baby girl counts as something of a distraction too. ;-) (Very happily).</p>

<p>When I finally starting shipping, Joe Cooney <a href='http://twitter.com/#!/josephcooney/status/30612770298798080'>said</a>:

<blockquote><p>I tip my hat to you - I think in the time I've re-written a few bits of UI you shipped a product.</p></blockquote>
<p>...in reference to his awesome <a href='http://www.lognv.com/'>LogEnvy tool</a>. But it's not a fair comparison, for two reasons.</p>
<p>Firstly, <a href='http://www.lognv.com/'>LogEnvy</a> is a much more sophisticated product than <a href='http://NimbleText.com'>NimbleText</a>. <a href='http://www.lognv.com/'>LogEnvy</a> does all kinds of powerful manipulation of events logs in a wide range of formats and intersperses it with all the kind of dazzling UI you expect from a WPF ninja. <strong>But most of all</strong> his statement is incorrect because NimbleText was almost <em>six years in the making</em>.</p>

<p style='clear:both' ></p>
<img src='http://secretgeek.net/image/merger_75.png' style='float:right;clear:right;border:0px solid #FFF;padding:10px;'>
<p>I wrote <a href='http://secretgeek.net/programmers_mate.asp'>the first version</a> in February 2005 and published it as part of a blog post soon after. I wrote it the very <a href='http://secretgeek.net/screenshot_journal.asp'>same day</a> I came up with the idea for <a href='http://TimeSnapper.com'>TimeSnapper</a>. It was a stressful week when I desperately needed both of those tools.</p>
<p>Although I was already a .net programmer, I wrote the original code in server-side VBScript for easier deployment. It was just a dozen or so lines. I called it variously 'the data pattern merge tool', 'the merger,' 'the programmer's mate' or the 'text multiplier.' Starting from that day, and continuing right up until the present, I have depended on this tool absolutely daily.</p>

<img src='http://secretgeek.net/image/w2scg_75.png' style='float:left;clear:left;border:0px solid #FFF;padding:10px;'>
<p>I released a <a href='http://secretgeek.net/New_Generator.asp'>second version</a> in July 2005, and called it 'the world's <em>second</em> simplest code generator'.</p>
<p>The source code is largely a comment block listing all the extra features I wished it had. (And almost all of which, by the way, are implemented in more recent verisons)</p>

<img src='http://secretgeek.net/image/wscg_example_50.PNG' style='float:right;clear:right;border:0px solid #FFF;padding:10px;'>
<p>A complete <a href='http://secretgeek.net/wscg_sneak.asp'>rewrite occurred in May 2006</a> when I started huffing the XSLT pixie dust and thought XSL could solve everything. Its dynamic nature gave it big advantages over the vbscript implementation.</p>
<p>But it soon turned into an exercise in writing a fully fledged compiler and I knew I was headed in the wrong direction.</p>

<p>I wrote an "offline version" around that time, in Windows Forms (VB.net version 1.1) I was never happy with it and didn't release it. If I have the code for it, I don't know where. My clearest memory of it was the way parts of the UI would animate (using a Timer control, of course :-) ).</p>

<p style='clear:both' ></p>
<img src='http://secretgeek.net/image/wscgjs_th.PNG' style='float:left;clear:left;border:0px solid #FFF;padding-right:10px;padding:10px;'>
<p>I <a href='http://secretgeek.net/wscgjs_th.asp'>re-wrote the tool in August 2007</a>, this time in javascript. Why did I rewrite it in Javasript? Because I was momentarily trapped on a machine that had no development tools, but I still felt like cutting some code. I assumed that browser performance would kill the tool, but I was dead wrong. Javascript was the perfect language for the problem, and the performance of Javascript was just beginning to take off as the browser wars re-ignited.</p>

<p>It was a clear victory for <a href='http://www.codinghorror.com/blog/2007/07/the-principle-of-least-power.html'>Atwood's Law</a>:</p>
<blockquote><p>"any application that <em>can</em> be written in JavaScript, <em>will</em> eventually be written in JavaScript."</p></blockquote>
<p>Or a pre-cursor to <a href='https://twitter.com/#!/secretGeek/status/119229415086501888'>Bambrick's Premonition</a>:</p>
<blockquote><p>"I don't know when skynet will take over. But I know what it will be written in: JavaScript."</p></blockquote>
<p style='clear:both' ></p>
<img src='http://secretgeek.net/image/wpftour_th1.PNG' style='float:right;clear:right;border:0px solid #FFF;padding:10px;'>
<p>I wrote a (playful) <a href='http://secretgeek.net/wpf_firstapp.asp'>WPF version</a> in Oct 2007 (in C#). 

<p>I wasn't happy with the tooling for WPF (maybe someone should <a href='http://fixwpf.org'>fix</a> that?), but more-so the dynamic behaviour of javascript trumped C# for this tool, so the WPF version never went anywhere.</p>
<p>Around that time I wrote other undocumented, unreleased versions in powershell and one in ruby (<a href='https://github.com/whymirror/shoes/tree'>shoes</a>). Powershell was well suited as a language, but lacked the reach of javascript, plus the performance (at that time) was dreadful. The <a href='http://en.wikipedia.org/wiki/Shoes_(GUI_toolkit)'>shoes</a> version dissappeared around the same time as <a href='http://ejohn.org/blog/eulogy-to-_why/'>_why</a>. (Coincidence? I think not.)</p>

<p>Late last year I decided to release it as a windows app, using a polished and thoroughly <a href="http://secretgeek.net/code_commute.asp">bus-tested</a> version of the javascript implementation, wrapped in a browser control inside a skinny winforms shim. Early this year I <a href='http://secretgeek.net/nimbletext_is_alive.asp'>went live</a> with it, under the new official title of NimbleText. I've hunted down <a href="http://secretgeek.net/nt_lesscrash.asp">bugs</a> and added features in the months since.</p>

<style type='text/css'>
.wtf { display:none}
</style>

<img src='http://secretgeek.net/image/sample_shot.png' style='float:left;clear:left;border:0px solid #FFF;padding:10px;'>

<p>The <a href='http://nimbletext.com/Version/Notes#1.4.0.37771'>latest release</a> looks a little more <a href='http://secretgeek.net/win8mullet.asp'>metro</a> than any previous version, as I stripped away a lot of the padding and extraneous lines, simplifying the appearance (and improving a few features as well, of course).</p>

<p>It's kind of amusing that after I chose to shun all of Microsoft's native application development toolkits  (wpf, silverlight, and winforms) going with HTML for the UI, it seems like Microsoft have now decided to meet me half way, making HTML a first class citizen in Metro.</p>

<p>Anytime I'm faced with a new platform, I usually implement a version of nimbleText as my own personal hello world, and it looks like Metro will make it easy for me. Porting the heart of this baby to Metro should be a breeze. I'll still have to put in some design effort around how the supporting features are presented (what will happen to the menus, toolbars etc?). But I expect it will be a good ice-breaker.</p>

<p>Meanwhile -- if you ever write code or munge data, save yourself some time and use NimbleText. Both <a href='http://nimbletext.com/Download/NimbleText.exe'>the download</a> and the <a href='http://nimbletext.com/live'>online version</a> are <strong>FREE</strong>. There's no time-limit on the application and you only choose to pay if you want the extended features (customizability and commandline integration).</p>

<p>If you have features you want, please leave a comment here or send an email to <code>support<span class='wtf'>exclude this bit</span>@<span class='wtf'>exclude this bit</span>NimbleText.com</code> </p>
]]>
    </description>
    <pubDate>Thu, 29 Sep 2011 13:26:31 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/nimbletext_origins.asp</guid>
  </item>
<item>
  <title>The Windows 8 Mullet</title>
    <link>http://www.secretGeek.net/win8mullet.asp</link>
    <description>
      <![CDATA[ 
<a href='http://secretGeek.net/image/win8mullet.png'><img src='http://secretGeek.net/image/win8mullet_50.png' style='float:right;clear:right;border:0px solid #FFF;padding:10px;' alt='Windows 8 is a mullet: Classic Windows Business at the front, Metro Party at the back'></a>

<p>I think i get it now. In Windows 8 you have two modes: metro and classic. </p>

<p>Metro is for exciting responsive new apps that you can use while sitting on a designer couch. </p>
<p>Classic is the Windows of spreadsheets and complex applications that we've used in our day jobs for years.</p>
<p>It's basically a mullet. Business in the front, party in the back.</p>
<p>I'm looking forward to joining the Metro party. I don't know if the business guy is going to host a very good party. But his client list is so long that a lot of great people are bound to be there.</p>
<p>Maybe I'm a little worried it will be like the party that Rick Moranis's character, <a href='http://www.imdb.com/title/tt0087332/quotes'>Louis</a>, is hosting in ghostbusters:</p>
<img src='http://secretGeek.net/image/rick_moranis_33.jpg' style='float:left;clear:left;border:0px solid #FFF;padding:10px;padding-right:-10px' alt="I'm givin' this whole thing as a promotional expense, that's why I invited clients instead of friends.">
<blockquote style='float:left;'><p>Louis: I'm givin' this whole thing as a promotional expense, that's why I invited clients instead of friends. You havin' a good time, Mark? <br />
[heads across the room, greeting other guests]</p></blockquote>
<p style='clear:both'>It's all going well until a terror dog turns up and terrifies the guests. But I digress.</p>
<p>At first I thought that this metro-fad would only have as much take-up as designing sidebar gadgets in Vista (i.e. approximately none). But the killer features to attract devs is the app store. Having your apps readily available to (potentially) hundreds of millions of people, is a very tempting proposition and bound to attract a lot of developers, possibly including me.</p>
<p>So, does anybody wanna play Parcheesi?</p> 
]]>
    </description>
    <pubDate>Sat, 17 Sep 2011 02:42:52 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/win8mullet.asp</guid>
  </item>
<item>
  <title>Introducing Cosby, spontaneous striped background generator</title>
    <link>http://www.secretGeek.net/cosby_code.asp</link>
    <description>
      <![CDATA[ 
<a href='http://cosby.secretgeek.net/Home/Play/V/50/000000/50/FF8800/50/000000/50/ed15ed'><img src='http://secretgeek.net/image/cos_stripy_50.png' style='float:right;clear:right;border:0px solid #FFF;padding:10px;' alt='cosby playground'></a>

<p><a href='http://cosby.secretGeek.net'>'Cosby'</a> is a small site for generating striped backgrounds (or gradient edges). You can incorporate the code from Cosby into your own asp.net/mvc applications and create striped backgrounds directly from within your Css file.</p>

<p>Once you've got Cosby in place, you can start to magically conjur stripy images out of thin air. Just reference a Cosby image as if it already exists, and it will cause the relevant image to be generated spontaneously and stored on disk for eternity.</p>

<p>For example, if you write: "background-image: url(/Image/Stripes/V/20/FFF/1/000);" then you will get a background with vertical ('V') stripes, alternating between 20 pixels of white (FFF) and 1 pixel of black (000). A moment later you decide you want the black stripes a little wider. Just alter the css (change the 1 to a 2) and they will be. No need to jump back and forth between image editor, filesystem, IDE and browser.</p>

<p>Cosby includes <a href='http://cosby.secretgeek.net/Home/Play'>a playground</a> where you can experiment with creating your own backgrounds.</p>
<br />
<p><a href='http://cosby.secretgeek.net/Home/Play' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Play with cosby</a></p>
<br />
<p><a href='http://cosby.codeplex.com/SourceControl/list/changesets' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Get the code</a></p>
<br />
<p><a href='http://cosby.secretgeek.net/' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Visit the site</a></p>

<h2 style='clear:right'>But Why!?</h2>

<p>While I was <strike>procrastinating about</strike> working on my <a href='http://secretgeek.net/wdcnz_mvc3.asp'>talk for WDCNZ</a> I wanted to mess around with MVC's <a href='http://msdn.microsoft.com/en-us/library/system.web.mvc.fileresult.aspx'>'FileResult'</a> which lets you return a file from an action. So I resurrected and mutated the idea behind a <a href='http://secretgeek.net/GradientMaker.asp'>Gradient Maker</a> I wrote SIX years ago, using asp.net 1.0, and ended up with this latest monstrosity. (Cosby also lets you generate gradients, though I haven't done much with that feature)</p>

<p>The code is published at <a href='http://cosby.codeplex.com/SourceControl/list/changesets'>cosby.secretGeek.net</a>, so feel free to grab it, criticise it, and forget about it.</p>
<p>And of course the name is a reference to Bill Cosby's infamous <a href='http://thecosbysweaterproject.tumblr.com'>Cosby sweaters</a>, which get their own <a href='http://en.wikipedia.org/wiki/Koos_Van_Den_Akker#The_Bill_Cosby_Sweaters'>detailed write up on wikipedia</a>. I was recently heartened to see 'Cosby sweater' amongst the text generated by the <a href='http://hipsteripsum.me/'>hipster ipsum</a> random text generator.</p>

<p>That's all for now.</p>
]]>
    </description>
    <pubDate>Wed, 24 Aug 2011 05:18:00 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/cosby_code.asp</guid>
  </item>
<item>
  <title>Slides from WDCNZ: Live Coding Asp.net MVC3</title>
    <link>http://www.secretGeek.net/wdcnz_mvc3.asp</link>
    <description>
      <![CDATA[ 
<img src='http://secretgeek.net/image/wdcnz_15.png' style='float:right;clear:right;border:0px solid #FFF;padding:10px;' alt='talkin in wellington'>

<p>I am just returned from an excellent holiday in New Zealand, wherein I talked about MVC 3 at the first ever <a href='http://wdcnz.com'>WDCNZ</a> in Wellington.</p>

<p>On the day of the talk I was deathly ill, so it was a very much <a href='http://www.flickr.com/photos/wdcnz/sets/72157627148171169/with/5972187758/'>less animated</a> talk than I wanted to give, but still enjoyable (for me, if not the audience). I missed out on seeing the rest of the conference, which is a real bugger.</p>
<p>In particular I wanted to see <a href='http://paulirish.com/'>Paul Irish</a> on Html5, but I did at least get to meet him for a quick chat the day before. Other speakers I met the day before were pretty interesting to talk to and I very much wanted to see the talks by <a href='http://pageofwords.com/blog/'>Kirk Jackson</a> and <a href='http://jwegesin.com/'>Jeffrey Wegesin</a>, <a href='http://koziarski.com/'>among</a> <a href='http://twitter.com/#!/turtlespin'>others</a>.</p>

<p>Here's my slides, using an updated version of <a href='http://higgins.codeplex.com'>Higgins</a>. You'll need to unzip them, then you can see the readme file, the slides themselves (by viewing higgins.html) or look at the included code.</p>

<p>&nbsp;</p>
<p><a href='http://secretGeek.net/content/wdcnz_mvc3_leon.zip' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:10px;padding:10px;-moz-border-radius: 15px; border-radius: 15px;'>Slides and Code for 'Live Coding Asp.net MVC 3'</a></p>
<p>&nbsp;</p>
<p>The talk covers Razor syntax, Display and Editor Templates, custom Code Templates and custom Project templates. Thankfully, there is no video.</p>

<p><a href='http://jcooney.net/'>Joseph Cooney</a> built a special utility to help with the talk, called <a href='http://jcooney.net/post/2011/07/15/Increased-Presentation-Impact-with-BigNote.aspx'>'BigNote'</a> -- available from <a href='http://bignote.codeplex.com'>bignote.codeplex.com</a>.</p>
<p>This is a handy tool for presenters. Invoke it with a hotkey (ctrl-F1) and then it lets you write in giant letters on top of the desktop. Very slick.</p>
<p>I had a slight panic during the talk when I realised that Joe Cooney, creator of <a href='http://ComputerUnlocked.com'>ComputerUnlocked.com</a> could have used the opportunity to slip any kind of nasty prank into the tool, just to punk me in front of a room full of strangers. But luckily he slipped up and missed the opportunity.</p>

<p>One other thing I ought to mention: the Dell laptop I bought in anticipation of the presentation turned out to be a total dud. I was only rescued the day before leaving Australia when <a href='http://www.PaulStovell.com'>Paul Stovell</a> managed to hook me up with an old laptop of his, which performed flawlessly. Thanks Paul!</p>
]]>
    </description>
    <pubDate>Sun, 31 Jul 2011 03:17:57 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/wdcnz_mvc3.asp</guid>
  </item>
<item>
  <title>MVC 3, "Third Times a Charm" references</title>
    <link>http://www.secretGeek.net/mvc3_Refs.asp</link>
    <description>
      <![CDATA[ 
<p>For the last few months I've been on an MVC 3 binge, learning as much as I can fit in my tiny brain. (Had to throw a few <a href='http://www.silverlight.net/'>other</a> <a href='http://en.wikipedia.org/wiki/Windows_CardSpace'>things</a> out first of course.)</p>
<p><a href='http://wdcnz.com/'>Web Dev Conf New Zealand (WDCNZ)</a>, is in Wellington very soon (<a href='http://lanyrd.com/2011/wdcnz/schedule/'>schedule on lanyrd</a>), and I'll be talking there about all things MVC 3. This is keeping me awake nights, I can tell you.</p>
<p>I've applied to talk at the <a href='http://blog.stackoverflow.com/2011/06/devdays-is-back/'>stack overflow dev days</a> conference in Sydney in October. That would be an absolute blast. I rank my chances pretty low, but my excitement is high regardless.</p>
<p>Recently I talked at <a href='http://www.qmsdnug.org/'>QMSDNUG</a>, on 'MVC 3: Third Times a Charm', alongside <a href='http://jcooney.net/'>Joe Cooney</a>. It was a lot of fun, and we allegedly broke a record with our crowd size. It's basically a preview of what I'll cover in Wellington, though some material will be in or out as I revise.</p>
<p>(<a href='http://higgins.codeplex.com/'>Higgins</a> got another workout, and had some html5 goodness baked in)</p>
<p>I promised to put up the references from my talk. They're mostly about customizating your MVC 3 experience in Visual Studio. Here they are.</p>

<table class='t'>
 <thead>
   <tr>
     <th>url</th>
     <th>topic</th>
   </tr>
 </thead>
 <tbody>
  <tr>
    <td><a href='http://download.microsoft.com/download/D/6/D/D6DFC36D-604F-448A-A189-15EC874ABAAF/ASPNETWebPagesWithRazorSyntax-Book-Beta3.pdf' title='http://download.microsoft.com/download/D/6/D/D6DFC36D-604F-448A-A189-15EC874ABAAF/ASPNETWebPagesWithRazorSyntax-Book-Beta3.pdf'>bit.ly/d71zIJ</a></td>
    <td>razor: ebook [pdf]</td>
  </tr>
  <tr>
    <td><a href='http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html' title='http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html'>bit.ly/3Vwjvj</a></td>
    <td>editor &amp; display templates (Brad Wilson)</td>
  </tr>
  <tr>
    <td><a href='http://code.google.com/p/mvc-mini-profiler/' title='http://code.google.com/p/mvc-mini-profiler/'>bit.ly/dIUPo4</a></td>
    <td>MVC Mini profiler (Sam Saffron)</td>
  </tr>
  <tr>
    <td><a href='http://www.hanselman.com/blog/ModifyingTheDefaultCodeGenerationscaffoldingTemplatesInASPNETMVC.aspx' title='http://www.hanselman.com/blog/ModifyingTheDefaultCodeGenerationscaffoldingTemplatesInASPNETMVC.aspx'>bit.ly/h8vQfX</a></td>
    <td>Code templates (Scott Hanselman)</td>
  </tr>
  <tr>
    <td><a href='http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/' title='http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/'>bit.ly/hwNUNS</a></td>
    <td>MVC Scaffolding (Steve Sanderson)</td>
  </tr>
  <tr>
    <td><a href='http://haacked.com/archive/2011/06/06/creating-a-custom-asp-net-mvc-project-template.aspx' title='http://haacked.com/archive/2011/06/06/creating-a-custom-asp-net-mvc-project-template.aspx'>bit.ly/khm2GL</a></td>
    <td>Project Templates (Phil Haack)</td>
  </tr>
  <tr>
    <td><a href='http://weblogs.asp.net/jgalloway/archive/2011/03/17/asp-net-mvc-3-roundup-of-tutorials-videos-labs-and-other-assorted-training-materials.aspx' title='http://weblogs.asp.net/jgalloway/archive/2011/03/17/asp-net-mvc-3-roundup-of-tutorials-videos-labs-and-other-assorted-training-materials.aspx'>bit.ly/hfWA6Z</a></td>
    <td>Roundup of tutorials (Jon Galloway)</td>
  </tr>
 </tbody>
</table>
<br />
<p>If you use MVC 3, what are your favourite bits? What would you cover in a talk? If you don't use it, why not? And what are the sort of things you'd like to see deomonstrated?</p>
]]>
    </description>
    <pubDate>Sat, 02 Jul 2011 02:41:41 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/mvc3_Refs.asp</guid>
  </item>
<item>
  <title>Custom Errors in ASP.Net MVC: It couldn't be simpler, right?</title>
    <link>http://www.secretGeek.net/custom_errors_mvc.asp</link>
    <description>
      <![CDATA[ 
<a href='http://github.com/404'><img src='http://secretGeek.net/image/github404.png' style='float:right;background:#333;padding:1px;margin:5px;margin-top:-2px;' alt='parallaxing 404 at github' /></a>
<p>Cool looking 404 pages are the new hotness. <a href='http://github.com/404'>Github has an amazing parallaxing 404 page</a> that allegedly cost more than any other feature on their site.</p>
<p>For a lot of sites, the 404 page is the most visited page, so it's worth getting it right.</p>

<p>The website for my new product, <a href='http://NimbleText.com/'>NimbleText</a>, uses asp.net mvc. A framework I really enjoy. <a href='http://weblogs.asp.net/scottgu/'>The gu</a> wrote it on a plane. Before takeoff.</p>
<p>One of the more voodoo aspects of getting NimbleText.com into production was setting up a succesful custom 404 page. Here's what I came up with: <a href='http://NimbleText.com/missingPageExample'>check it out.</a></p>
<p>Some of the articles out there that cover custom errors in asp.net MVC seemed to be a little bit confused about exactly what is going on, many are out of date or incomplete and some are downright misleading.</p>
<p>So once and for all I want to give a definitive guide to error handling in asp.net MVC.</p>

<p>Here we are. Just <strong>eleven simple steps to follow for amazing results.</strong></p>

<p>First, map a catch-all route in <code>global.asax</code>, at the end of your other routes. E.g.</p>

<blockquote><code>
routes.MapRoute(<br />
&nbsp;&nbsp;    "404-PageNotFound",<br />
&nbsp;&nbsp;    "{*url}",<br />
&nbsp;&nbsp;    new { controller = "StaticContent", action = "PageNotFound" }<br />
);
</code></blockquote>


<p>Second, create an Error Controller, like this:</p>

<blockquote><code>
    public class ErrorController : Controller<br />
    {<br />
&nbsp;&nbsp;        [AcceptVerbs(HttpVerbs.Get)]<br />
&nbsp;&nbsp;        public ViewResult Unknown()<br />
&nbsp;&nbsp;        {<br />
&nbsp;&nbsp;&nbsp;&nbsp;             Response.StatusCode = (int)HttpStatusCode.InternalServerError;<br />
&nbsp;&nbsp;&nbsp;&nbsp;             return View("Unknown");<br />
&nbsp;&nbsp;        }<br />
 <br />
&nbsp;&nbsp;        [AcceptVerbs(HttpVerbs.Get)]<br />
&nbsp;&nbsp;        public ViewResult NotFound(string path)<br />
&nbsp;&nbsp;        {<br />
&nbsp;&nbsp;&nbsp;&nbsp;             Response.StatusCode = (int)HttpStatusCode.NotFound;<br />
&nbsp;&nbsp;&nbsp;&nbsp;             return View("NotFound", path);<br />
&nbsp;&nbsp;        }<br />
    }<br />
</code></blockquote>
	
<p>Third and fourth -- create custom views to handle the Unknown and NotFound actions above.</p>

<p>Fifth, create a page called Custom404.htm and add it to the root of your application. Use it to display a helpful, edgy and hopefully cool message. But don't be too edgy.</p>

<p>Sixth, add this to web.config, inside the <code>system.web</code> node:</p>
<blockquote><code>&lt;<a href='http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx'>customErrors</a> mode=&quot;RemoteOnly&quot; defaultRedirect=&quot;GenericErrorPage.htm&quot;&gt;<br />
&nbsp;&nbsp; &lt;error statusCode=&quot;404&quot; redirect=&quot;/Custom404.htm&quot; /&gt;<br />
&lt;/customErrors&gt;
</code></blockquote>

<p>Seventh, add a <a href='http://www.iis.net/ConfigReference/system.webServer/httpErrors'>httpErrors</a> element inside the <code>system.webServer</code> node:</p>
	
<blockquote><code>&lt;httpErrors&gt;<br />
&nbsp;&nbsp;            &lt;error statusCode=&quot;404&quot; subStatusCode=&quot;-1&quot; path=&quot;/custom404.htm&quot; responseMode=&quot;Redirect&quot; /&gt;<br />
        &lt;/httpErrors&gt;
</code></blockquote>

<p>Eighth, inside your existing controllers, if there is no data to serve (e.g. if someone asks for a UserId that doesn't exist) then use this snippet of code:</p>

<blockquote><code>throw new HttpException(404);</code></blockquote>

<p>Ninth, inside Global.asax, look for the <code>RegisterGlobalFilters</code> method (it will be called during <code>Application_Start</code>), and add another global filter, to handle any specific exceptions in your code, like this:</p>

<blockquote><code>
filters.Add(new HandleErrorAttribute<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ExceptionType = typeof(FileNotFoundException),<br />
&nbsp; &nbsp; &nbsp; &nbsp; View = "Custom404",  // Custom404.cshtml is a view in the Shared folder.<br />
&nbsp; &nbsp; &nbsp; &nbsp; Order = 2<br />
&nbsp; &nbsp; });
</code></blockquote>
<p>Tenth, add a view called <code>Custom404.cshtml</code> under views/shared.</p>
			
<p>And, eleventh, take care to handle the global application error event, capturing and logging any errors, before redirecting to the views you're after:</p>

<blockquote><code>
protected void Application_Error(object sender, EventArgs e)<br />
{<br />
&nbsp; &nbsp; Exception exception = Server.GetLastError();<br />
&nbsp; &nbsp; Response.Clear();<br />
&nbsp; &nbsp; HttpException httpException = exception as HttpException;<br />
&nbsp; &nbsp; if (httpException != null)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; string action;<br />
&nbsp; &nbsp; &nbsp; &nbsp; switch (httpException.GetHttpCode())<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 404:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // page not found<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action = "HttpError404";<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 500:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // server error<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action = "Internal500";<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; default:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action = "General";<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; // clear error on server<br />
&nbsp; &nbsp; &nbsp; &nbsp; Server.ClearError();<br />
&nbsp; &nbsp; &nbsp; &nbsp; Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));<br />
&nbsp; &nbsp; }<br />
}<br />
</code></blockquote>			

<img src='http://secretGeek.net/image/unhandledException.png' style='float:right;background:#F33;padding:1px;margin:5px;margin-top:-2px;' alt='unexpected error' />


<p>Good. </p>

<p>Now your website is well and truly borked.</p>
<p>Every request will bounce around your application like a demented pinball tripping on acid.</p>
<p>When an error happens, a bunch of different code modules will go to war.</p>
<!-- 

<p>You'll get a different error handler depending on what version of IIS you have, what version of MVC you're using, whether you've deployed in debug or release, whether you're visiting locally or remotely, whether it's sunny or raining.</p>
-->
<!--
<p>Every request will bounce around your application like a demented pinball tripping on acid inside a labyrinthine machine extracted by nazi scientists from the darkest corners of Rube Goldberg's tortured mind during an opium nightmare of Lewis Carrol proportions.</p>
-->
<!-- too much? -->

<!--
<p>When an error happens, chaos will reign. A beast will arise from the north, and one from the sea and one from the earth. A mighty beast with seven-heads and ten horns will stalk the land, the howls and lamentations of the sinners will drown out the cries of the vanquished, blood will fill the sky, and all reason and hope will flee as a horde of code modules go to war.</p>
-->


<p>The victorious code module will tear out the entrails of all those who oppose it, and throw them in the visitor's face.</p>
<p>You'll get a different error handler depending on what version of IIS you have, what version of MVC you're using, whether you've deployed in debug or release, whether you're visiting locally or remotely, whether it's sunny or raining.</p>
<p>Your server will be reduced to a pile of smouldering rubble from which reboot is impossible.</p>
<p>But if you want to get truly weird, try setting up a custom 40<em><strong>3</strong></em> page. That's about three times as odd.</p>
<p>Or, switch to <a href='http://Dod.CodePlex.Com/'>Dos on Dope</a>*. Life will be simple again.</p>
<p>Sorry I didn't really have time to write a definitive guide to this stuff. Error handling in MVC is crazy man, I'm busy fighting a clandestine war against hackers and crackers and bots and beuracrats: I can't be documenting that kind of mystery wrapped in an enigma.</p>
<p>If someone does write a <strong>complete</strong> guide to error handling in MVC, that includes the meaning and interaction behind each of these snippets, plus how the interplay between IIS, asp.net and MVC truly works, then I will happily update this article to include a link to it, right up top.</p>
<hr />
<p><small><strong>* Don't</strong> switch to Dos On Dope.</small></p>
]]>
    </description>
    <pubDate>Sat, 11 Jun 2011 01:10:49 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/custom_errors_mvc.asp</guid>
  </item>
<item>
  <title>Anatomy of a Domain Hijacking, part 2: The Website Who Came In From The Cold</title>
    <link>http://www.secretGeek.net/sg_hijack_2.asp</link>
    <description>
      <![CDATA[ <p>When secretGeek.net was taken I swore a solemn oath to myself:</p>
<blockquote><p>My relentless campaign of jokes and nonsense will not be stopped.</p></blockquote>
<p>And now, just a couple of long weeks later, here I am, happy to report I'm back in control of secretGeek.net.</p>
<p>Right when I was ready to migrate over to leonbambrick.com, I got an email from the Russian registrar, Regtime Ltd, saying:</p>
<blockquote><p>Sorry&nbsp;&nbsp;for answer delay. Domain was transferred onto you account.</p></blockquote>
<p>The number one thing, I think, that helped get the site back was when a good friend, Madina, translated a lengthy email into fluent Russian for me to send to the Russian Registrar.</p> 
<p>She re-structured the email to put the sob-story up front, all about how much personal meaning this site has for me, and the positive effects it has had on my life. I think that did the trick.</p>

<h2>So what did we learn?</h2>
<p>I learnt that passwords at google <a href='http://seclists.org/fulldisclosure/2009/Jul/254'>can be brute forced, if pop is enabled</a>. This can be sped up by use of multiple IP addresses, or a <a href='http://www.abuse.ch/?p=3294'>botnet</a>.</p>
<p>That's the most likely way they got access to my account. My password was 'good' by gmail standards but is now 'freaking solid' by any standard.</p>
<p>And I've turned on <a href='http://googleblog.blogspot.com/2011/02/advanced-sign-in-security-for-your.html'>2-step verification</a>, plus all the other <a href='http://secretgeek.net/sg_hijack_1.asp'>recommendations from part 1.</a></p>
<p>Thanks for the encouragement and support. It was dark times, but now the nonsense can continue.</p>

]]>
    </description>
    <pubDate>Tue, 07 Jun 2011 21:33:47 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/sg_hijack_2.asp</guid>
  </item>
<item>
  <title>Anatomy of a Domain Hijacking, part 1</title>
    <link>http://www.secretGeek.net/sg_hijack_1.asp</link>
    <description>
      <![CDATA[ 
<p>Two weeks ago I'd never heard the term <a href='http://en.wikipedia.org/wiki/Domain_hijacking'>'Domain Hijacking'</a>. Right now, I'm in the middle of a fight to regain control of my hijacked domain, <a href='http://secretGeek.net' rel='nofollow'>secretGeek.net</a>. It's not an easy fight, I haven't yet won, and I may never win.</p>

<p><strong>If you have any information that could help me get control of my domain again please leave a comment, or tweet me (<a href='http://twitter.com/#!/secretGeek'>@secretgeek</a>), or get in touch via my (now re-secured) email address, leonbambrick@gmail.com</strong></p>

 
<h2>From Russia with Love</h2>
 
<p>On Monday 9th May, I checked my gmail account at around 3:40 in the afternoon, and I was confronted with a dark red message at the top of the screen (in the area where you normally see messages like 'Your email has been sent'). The message said:</p>
 
 <p style='text-align:center'><span style='background-color:#980000; color:white;padding:4px;border-radius:4px'><strong>Warning: we believe your account was recently accessed from: Russia. <span style='text-decoration:underline'>Show details and preferences</span> | <span style='text-decoration:underline'>Ignore</span></strong></span></p>
 
 <p>I clicked on 'show details and preferences', and a new window opened with this message:</p>
 <a href='http://secretGeek.net/image/russian_ip_full.png'><img src='http://secretGeek.net/image/russian_ip_zoom.png' style='border:0px solid #000'/></a>
 <p>(click to see the message in context -- [note that my own ip addresses are redacted])</p>
 
 <p>This was definitely not me. At 4:19 AM, and 5:40am I had been far too busy being fast asleep, preparing for a big week, to get to Russia and back for some casual email reading. So someone had infiltrated my email. The freaking out sensation began immediately. I couldn't move. I was frozen completely still.</p>
 <p>I followed google's advice and immediately changed my password, then notified my wife. My mind was racing as to what the implications could be.</p>
 <p>A little voice told me to check the trash. I was really hesitant, I think I knew the trash would contain something I didn't want to see.</p>
 <p>In the trash I found two messages, received at 5:45am.</p>
 <img src='http://secretGeek.net/image/messages_in_trash.png' style='border:0px solid #000'/>
 <p>The content of the messages was to explain that my domain, secretGeek.net, had been succesfully transferred from my registrar, <a href='http://GoDaddy.com'>GoDaddy</a>, to a Russian registrar, <a href='http://www.webnames.ru/'>Regtime Ltd</a>.</p>
 <p>I felt completely unreal, like this was a dream, or a prank. I logged into my GoDaddy account to check on my domains. They all still appeared to be there. I took a few deep breaths. I felt it must be all just a daydream. I read the list carefully. No -- secretGeek.net was missing from the list. All of the others were still there.</p>
<p>I started sending emails to GoDaddy. I replied to the emails I'd found in the trash, telling them that it was a mistake, the result of my email being violated.</p>
<p>I lodged support requests with GoDaddy. When I went back to the trash to read the deleted emails again I found there were <em>new</em> messages in the trash. Emails from godaddy in response to my support requests had been automatically deleted. This was *weird*. It was a few minutes before the penny dropped.</p>
<p>I looked in my gmail filters and there were two new ones. The two new filters were designed to delete any messages containing the words 'GoDaddy' or 'Webnames'. (I later found that 'Webnames.ru' is the trading name of 'Regtime Ltd', the Russian registrar holding secretGeek.net)</p>
<img src='http://secretGeek.net/image/new_filters.png' style='border:0px solid #000'/>
<p>This was starting to become very 'real'. This wasn't some kind of misunderstanding. It was definitely a thing. It was a deliberate, targeted attack, by a person or people who knew what they were doing and had either done this thing before or had thought it through very carefully.</p>
<p>I turned to my friend, <a href='http://JCooney.net'>Joe Cooney</a>, to show him what I'd found. He was equally gobsmacked. He told me to call GoDaddy on their support number and see what they said.</p>
<p>A whois request on secretGeek.net showed that my name servers were still listed, but the registrar was Regtime ltd, and the contact information was all blank.</p>
<p>The support guy at GoDaddy told me to contact the gaining registrar and find out what their policy is for transfer disputes. He told me there was nothing GoDaddy could do (turns out this was bad advice, by the way)</p>
<p>I was busy worrying about what else was in danger. My wife was already on the task of changing every password, keycode, and security question associated with all of our bank accounts, credit cards, online identities, home pcs etc, and checking at each of these places for any trace of unusual activity.</p>
<p>In order to send a support request to the Russian registrar, I had to sign up as a member (and I noted with some distaste that they sent me my new password in plain text.) I sent them multiple emails explaining what happened. Then I re-sent each of those messages, in Russian this time, translated by translate.google, and including the original text.</p>
<p>I worked late that day to make up for the lost time and somehow managed another check-in before I went home.</p>
<p>That night I called GoDaddy again, hoping to get more help. By now I'd read about <a href='http://www.davidairey.com/google-gmail-security-hijack/'>the similar case of David Airey</a> where a gmail vulnerability led to a domain hijacking, which also involved godaddy. This time I got a more helpful support staff member. She told me to fill out the <a href='http://www.godaddy.com/agreements/ShowDoc.aspx?pageid=Dispute_On_Transfer_Away_Form'>'dispute on transfer away'</a> form at GoDaddy, which I promptly did. This meant that the right people at godaddy would be notified, and they'd contact the Russian registrar to request the domain be returned.</p>

<h2>Wrapping up part 1.</h2>

<p>While there's more that's happened since, things haven't really progressed since that day at all.</p>

<p>I still haven't regained control of the domain.  I'm waiting on word from the Russian registrar. I remain hopeful that any minute now I'll get an email from them saying "Ah, we're sending back your domain!" -- but my hope is fading.</p>

<p>The name servers haven't been changed, so my content continues to be served up as always. If it does go down, the plan is to launch a new and improved secretGeek at <a href='http://LeonBambrick.com'>LeonBambrick.com</a>. Announcements or news will be via twitter (<a href='http://twitter.com/#!/secretGeek'>@secretGeek</a>) or from my business website, <a href='http://nimblething.net'>NimbleThing.net</a>.

<p><strong>If you have any information that could help me get control of my domain again please leave a comment, or tweet me (<a href='http://twitter.com/#!/secretGeek'>@secretgeek</a>), or get in touch via my (now re-secured) email address, leonbambrick@gmail.com</strong></p>

<p> In the next part of the story I want to discuss gmail security, all of the possible ways I could've been hacked, and the one I think is most likely. But I can't wait until then to put out the following checklists. These are steps that you can do to protect your email account and to protect your domains:</p>

<h2>What can you do to stop this happening to you?</h2>
<p><strong>Protect your email via:</strong></p>
<ul>
<li>Change your password often. For example, right now.</li>
<li>Make your password very strong.</li>
<li>In gmail: disable POP.</li>
<li>Ensure your password recovery options are as strong as your password.</li>
<li>Make sure 'always use https' is selected.</li>
<li>In gmail: check for unusual activity (it's available at the foot of the screen).</li>
<li>In gmail: don't let any other apps be associated with your account.</li>
<li>Use two-step authentication.</li>
</ul>
<p><strong>Protect your domains via:</strong></p>
<ul>
<li>Pay for private domain registration.</li>
<li>Pay for enhanced transfer protection. (e.g. at GoDaddy they call it 'Deadbolt' protection, and it means they require you to send them identification before they'll approve a transfer.)</li>
</ul>
]]>
    </description>
    <pubDate>Sun, 22 May 2011 13:30:20 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/sg_hijack_1.asp</guid>
  </item>
<item>
  <title>secretGeek.net domain has been stolen. The site may go down.</title>
    <link>http://www.secretGeek.net/sg_hijack.asp</link>
    <description>
      <![CDATA[ 
<p><em>The short story:</em></p>
<p>A person with a Russian IP address broke into my email account and used that access to transer ownership of the secretGeek.net domain to a Russian registrar, webNames.ru.</p>
<p>The full story is jam packed with intrigue, daring adventure, black ops helicopters, sexy double agents, Ukrainian php developers, and a liberal dash of nerdy security best practices.</p>
<p>I will tell the full story once I have secured my domain again.</p>
<p>In the meantime, if your beloved secretGeek.net is suddenly replaced by a spammy porn site or variant thereof, do not despair. Follow me on twitter (<a href='http://twitter.com/#!/secretGeek'>@secretGeek</a>) or head to my business website (<a href='http://NimbleThing.net'>NimbleThing.net</a>) where (if necessary) I will mirror the original secretGeek content and continue blogging until I've taken charge of the domain again.</p>
]]>
    </description>
    <pubDate>Tue, 10 May 2011 11:37:25 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/sg_hijack.asp</guid>
  </item>
<item>
  <title>Boring article about fixing a 'Login failed... untrusted domain' issue when connecting to SQL Server.</title>
    <link>http://www.secretGeek.net/boring_sql_one.asp</link>
    <description>
      <![CDATA[<p>This will be the most boring and dry technical post I've ever written. I promise. I'm only writing it down because I hear <a href='http://www.codinghorror.com/blog/'>Jeff Atwood's</a> voice in my head telling me that if I haven't shared the solution then there's almost no value in solving it.</p>

<p>So here was the problem...</p>
<p>On one of my machines, in recent months, anytime I tried to run an asp.net application that attempts to connect to a SQL Server database I receive this error:</p>

<blockquote><p>Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.</p></blockquote>

<p>This is in a scenario where everything is local: I'm on a home computer, using a local database server. And it doesn't matter if I'm using IIS, webdevserver, or IIS Express. It doesn't matter if I'm trying to connect to SQL Express or SQL Server 2008 r2. I can enter the credentials using the machine name or IP address. The result is the same.</p>

<p>Looking in the Windows Event Viewer I see:</p> 

<blockquote><p>SSPI handshake failed with error code 0x8009030c, state 14 while establishing a connection with integrated security; the connection has been closed. Reason: AcceptSecurityContext failed. The Windows error code indicates the cause of failure.  [CLIENT: &lt;local machine&gt;]. </p></blockquote>

<p>Most of the 'solutions' online were not applicable because they involve domain issues. This is just a local machine.</p>


<p>One particular forum message involved a guy with a similar setup to me. He <a href='http://social.msdn.microsoft.com/Forums/en-US/sqlexpress/thread/54824854-0dc2-4d9b-9ad7-482701929a6e/'>solved the problem</a> for himself, but left behind only this very abbreviated and somewhat cryptic explanation:</p>

<blockquote><p>Solved. Traced the prob. to my net setup. The clue was this a msg in the Win System Log from Lsasrv about the target name and it showed the fqdn. Did some checks and the fqdn didn't look right, cleaned up my network config (I had customized it for another project), and now it's workin.</p></blockquote>

<p>The 'fqdn' is the fully qualified domain name. I found three different ways to find my fqdn, and one of them disagreed with the others! So this was a smoking gun.</p>

<p>Method 1 for finding the fqdn: When I right clicked on "computer" in the start menu and looked at the properties, the 'full computer name' was reported as '<code>Leon_xps</code>'.

<p>Method 2 for finding the fqdn: When I ran "</code>ipconfig /all</code>" and got these values for Host Name and Primary Dns Suffix:</p>
<blockquote><pre>   Host Name . . . . . . . . . . . . : Leon_xps
   Primary Dns Suffix  . . . . . . . : 
</pre></blockquote>   
<p>(Add them together and you get a fqdn of just 'Leon_xps'</p>

<p>Method 3 for finding the fqdn: In <code>cmd</code> when I ran '<code>ping -a Leon_xps</code>' I saw a <em>very</em> unexpected result!</p>

<p>It said:</p>

<blockquote><pre>Pinging leonx_xps [192.168.1.2] with 32 bytes of data:
Request timed out.
Request timed out.
Request timed out.
Request timed out.</pre></blockquote>

<p>Notice that it's changed the name '<code>leon_xps</code>' into '<code>leon<strong style='font-size:large'>x</strong>_xps</code>' and come up with the ipaddress of '<code>192.168.1.2</code>'. instead of what I expected (such as a loopback address, 127.0.0.1... or some IPv6 nonsense)</p>

<p>There's only one kind of alchemy I know of for turning a good name into a crazy ipaddress: and that's <a href='http://secretgeek.net/block_sites.asp'>the magic of the HOSTS file</a>.</p>

<p>So I looked in there for '<code>leon<strong style='font-size:large'>x</strong>_xps</code>' and I found it. Found this crazy nonsense line, probably added by myself during some other wild-goose-chase for a solution to some other messed up problem:</p>

<blockquote><pre>192.168.1.2 leonx_xps leon_xps</pre></blockquote>

<p>Once I'd commented out that rule, the asp.net application immediately started to connect succesfully to SQL Server 2008 r2. And I can move forward with my testing of <a href='https://github.com/robconery/massive'>Massive</a> and <a href='https://github.com/SamSaffron/dapper-dot-net'>Dapper</a>.</p>

<p>But just mentioning the probable cause of this (not cleaning up during an earlier problem-panic) I remember that earlier tonight, while frantically trying to fix this problem I added some stupid rules to the windows firewall. I had better go and remove them now before my computer gets owned. Hey wait a moment!? Why is my CPU at 100%? Be right back...</p>
 
]]>
    </description>
    <pubDate>Sun, 08 May 2011 13:30:04 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/boring_sql_one.asp</guid>
  </item>
<item>
  <title>Coding While You Commute</title>
    <link>http://www.secretGeek.net/code_commute.asp</link>
    <description>
      <![CDATA[<a href='http://secretGeek.net/higgins/slides_alt_net.html' style='float:right; margin:5px'><img src='http://secretGeek.net/image/codeslide_bus.png' alt='coding on the bus' style='border:2px solid #AAA' /></a>

<p>I gave a talk at <a href='http://www.meetup.com/Brisbane-Alt-Net-Group/'>Brisbane's alt.net</a> recently. You can download the slides <a href='http://secretGeek.net/higgins/slides_alt_net.zip'>here (1.5M zipped)</a> or:</p>
<p>&nbsp;</p>

<p><a href='http://secretGeek.net/higgins/slides_alt_net.html' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:20px;padding:10px;margin-left:45px;-moz-border-radius: 15px; border-radius: 15px;' title='slides for coding on the bus talk'>View the 97 slides online here</a></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (use arrow keys to advance)</p>
<p>&nbsp;</p>
<p>The theme was '<strong>Coding on the Bus</strong>' -- the optimisations and approach I've used for cranking out a dozen mini projects on my daily commute in the last year.</p>
<p>A bus is a seemingly counter-productive environment. As I say in one of the slides: 
<blockquote><p>If your workplace was like a bus: everyone would quit.</p></blockquote>
<p>And yet I'm producing a lot of stuff while on that short ride, definitely pushing the limits of my abilities. So this talk was an attempt to extract all the lessons I could from this real life productivity success story.</p>
<h1>TL;DR;</h1>
<p>Here's the quick version:</p>
<blockquote><p>
#1 Internet is bad<br />
#2 Keep it damn simple<br />
#3 Value your tools/libraries/snippets<br />
#4 Don't be a hero</p></blockquote>


<p>The people at Brisbane Alt.Net are a very cluey bunch so it was great to get their input on the whole thing. They were a very attentive and helpful bunch. It was a massive buzz talking to them. I highly recommend it.</p>

<a href='http://higgins.codeplex.com/' style='float:right;margin:5px'><img src='http://secretGeek.net/image/higgins_logo.png' alt='higgins presenter' style='border:5px solid #C00' /></a>

<h2>...And Introducing Higgins</h2>
<p>Naturally, I wrote the slides about writing on the bus, <em>while on the bus</em>. I don't have Powerpoint on my bus netbook, so I also had to write my own html-based slide presenter, which I've codenamed Higgins.</p>
<p>I've since added higgins to codeplex. You can <a href='http://higgins.codeplex.com'>get Higgins from codeplex</a> and use it yourself, if you're so inclined.</p>
<p>&nbsp;</p>

<p><a href='http://higgins.codeplex.com' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:20px;padding:10px;margin-left:45px;-moz-border-radius: 15px; border-radius: 15px;'>Visit higgins at codeplex</a></p>
<p>&nbsp;</p>
<p><a href='http://higgins.codeplex.com/releases/64531/download/228871' style='font-size:large; background-color:#333;color:#AFA;font-weight:bold;margin:20px;padding:10px;margin-left:45px;-moz-border-radius: 15px; border-radius: 15px;'>Download higgins here</a></p>

<p style='clear:right'>&nbsp;</p>

<img src='http://secretGeek.net/image/briz_alt_net_20.jpg' alt='briz alt net sign kind of ironic i think' style='border:2px solid #AAA; display:block;float:center;margin:5px;margin-left:auto;margin-right:auto;' />

<p style='clear:both'>&nbsp;</p>
]]>
    </description>
    <pubDate>Sat, 16 Apr 2011 03:33:12 GMT</pubDate>
    <dc:creator>Leon Bambrick</dc:creator>
    <guid>http://www.secretGeek.net/code_commute.asp</guid>
  </item>
</channel>
</rss>

