<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Kickass Labs</title>
	
	<link>http://www.kickasslabs.com</link>
	<description>We ♥ code.</description>
	<lastBuildDate>Wed, 28 Dec 2011 16:57:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/KickassLabs" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="kickasslabs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Agile vs. No Silver Bullet</title>
		<link>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/</link>
		<comments>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 16:48:23 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Process]]></category>
		<category><![CDATA[Quick Hits]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=770</guid>
		<description><![CDATA[I&#8217;ve been returning to my source materials on Agile software development/project management methods recently, just to stay fresh. As part of my study, I ran across a blog post (more of a petulant rant, actually) that cites (actually, mentions in &#8230; <a href="http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been returning to my source materials on Agile software development/project management methods recently, just to stay fresh.  As part of my study, I ran across a blog post (more of a petulant rant, actually) that cites (actually, mentions in passing, with no real justification) the classic Fred Brooks essay <a href="http://en.wikipedia.org/wiki/No_Silver_Bullet" title="No Silver Bullet" target="nsb"><i>No Silver Bullet</i></a> in support of the assertion that big-A Agile methods cannot possibly be better than other ways of getting software delivered.  Besides suffering from the fallacy of appeal to authority (however meritorious Mr. Brooks&#8217;s authority in our field might be), it also falls a bit flat to cite <i>NSB</i> in an anti-Scrum screed. To wit:</p>
<blockquote><p>Incremental development&#8211;grow, don&#8217;t build, software. I still remember the jolt I felt in 1958 when I first heard a friend talk about building a program, as opposed to writing one. In a flash he broadened my whole view of the software process. The metaphor shift was powerful, and accurate. Today we understand how like other building processes the construction of software is, and we freely use other elements of the metaphor, such as specifications, assembly of components, and scaffolding.</p>
<p>The building metaphor has outlived its usefulness. It is time to change again. If, as I believe, the conceptual structures we construct today are too complicated to be specified accurately in advance, and too complex to be built faultlessly, then we must take a radically different approach.</p>
<p>Let us turn nature and study complexity in living things, instead of just the dead works of man. Here we find constructs whose complexities thrill us with awe. The brain alone is intricate beyond mapping, powerful beyond imitation, rich in diversity, self-protecting, and selfrenewing. The secret is that it is grown, not built.</p>
<p>So it must be with our software-systems. Some years ago Harlan Mills proposed that any software system should be grown by incremental development. That is, the system should first be made to run, even if it does nothing useful except call the proper set of dummy subprograms. Then, bit by bit, it should be fleshed out, with the subprograms in turn being developed&#8211;into actions or calls to empty stubs in the level below.</p>
<p>I have seen most dramatic results since I began urging this technique on the project builders in my Software Engineering Laboratory class. Nothing in the past decade has so radically changed my own practice, or its effectiveness. The approach necessitates top-down design, for it is a top-down growing of the software. It allows easy backtracking. It lends itself to early prototypes. Each added function and new provision for more complex data or circumstances grows organically out of what is already there.</p>
<p>The morale effects are startling. Enthusiasm jumps when there is a running system, even a simple one. Efforts redouble when the first picture from a new graphics software system appears on the screen, even if it is only a rectangle. One always has, at every stage in the process, a working system. I find that teams can grow much more complex entities in four months than they can build.</p></blockquote>
<p>(The above is, of course, excerpted from Brooks&#8217;s essay.)</p>
<p>Iterative development that delivers frequent releases of working software, and uses feedback to determine the direction of growth for the next increment? And a report of empirical (if decidedly anecdotal) support for the notion?</p>
<p>Sounds pretty Agile to me.</p>
<p>(The full essay is available in <i><a href="http://www.amazon.com/gp/product/0201835959/ref=as_li_ss_tl?ie=UTF8&#038;tag=bradandkristshom&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0201835959" target="mmm">The Mythical Man-Month: Essays on Software Engineering</a><img src="http://www.assoc-amazon.com/e/ir?t=bradandkristshom&#038;l=as2&#038;o=1&#038;a=0201835959" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />,</i> which I recommend to anyone who writes, builds, grows, or otherwise makes software.)</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F12%2F28%2Fagile-vs-no-silver-bullet%2F&amp;title=Agile%20vs.%20No%20Silver%20Bullet" id="wpa2a_2"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yet Another Backbone.js Tutorial – Part 2 – Pre-Reqs &amp; The Spec</title>
		<link>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/</link>
		<comments>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 04:50:01 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[underscore.js]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=529</guid>
		<description><![CDATA[Please checkout Part 1 where I explain the philosophy behind Backbone.js It&#8217;s time to build our Backbone.js app, &#8220;Comment on the Movies&#8221;.  This tutorial will, ideally, give you something interesting to build.  Take a look at the finished app (so far) on &#8230; <a href="http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em><a title="Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy" href="http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/">Please checkout <strong>Part 1</strong> where I explain the philosophy behind Backbone.js</a></em></p>
<p>It&#8217;s time to build our Backbone.js app, &#8220;Comment on the Movies&#8221;.  This tutorial will, ideally, give you something interesting to build.  Take a look at <strong><a href="http://commentonthemovies.heroku.com" target="_blank">the finished app (so far) on Heroku</a></strong> &amp; feel free to <strong><a href="https://github.com/abelmartin/Comment-On-The-Movies/tree/KAL_Post_Part_2" target="_blank">pull it from GitHub</a></strong>.  In addition, I&#8217;ve updated the code to use Backbone.js 0.5.3, Underscore 1.2.2, Mustache 0.3 &amp; jQuery 1.7.1.  Let&#8217;s do this!<span id="more-529"></span></p>
<p>*Before we get started, check out one more resource: Charlie Robbins (Co-Founder of <a href="http://nodejitsu.com/" target="_blank">Nodejitsu</a>) wrote an awesome article about <a href="http://blog.nodejitsu.com/scaling-isomorphic-javascript-code" target="_blank">Scaling Isomorphic Javascript Code</a>.  In the writeup, he describes popular methodologies in retrieving data and presenting it to the user.  It&#8217;s a great read.  The image below from that article:</p>
<div class="wp-caption aligncenter" style="width: 450px"><img src="http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/mvvm.png" alt="" width="440" height="369" /><p class="wp-caption-text">Backbone.js interactions: Model-View-ViewModel</p></div>
<h2>Prerequisites:  Rotten Tomatoes API Account, Ruby, Sinatra, &amp; Haml</h2>
<h3>Rotten Tomatoes API Account</h3>
<p>The app we&#8217;re writing is called &#8220;Comment On The Movies&#8221;.  The RottenTomatoes API is full of well formed data (which is more than I can say about the New York Times movie api calls).  Real data is always more interesting than building dummy datasets ourselves.</p>
<p><strong><a href="http://developer.rottentomatoes.com/" target="_blank">The Rotten Tomatoes API registration is free, quick &amp; painless</a></strong>.  Get your api_key &amp; come back to this tutorial.</p>
<p>We&#8217;ll also be using <strong><a href="http://images.rottentomatoes.com/assets.html" target="_blank">the R.T. assets</a></strong>.  R.T. makes their images available to developers to use in their apps and we&#8217;ll be taking advantage.</p>
<h3>Ruby (<a href="http://www.ruby-lang.org/en/" target="_blank">Project Site</a>)</h3>
<p>Realistically, if you&#8217;re reading this webpage, you probably already have it installed (even if you don&#8217;t use it) <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .  I chose Ruby here because I 9-5 in Ruby and I really enjoy it.  You can use ANY server side scripting language here (PHP, Asp.NET, JSP), but <span style="text-decoration: underline;"><strong>you need to use something</strong></span>. You don&#8217;t want to simply expose your R.T. API App Key to the world.  By using a server side language, you can create a proxy page that protects your API App Key.  Here&#8217;s how this app will work:</p>
<ol>
<li>Your Backbone app makes an AJAX call with R.T. API parameters to the proxy page</li>
<li>The proxy page appends your API_KEY &amp; makes the call to a R.T. servers</li>
<li>The proxy page receives the response and returns it to your Backbone app</li>
<li>The Backbone app updates it&#8217;s UI.</li>
</ol>
<h3>Sinatra (<a href="http://www.sinatrarb.com/intro" target="_blank">Project Site</a>)</h3>
<p>Since we only need an index page and a proxy, Sinatra is a perfect option here.  A full Rails app would be WAY too much.</p>
<h3>Haml (<a href="http://haml-lang.com/" target="_blank">Project Site</a>)</h3>
<p>I enjoy haml.  It&#8217;s really easy to create markup with it.</p>
<h2>The &#8220;Comment on the Movies&#8221; Spec</h2>
<p>Here&#8217;s what the app needs to accomplish:<br />
<span style="color: #ff6600;">**Items in orange will be implemented in future tutorial posts**</span></p>
<ul>
<li>Users should be able to switch between the various lists of R.T. data:</li>
<ul>
<li>Box Office (default view on page load)</li>
<li>In Theaters</li>
<li>Opening</li>
<li>Upcoming</li>
</ul>
<li>The &#8220;Movies Table&#8221; should display:
<ul>
<li>Title</li>
<li>Year</li>
<li>MPAA Rating (R, PG-13, etc)</li>
<li>Runtime</li>
<li>Release Date (default sort)</li>
<li>Critic&#8217;s Score</li>
<ul>
<li>If it&#8217;s &#8216;certified fresh&#8217; that should be indicated.</li>
</ul>
<li><span style="color: #ff6600;">Number of comments</span></li>
</ul>
</li>
<li><span class="Apple-style-span" style="color: #000000;">Clicking on a table column title should sort the current set of movies in the table.</span></li>
<li><span style="color: #ff6600;">Clicking on a movie&#8217;s row should take you to a &#8220;detailed&#8221; view of the film.  The &#8220;detailed&#8221; view should display: </span>
<ul>
<li><span style="color: #ff6600;">Links [all links that lead us away from the site should open in a new window] to&#8230;</span>
<ul>
<li><span style="color: #ff6600;">Showtimes</span></li>
<li><span style="color: #ff6600;">Awards (if any)</span></li>
<li><span style="color: #ff6600;">Trailers</span></li>
<li><span style="color: #ff6600;">Abridged Cast</span></li>
<li><span style="color: #ff6600;">IMDB records</span></li>
</ul>
</li>
</ul>
</li>
<li><span style="color: #ff6600;">Comments </span>
<ul>
<li><span class="Apple-style-span" style="color: #ff6600;">Add a new comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Edit an existing comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Delete a comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Require that the review indicates if the comment is BEFORE or AFTER you&#8217;ve seen the movie</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Comments should persists across browser restarts</span></li>
</ul>
</li>
<li>The app needs to be crawl-able by Google.</li>
<li><span style="color: #ff6600;">It needs to be well tested</span></li>
</ul>
<h2>Make your Backbone App Google Crawl-able via hashbang URLs</h2>
<p>Hashbanging (/#!) your URLs let&#8217;s the <a href="http://code.google.com/web/ajaxcrawling/docs/getting-started.html">Google crawling bot know that there&#8217;s AJAXed content on this page</a>.  Fortunately, it&#8217;s really easy in Backbone.js <a href="http://commentonthemovies.heroku.com/" target="_blank">as you can see in the live demo</a></p>
<h2>In The Next Post&#8230;</h2>
<p>I&#8217;ll explain how I implemented the app thus far.  That&#8217;ll include the filling the index view &amp; the hashbang technique mentioned above.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F11%2F27%2Fyet-another-backbone-js-tutorial-%25e2%2580%2593-part-2-%25e2%2580%2593-prereqs-and-the-spec%2F&amp;title=Yet%20Another%20Backbone.js%20Tutorial%20%E2%80%93%20Part%202%20%E2%80%93%20Pre-Reqs%20%26%23038%3B%20The%20Spec" id="wpa2a_4"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Traveling Salesman Attack! (Hadoop and Genetic Algorithms)</title>
		<link>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/</link>
		<comments>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 15:49:15 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[hadoop]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Just for Kicks]]></category>
		<category><![CDATA[genetic algorithms]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[traveling salesman]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=669</guid>
		<description><![CDATA[For one of my &#8220;coffee projects&#8221; (things I work on for about 20-30 minutes each morning to warm my brain up and stay amused), I wrote a genetic algorithm attack on the Traveling Salesman problem. Because I&#8217;m a Big Data &#8230; <a href="http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For one of my &#8220;coffee projects&#8221; (things I work on for about 20-30 minutes each morning to warm my brain up and stay amused), I wrote a <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">genetic algorithm</a> attack on the <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Traveling Salesman problem</a>. Because I&#8217;m a Big Data geek, I parallelized it with <a href="http://hadoop.apache.org">Hadoop</a>.</p>
<p><i>(Note:  I actually gave a talk on this topic some time back, having implemented this same concept in Ruby using Hadoop Streaming.  That implementation contained a number of flaws, some of which I&#8217;m attempting to rectify.  Also, <a href="http://scholar.google.com/scholar?q=hadoop+genetic+algorithm&#038;hl=en&#038;as_sdt=0&#038;as_vis=1&#038;oi=scholart">it&#8217;s not as though I&#8217;m the first guy to work this angle</a>. I haven&#8217;t perused the latest Hadoop/GA work in the field yet, because I wanted to maximize my first-hand learning at this stage &#8211; but I&#8217;ll be looking to other sources for inspiration as I develop and generalize this code.)</i></p>
<p>This was just done for my own edification; I haven&#8217;t put enough effort into tuning this software or studying its properties for this to be considered a serious work of research (yet). I&#8217;m not a specialist or any kind of expert with genetic algorithms, beyond my recreational reading. That said, I had some success at building a gene representation and evolutionary mechanisms that drove a population of solutions for an NP-hard problem toward (mostly) monotonic improvement.</p>
<p>What follows is a brief description of my approach to the problem, with code attached. If you <em>are</em> an expert with GAs, I&#8217;d love to hear your feedback on what I could do better.</p>
<p>I haven&#8217;t spent any effort in this post describing the <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Traveling Salesman problem</a>, <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">genetic algorithms</a>, or <a href="http://hadoop.apache.org">Hadoop</a>/MapReduce. (It was plenty long already.)  If you&#8217;re interested in any of those topics but need to brush up on the basics, check out the preceding links.</p>
<p>More geekery below the fold&#8230;</p>
<p><span id="more-669"></span></p>
<p><strong>The Map</strong></p>
<p>A &#8220;city&#8221; in my representation is an (x, y) coordinate pair, with each coordinate having a floating-point value in [0.0, 1.0). The software can take any arrangement of cities, but for testing I used an arrangement with a set of trivial solutions:</p>
<table>
<tbody>
<tr>
<td>(0.0, 0.0)</td>
<td>(0.0, 0.2)</td>
<td>(0.0, 0.4)</td>
<td>(0.0, 0.6)</td>
<td>(0.0, 0.8)</td>
</tr>
<tr>
<td>(0.0, 1.0)</td>
<td>(0.2, 1.0)</td>
<td>(0.4, 1.0)</td>
<td>(0.6, 1.0)</td>
<td>(0.8, 1.0)</td>
</tr>
<tr>
<td>(1.0, 1.0)</td>
<td>(1.0, 0.8)</td>
<td>(1.0, 0.6)</td>
<td>(1.0, 0.4)</td>
<td>(1.0, 0.2)</td>
</tr>
<tr>
<td>(1.0, 0.0)</td>
<td>(0.8, 0.0)</td>
<td>(0.6, 0.0)</td>
<td>(0.4, 0.0)</td>
<td>(0.2, 0.0)</td>
</tr>
</tbody>
</table>
<p><strong>Gene Representation</strong></p>
<p>When choosing a non-repeating path among <em>N</em> distinct cities, there are <em>N</em> possible choices for the first city; <em>N-1</em> choices for the second city, and so on; and only one choice for the final city.</p>
<p>In my representation, a chromosome has <em>N &#8211; 1</em> integer genes. For a gene <em>G<sub>n</sub>,</em> valid values are <em>[0, N - n)</em> &#8211; thus, the first gene has <em>N</em> valid values, the second gene <em>N &#8211; 1,</em> and so on. Each gene corresponds to the 0-based index of a city in an ordered collection of the cities not yet accounted for in the path. For example, if we start with an ordered collection of cities <em>{C<sub>0</sub>, C<sub>1</sub>, C<sub>2</sub>},</em> and the chromosome<em> {0, 0}:</em></p>
<ul>
<li>The first city in this candidate solution path is at index 0 in the collection:  <em>C<sub>0</sub></em></li>
<li>The second city in the path is at index 0 in the collection of remaining cities, <em>{C<sub>1</sub>, C<sub>2</sub>}: C<sub>1</sub></em></li>
<li>The final city is trivially <em>C<sub>2</sub></em>.</li>
</ul>
<p>Likewise, the chromosome <em>{1, 1}</em> encodes the path <em>C<sub>1</sub> -&gt; C<sub>2</sub> -&gt; C<sub>0</sub>.</em></p>
<p><strong>Fitness Scoring</strong></p>
<p>Here I&#8217;ve implemented the <i>symmetric</i> Traveling Salesman problem (the distance/cost from <i>C<sub>1</sub></i> to <i>C<sub>2</sub></i> is the same as from <i>C<sub>2</sub></i> to <i>C<sub>1</sub></i>), and the distance between cities is just the Cartesian distance between their coordinates.  The maximum possible distance between any two cities in the landscape I&#8217;ve defined is <em>√<span style="text-decoration: overline;">2</span></em>, so the maximum/worst-case distance possible for an <em>N</em>-city map is <em>(N &#8211; 1) * √<span style="text-decoration: overline;">2</span></em>.</p>
<p>A chromosome&#8217;s score is this worst-case distance minus the actual distance of the path it encodes; thus, the greater the improvement over the theoretically pessimal case, the higher the chromomsome&#8217;s score.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ChromosomeScorer <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">ArrayList</span> cities<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">ArrayList</span> citiesUsed<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">double</span> SQRT2 <span style="color: #339933;">=</span> <span style="color: #003399;">Math</span>.<span style="color: #006633;">sqrt</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2.0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">double</span> maxDistance<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ChromosomeScorer<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> cityString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        cities <span style="color: #339933;">=</span> getCitiesFromString<span style="color: #009900;">&#40;</span>cityString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        citiesUsed <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span>cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        maxDistance <span style="color: #339933;">=</span> SQRT2 <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            citiesUsed.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">Boolean</span>.<span style="color: #000066; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">double</span> score<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> chromosomeString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">ArrayList</span> route <span style="color: #339933;">=</span> getRouteFromChromosome<span style="color: #009900;">&#40;</span>chromosomeString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">double</span> distance <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.0</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">int</span> city1Index <span style="color: #339933;">=</span> route.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">int</span> city2Index <span style="color: #339933;">=</span> route.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> city1 <span style="color: #339933;">=</span> cities.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>city1Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> city2 <span style="color: #339933;">=</span> cities.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>city2Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span> city1x <span style="color: #339933;">=</span> city1<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">double</span> city1y <span style="color: #339933;">=</span> city1<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span> city2x <span style="color: #339933;">=</span> city2<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">double</span> city2y <span style="color: #339933;">=</span> city2<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
            distance <span style="color: #339933;">+=</span> <span style="color: #003399;">Math</span>.<span style="color: #006633;">sqrt</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>city1x <span style="color: #339933;">-</span> city2x<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>city1x <span style="color: #339933;">-</span> city2x<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>city1y <span style="color: #339933;">-</span> city2y<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>city1y <span style="color: #339933;">-</span> city2y<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> maxDistance <span style="color: #339933;">-</span> distance<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// city string parsing code elided</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The <tt>ArrayList</tt> is a list of flags indicating whether a city has been added to the route yet; it&#8217;s for implementing the chromosome parsing I described above. In my example, I described the process in terms of pulling elements from an ordered collection, and performing further operations on the reduced collection. Regenerating the ordered list of cities and manipulating it in this way every time I wanted to score a chromosome sounded computationally expensive; flipping booleans sounded cheaper. (I could probably get cheaper still using actual bit flags, but I was trying to keep the code both readable and writable at this stage. Optimizations will come later.)</p>
<p><strong>Initial Population</strong></p>
<p>The following code creates an initial population of chromosomes (encoded as Strings) and dumps them to a requested file:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> createInitialPopulation<span style="color: #009900;">&#40;</span>FSDataOutputStream populationOutfile, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> populationSize, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> numCities<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> populationSize<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;</span> <span style="color: #009900;">&#40;</span>numCities <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>j<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
             <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span>.<span style="color: #006633;">format</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;%d&quot;</span>, random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>numCities <span style="color: #339933;">-</span> j<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    populationOutfile.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>At a later time, I&#8217;ll experiment with using Hadoop&#8217;s ArrayWritable or other serialization schemes for more efficient representation of the chromosomes; at this stage, it was important to me to keep the data human-readable.</p>
<p>There&#8217;s a mapper dedicated to scoring generation 0:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ScoringMapper <span style="color: #000000; font-weight: bold;">extends</span> Mapper <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> Text outKey <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Text<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> DoubleWritable outValue <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DoubleWritable<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> ChromosomeScorer scorer <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> map<span style="color: #009900;">&#40;</span>LongWritable key, Text value, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">String</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">split</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">String</span> chromosome <span style="color: #339933;">=</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">double</span> score <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.0</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>incomingValue.<span style="color: #006633;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003399;">String</span> scoreString <span style="color: #339933;">=</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
                score <span style="color: #339933;">=</span> <span style="color: #003399;">Double</span>.<span style="color: #006633;">parseDouble</span><span style="color: #009900;">&#40;</span>scoreString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">NumberFormatException</span> nfe<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// weird - but let's try re-generating the score</span>
                score <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">// we only go through the scoring process if we don't have a map</span>
            score <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        outValue.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>score<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>chromosome<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, outValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// setup code elided</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Subsequent Generations</strong></p>
<p>I managed to cram the rest of the operations for each generation into one mapper and one reducer &#8211; really, into one reducer, since the map function just randomly assigns chromosomes to groups:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> map<span style="color: #009900;">&#40;</span>LongWritable key, Text value, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>numBins<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// shuffle</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>So why am I shuffling the chromosomes thus? Most methods of population <a href="http://en.wikipedia.org/wiki/Selection_(genetic_algorithm)">selection</a> involve having some view over the data; the naïve method of <a href="http://en.wikipedia.org/wiki/Truncation_selection">truncation selection</a> is an extreme example, where you need to sort the entire population, and keep some fraction of the highest-scoring individuals. This is hard to parallelize, and not especially scalable for large populations.</p>
<p>Other selection methods such as <a href="http://en.wikipedia.org/wiki/Fitness_proportionate_selection">fitness proportionate selection</a>, however, look like they&#8217;d retain their properties well if the total population was divided into large, random subpopulations. (I have yet to do a detailed mathematical treatment of this, but some combination of intuition and cocktail napkin calculation has convinced me of this well enough to forge ahead.) To this end, I&#8217;ve set up the system to randomly distribute the full population into a user-settable number of subpopulations; the size of these subpopulations can be tuned to fit within the memory allocated to a reducer instance. (Naturally, the ideal would be to have a subpopulation just large enough to be handled by one reducer instance.) Assuming that the subpopulations are sufficiently large, the random distribution should retain the aggregate characteristics (distribution of fitness scores, &amp;c) of the total population, and give similar results under fitness proportionate selection.</p>
<p>After this subdivision of the population, a reducer instance receives a subpopulation, and is then responsible for selecting survivors from that population, breeding replacement members of the population from the survivors, and scoring the new population members.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> reduce<span style="color: #009900;">&#40;</span>VIntWritable key, Iterable values, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">TreeSet</span> sortedChromosomes <span style="color: #339933;">=</span> getSortedChromosomeSet<span style="color: #009900;">&#40;</span>values<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        normalizeScores<span style="color: #009900;">&#40;</span>sortedChromosomes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">int</span> survivorsWanted <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#41;</span> sortedChromosomes.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> survivorProportion<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">Set</span> survivors <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashSet</span><span style="color: #009900;">&#40;</span>survivorsWanted<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>survivors.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> survivorsWanted<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            survivors.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>selectSurvivor<span style="color: #009900;">&#40;</span>sortedChromosomes<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">ArrayList</span> parentPool <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span>survivors<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>survivors.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> desiredPopulationSize<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            survivors.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>makeOffspring<span style="color: #009900;">&#40;</span>parentPool<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">Iterator</span> iter <span style="color: #339933;">=</span> survivors.<span style="color: #006633;">iterator</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>iter.<span style="color: #006633;">hasNext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            ScoredChromosome sc <span style="color: #339933;">=</span> iter.<span style="color: #006633;">next</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>sc.<span style="color: #006633;">chromosome</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            outValue.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>sc.<span style="color: #006633;">score</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, outValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Selection:</strong> The first step in fitness proportionate selection is to sort the new members according to their score, ascending. After that, survivors are selected from the population randomly, weighted by their scores (the higher a chromosome&#8217;s score, the more likely it is to survive).</p>
<p><strong>Repopulation:</strong> Surviving chromosomes are used to breed back up to our original population numbers. I used single crossover and random mutations (maximum of one mutation per chromosome per generation):</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">protected</span> ScoredChromosome makeOffspring<span style="color: #009900;">&#40;</span><span style="color: #003399;">ArrayList</span> parentPool<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">int</span> parent1Index <span style="color: #339933;">=</span> random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>parentPool.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> parent2Index <span style="color: #339933;">=</span> parent1Index<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>parent2Index <span style="color: #339933;">==</span> parent1Index<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parent2Index <span style="color: #339933;">=</span> random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>parentPool.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        ScoredChromosome parent1 <span style="color: #339933;">=</span> parentPool.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>parent1Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ScoredChromosome parent2 <span style="color: #339933;">=</span> parentPool.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>parent2Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        ScoredChromosome offspring <span style="color: #339933;">=</span> crossover<span style="color: #009900;">&#40;</span>parent1, parent2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>random.<span style="color: #006633;">nextDouble</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> mutationChance<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            mutate<span style="color: #009900;">&#40;</span>offspring<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        offspring.<span style="color: #006633;">score</span> <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>offspring.<span style="color: #006633;">chromosome</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> offspring<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Scoring:</strong> Finally, all unscored population members are scored in preparation for the next round.</p>
<p>This process is repeated for as many generations as is specified at the beginning of the run.  (Later, I plan to allow the number of generations to be unspecified, and have the algorithm terminate when the maximum score starts to settle/converge.)</p>
<p><strong>Parameters</strong></p>
<ul>
<li>Number of cities</li>
<li>Population size</li>
<li>Proportion of survivors in each generation</li>
<li>Subpopulation size (see above for rationale for dividing up the population, and thoughts on tuning)</li>
<li>Chance of random mutation</li>
<li>Number of generations</li>
</ul>
<p><strong>Results</strong></p>
<p>I&#8217;ve thrown the data for min/max/mean scores for each generation of each run into a <a href="https://docs.google.com/spreadsheet/ccc?key=0AkBz3y6su8VvdHNkMGdFYnlSdmNhZ1hNOW5GTWwtb0E&#038;hl=en_US">Google spreadsheet</a>, and made some simple graphs.</p>
<p>The first run was done with 10,000-member population, 30% survival chance, 500 generations.  There&#8217;s an unmistakable fitness increase over time, and it gets pretty close to the theoretical maximum for my test city (~23.066).</p>
<p>The second run was done with a 100,000-member population and 50% survival chance, 500 generations.  It gets off to a slower start, but there&#8217;s a burst of improvement late in the 500-generation run and it gets pretty close to the optimum.</p>
<p>The difference in early-stage performance of the second run had me kicking myself for changing <i>two</i> inputs.  I switched back to a 30% survival chance but kept the larger population.  This run landed in the same neighborhood as the others, and looked like it still had room to settle.</p>
<p>Interesting to note on all 3 runs is that all start with a few generations of quick improvement, then flatten out, then have an inflection point after which there&#8217;s a burst of quick improvement.  (<a href="http://en.wikipedia.org/wiki/Punctuated_equilibrium">Punctuated equilibrium</a>?)  All runs seem to still be on the climb; I suspect that a moving average over a few generations and/or some statistical tests for convergence would give a clearer picture of what&#8217;s happening with the max trend; the average was still definitely on the rise at the end of all three runs.</p>
<p><strong>Notes</strong></p>
<p>Test coverage could be improved, especially with the use of mocks.  I may move to <a href="https://ccp.cloudera.com/display/SUPPORT/Downloads">CDH3</a> and try <a href="http://www.cloudera.com/blog/2009/07/debugging-mapreduce-programs-with-mrunit/">MRUnit</a> to ease test design.  As it stands I&#8217;m taking most of the logic out of the mappers and reducers and just using the overridden map() and reduce() functions to coordinate the calls that do the actual work, largely to make it easier to test the logic in isolation.</p>
<p>For the sake of speed, I could probably take out some of the square roots and do my scoring using the squares of the distances.</p>
<p>On my 13&#8243; MacBook Pro with Core Duo processor running 2 mappers and 2 reducers, a population of 10,000 took 45-60 seconds to cull, breed, and score. The time per generation didn&#8217;t change appreciably when I went from 10,000 chromomsomes per generation to a population of 100,000 &#8211; which means most of my time is still spent in Hadoop overhead, which means that even on my little laptop, I could put up much bigger populations (or much bigger maps) and still run 500 generations in about 6 hours.</p>
<p>I haven&#8217;t bothered taking the simulation parameters in via the command line yet; this would be an obvious improvement, and probably the next thing I&#8217;ll do. I was a lot more focused on getting the GA code right and checking that it behaved as expected than I was with making a usable tool.  I&#8217;ve gotten the itch to generalize and grow this thing, though, so I&#8217;ll need to start making it usable &amp; configurable &amp; scriptable.</p>
<p>Clearly, this is not a general toolkit for GA, or even GA applied to NP-hard problems. (I don&#8217;t like to generalize without at least two cases.) I do see plenty of places where it is generalizable, though, and will starting doing so as soon as I pick a second problem to attack. A long-term goal is to factor out a library/API for doing GA on Hadoop.</p>
<p>Genetic algorithms are not one single thing &#8211; there are multiple strategies for culling populations, doing crossover/breeding, etc. A longer-term design goal is to make each of those variable pieces of the algorithm into pluggable strategies selectable from the command line.</p>
<p>There&#8217;s optimization to do all over the place, e.g. with the multiple copies of data kept in the reducer. I chose the data structures I used for ease of implementing the algorithm &#8211; e.g., picking a Set to hold survivors so as to avoid picking up duplicate survivors &#8211; with the intent to get working software quickly, and <a href="http://www.irocon.com/blog/2006/09/07/optimize-last.aspx">optimize last</a>.</p>
<p><strong>The Code</strong></p>
<p>The code, such as it is, is in a <a href="https://github.com/bradheintz/TravSales">public repository on GitHub</a>.  More to come.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F10%2F10%2Ftraveling-salesman-attack%2F&amp;title=Traveling%20Salesman%20Attack%21%20%28Hadoop%20and%20Genetic%20Algorithms%29" id="wpa2a_6"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Node Knockout 2011 Post Mortem</title>
		<link>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/</link>
		<comments>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 07:21:40 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Nodejs]]></category>
		<category><![CDATA[Post Mortem]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[competition]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[nodeknockout]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=633</guid>
		<description><![CDATA[Node Knockout 2011 took place this past weekend.  I signed up with the hope of being a &#8220;One Man Army&#8221; &#38; winning the solo contestant award.  I figured that NodeJs was so easy to use and so powerful (seriously, it&#8217;s freaking awesome) that &#8230; <a href="http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://nodeknockout.com/" target="_blank">Node Knockout 2011</a> took place this past weekend.  I signed up with the hope of being a &#8220;One Man Army&#8221; &amp; winning the <a href="http://nodeknockout.com/prizes" target="_blank">solo contestant</a> award.  I figured that <a href="http://nodejs.org/" target="_blank">NodeJs</a> was so easy to use and so powerful (seriously, it&#8217;s freaking awesome) that it&#8217;d be child&#8217;s play.  I unfortunately bit more than I can chew however.</p>
<p><a href="https://twitter.com/codinghorror" target="_blank">Jeff Atwood</a> once blogged: &#8220;<a href="http://www.codinghorror.com/blog/2006/11/the-project-postmortem.html" target="_blank">I don&#8217;t think it matters how you conduct the postmortem, as long as you do it</a>&#8220;.  To that end, here&#8217;s my post mortem of the app I <strong>didn&#8217;t</strong> finish.  Ideally  other developers will learn from my successes and mistakes.  :)</p>
<p><span id="more-633"></span><span style="text-decoration: underline;"><strong>The App/Idea</strong></span>: A web version of my iphone app ( <a href="http://www.touchplaybook.com/" target="_blank">Touch Playbook</a> ) called Playbook Nodes.  I learned a lot creating TPB and I figured I&#8217;d learn a lot porting the code as well.  I emailed the contest organizers early to make sure I wasn&#8217;t going to violate the following rule:</p>
<p style="padding-left: 30px;">&#8220;Of course, feel free to work on the concept for your application before the competition starts: pretty hand-drawn pictures on napkins, angry email threads between team members on two-space or four-space indentation, schema designs, finite state machines.  Just no digital assets including graphic design assets, code, etc.&#8221;</p>
<p style="padding-left: 30px;">~<a href="http://nodeknockout.com/rules">Node Knockout Rules</a></p>
<p>They gave me the green light, so I starting researching the parts of the app I&#8217;d need to understand.  Looking back, here were my mistakes:</p>
<p><span style="text-decoration: underline;"><strong>Mistake #1: Doing too much</strong></span><br />
Heading into the competition, my goal was to recreate the entire app.  That includes the user interactions (dragging players, passing the ball, shooting, etc), full replay animation logic, &amp; state management.  On top of that, I wanted to add new features like user accounts and the ability to share pays.  Considering that it took me 5 months to build TPB (1 month to spec / 3 months to implement / 1 month of user testing ), this order was WAY too tall.  In hindsight, <strong>I should have simply picked another project</strong>.  Anything TPB inspired that&#8217;d be worthwhile would simply take too long.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #2: Assuming that things will simply fit together</strong></span><br />
I assumed that I&#8217;d simply figure out how to elegantly draw paths as the user dragged players (and animate the process later) despite the fact that I couldn&#8217;t find good examples of animating the drawing of paths and I&#8217;d never done it before using Raphael.  I also assumed Mongoose-Auth would be easily to implement and&#8230;well..would just work.  Both of these assumptions cost me precious time.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #3: Oversleeping</strong></span><br />
I was hoping to get about 5-6 hours of sleep each night.  Instead I got 7-8 each night.  I felt great, but I wish I had the extra hours to code.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #4: Failing to achieve a &#8220;thin line through&#8221; in the first 24 hours</strong></span><br />
This might be the most telling sign of failure in a 48 hour competition.  It&#8217;s really important to get a barebones version of your app working before you continue working on the features in your spec.  The 24 span INCLUDES server setup.</p>
<p>It wasn&#8217;t all bad though.  Here are some things I did right:</p>
<p><span style="text-decoration: underline;"><strong>Success #1: Spec&#8217;d as much as I could BEFORE the competition</strong></span><br />
<a href="https://gomockingbird.com/" target="_blank">Mockingbird</a> was super handy way to mock views &amp; my trusty notebook saved my thoughts in the weeks leading to the competition.  Also, I was able to pull my notes from the creation of TPB which helped a bunch.</p>
<p><span style="text-decoration: underline;"><strong>Success #2: Improved my overall JavaScript skills &amp; got comfortable writing node JavaScript before the competition</strong></span><br />
I&#8217;m new to Node.js, but I&#8217;m not new to web development.  I have to shamefully admit that I used to think of JavaScript as a sub-language whose only use were silly DOM tricks.  Fortunately, I started following the works of Douglas Crockford and saw the light.  Not too long after that, I start hearing about NodeJS &amp; I started soaking up examples around the first week in August.  I turned my knowledge harvesting into overdrive &amp; gained the confidence I needed to enter the competition .  Here are some of the things that I did:</p>
<ul>
<li><a href="http://www.yuiblog.com/crockford/" target="_blank">Watched 7.5 hours</a> of Douglas Crockford&#8217;s presentations</li>
<ul>
<li>Also kept a copy of &#8220;<a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/ref=sr_1_1?ie=UTF8&amp;qid=1314686380&amp;sr=8-1" target="_blank">Javascript: The Good Parts</a>&#8221; close by at all times <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<li>Attending a free training by the co-founders of <a href="http://nodejitsu.com/" target="_blank">Nodejitsu</a>, (<a href="https://twitter.com/hij1nx" target="_blank">@hij1nx</a> &amp; <a href="https://twitter.com/indexzero" target="_blank">@indexzero</a>)</li>
<li>Watching as many <a href="http://nodetuts.com/" target="_blank">NodeTuts</a> as I possible could and coding the examples in the vids.</li>
<li><a href="http://nodeguide.com/" target="_blank">Felix&#8217;s Node.js Guide</a></li>
<ul>
<li>Tons of links to helpful content &amp; people to follow (twitter, blogs, etc).</li>
</ul>
<li>Watching videos by <a href="http://twitter.com/ryah" target="_blank">Ryan Dahl</a>, the creator of Node.js</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Success #3: I went with Heroku instead of Linode or Joyent</strong></span><br />
I didn&#8217;t want to lose time configuring a server.  The purpose of the competition is the app that I create, not testing my Sys-Admin skills.  Going with Heroku saved me the headache that many of my fellow participants faced.  Some teams never got their server setup, but I was deploying early and easily.</p>
<p><span style="text-decoration: underline;"><strong>Success #4: Logging my actions</strong></span><br />
Every hour, on the hour, I wrote a summary of how I spent my time.  If I started writing a bunch of code, I&#8217;d shorten my logging to 30 minute intervals.  This was helpful because it drove me to get small victories at least once an hour.</p>
<p><span style="text-decoration: underline;"><strong>Success #5: In Backbone.js apps, add a global logging function</strong></span><br />
I started doing this in every Backbone app that I create.  I add 3 simple methods to my controller/router definition.  This gives me a name-spaced way to log &amp; benchmark events from my controllers, models &amp; views.  It also gives me a clean way to disable logging when I deploy to production &amp; an easy way to toggle the logging once the code is deployed to prod.</p>
<ul>
<li>debugEnv()</li>
<ul>
<li>The router/controller has a variable called &#8216;debug&#8217; which is set to true/false.</li>
<li>The first line of the method looks like this:<br />
<strong>return (this.debug &amp;&amp; (typeof console !== &#8216;undefined&#8217;)); </strong></li>
</ul>
<li>logEvent(message)</li>
<ul>
<li>This method returns if the controller/router&#8217;s debug method is off<br />
<strong>if(! this.debugEnv() ){ return; }  </strong></li>
<li>Otherwise:<br />
<strong>console.log( (new Date()).toTimeString() + &#8220;: &#8221; + message); </strong></li>
</ul>
<li>benchEvent(handle, operand_string)</li>
<ul>
<li>This method needs to use console.time() &amp; console.timeEnd() so it makes sure that we can debug AND that the &#8216;time&#8217; method exists (This is a problem on IE):<br />
<strong>if(! this.debugEnv() || typeof console.time === &#8216;undefined&#8217; ){ return; }</strong></li>
<li>Otherwise, depending on the &#8216;operand_string&#8217;, &#8230;<br />
<strong>case &#8216;+&#8217; : console.time(handle); break;</strong><br />
<strong>case &#8216;-&#8217;: console.timeEnd(handle); break;</strong></li>
</ul>
</ul>
<p><span class="Apple-style-span" style="color: #444444; font-family: Georgia, 'Bitstream Charter', serif; font-size: 16px; line-height: 24px;">This makes it really easy to track what my app is doing and provides simple benchmarking.  I find it super helpful! </span></p>
<p><span style="text-decoration: underline;"><strong>Success #6: Entering Node Knockout 2011</strong></span><br />
The biggest success was taking part in the competition.   I learned so much more about <a href="http://www.expressjs.com/" target="_blank">ExpressJS</a>, <a href="https://github.com/visionmedia/jade" target="_blank">Jade</a>, <a href="http://learnboost.github.com/stylus/docs/js.html" target="_blank">Stylus</a>, <a href="http://mongoosejs.com/" target="_blank">Mongoose</a>, <a href="http://www.mongodb.org/" target="_blank">MongoDB</a>, <a href="http://www.colorzilla.com/gradient-editor/" target="_blank">CSS3 Gradients</a>, and more because I challenged myself.  Was I ready for every single challenge I faced? Absolutely not!  However, failing with focused effort is better than never trying at all.</p>
<p><span style="text-decoration: underline;"><strong>In Conclusion</strong></span><br />
I look forward to Node Knockout 2012.  I&#8217;m probably going to start spec&#8217;ing even earlier and I&#8217;ll be more realistic about what can be accomplished in 48 hours.  I also intend to complete PlaybookNodes.  While I didn&#8217;t get everything done in 48 hours, I put together a LOT of plumbing and I feel that I&#8217;m potentially only a few days away from a finished product.  I hope my experiences help you plan your next 48 coding session better than I did. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Oh, and now that I&#8217;m done with NKO2011, Part 2 of the Backbone.JS tutorial is on it&#8217;s way!</p>
<p>Till next time, Happy Coding!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F08%2F30%2Fnode-knockout-2011-post-mortem%2F&amp;title=Node%20Knockout%202011%20Post%20Mortem" id="wpa2a_8"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Gotchas while Deploying a Sinatra App to Heroku</title>
		<link>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/</link>
		<comments>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/#comments</comments>
		<pubDate>Wed, 11 May 2011 05:03:37 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Heroku]]></category>
		<category><![CDATA[Sinatra]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=597</guid>
		<description><![CDATA[I figured it&#8217;d nice to deploy the tutorial Backbone.js app to Heroku.  The tutorial app that we&#8217;re building, &#8220;Comment on the movies&#8221;, has a simple Sinatra backend &#38; Heroku welcomes Rails &#38; Rack-based apps.  Here are the 2 gotchas that I &#8230; <a href="http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I figured it&#8217;d nice to deploy the tutorial Backbone.js app to Heroku.  The tutorial app that we&#8217;re building, &#8220;Comment on the movies&#8221;, has a simple Sinatra backend &amp; <a href="http://devcenter.heroku.com/articles/rack" target="_blank">Heroku welcomes Rails &amp; Rack-based apps</a>.  Here are the 2 gotchas that I needed to deal with in order to deploy to Heroku:<span id="more-597"></span></p>
<h2>Gotcha 1 &#8211; The .gems file:</h2>
<p>The &#8216;.gems&#8217; file is <strong>SUPER</strong> important.  Without it, Heroku won&#8217;t be able to install the gems that your app needs to function properly ( like&#8230;say&#8230;Sinatra <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).  It&#8217;s mentioned as a single line in the linked page above, but it&#8217;s worth mentioning because it&#8217;s easy to miss.</p>
<h2>Gotcha 2 &#8211; Heroku&#8217;s read-only Filesystem:</h2>
<p>There are certain files that you shouldn&#8217;t put into source control, like an API key from the New York Times (hint, hint).  Historically, I&#8217;ve added files like these to the server directly (along with other sensitive keys/data).  <a href="http://devcenter.heroku.com/articles/read-only-filesystem" target="_blank">While Heroku&#8217;s read-only file system doesn&#8217;t allow this</a>, it does have a nice solution:  Define sensitive values <a href="http://devcenter.heroku.com/articles/config-vars#cli_usage" target="_blank">via the Command Line Interface</a>:</p>
<blockquote><p>heroku config:add API_KEY=&#8217;ABC123&#8242;</p></blockquote>
<p>&#8230; and reference them in code like this:</p>
<blockquote><p>my_key = ENV['API_KEY']</p></blockquote>
<p>Those are the two <strong>VERY</strong> simple gotchas I ran into which shouldn&#8217;t distract from how awesome Heroku is.  Create your free account and play with it.</p>
<p>In other news, Part 2 of the Backbone.js tutorial series is coming soon.  In fact, the site&#8217;s layout was changed to accomodate the code and text for the tutorial.  You can watch the unfinished product evolve on <a href="https://github.com/abelmartin/Comment-On-The-Movies" target="_blank">GitHub</a> &amp; <a href="http://commentonthemovies.heroku.com/" target="_blank">play with it on Heroku</a>.</p>
<p>Happy Coding!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F05%2F11%2Fquick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku%2F&amp;title=Quick%20Hits%3A%20Gotchas%20while%20Deploying%20a%20Sinatra%20App%20to%20Heroku" id="wpa2a_10"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy</title>
		<link>http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/</link>
		<comments>http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/#comments</comments>
		<pubDate>Sun, 17 Apr 2011 02:18:19 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[underscore.js]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=513</guid>
		<description><![CDATA[At my new job I'm getting pretty friendly with Backbone.js. This 2-part post will teach you some backbone basics &#038; show you how to create your own backbone.js app with multiple routes. <a href="http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>A couple of house keeping notes</h2>
<p>It&#8217;s been a while since our last post.  Gabe&#8217;s been hard at work in Australia, hacking on a number of things.  Rebecca &amp; Brad have large, awesome projects in the works.  Meanwhile  I&#8217;ve switched jobs a couple of times <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .  All the while, we&#8217;ve been coding like mad and learning a ton of interesting things.  While I can&#8217;t promise that we&#8217;ll &#8220;turn the posting faucet back on&#8221;, I can say that we&#8217;ll try to reduce the big draughts.  Now then, on to the show!</p>
<h2>Backbone.js Philosophy (as I see it)</h2>
<p>I&#8217;ve been getting pretty friendly with Backbone.js lately.  This 2-part post will teach you some backbone basics &amp; show you how to create your own backbone.js app with multiple routes.<span id="more-513"></span></p>
<p>Before we begin, take a look at some of these other tutorials to get a sense of what we&#8217;re about to do.  I learned a LOT from them:</p>
<ul>
<li><a href="http://documentcloud.github.com/backbone/" target="_blank">Document Cloud&#8217;s backbone.js framework documentation</a></li>
<li><a href="http://documentcloud.github.com/backbone/examples/todos/index.html" target="_blank">Jérôme Gravel-Nique&#8217;s &#8221;Todo list&#8221; example</a></li>
<li><a href="http://www.plexical.com/blog/2010/11/18/backbone-js-tutorial/" target="_blank">The Meta Cloud&#8217;s backbone tutorial</a></li>
<li><a href="http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/" target="_blank">Liquid Media&#8217;s backbone tutorial (3 parts)</a></li>
<li><a href="http://www.elfsternberg.com/2010/12/08/backbonejs-introducing-backbone-store/" target="_blank">Elf Sternberg&#8217;s backbone tutorial</a></li>
<li><a href="http://www.jamesyu.org/2011/01/27/cloudedit-a-backbone-js-tutorial-by-example/" target="_blank">James Yu&#8217;s tutorial</a></li>
<li><a href="http://fleetventures.com/2011/02/08/quiet-clarity" target="_blank">David Richard&#8217;s thoughts on backbone.js</a></li>
</ul>
<p>The most important thing to understand about a Backbone.js app is the separations of concerns.  Each of the parts below can do even more than what I&#8217;m describing, but here&#8217;s the minimum of what you need to know about them.</p>
<h3>Models and Collections (an array of models)</h3>
<ul>
<li>knows how to speak to the data source (both restful resources and api calls).</li>
<li>can <a href="http://documentcloud.github.com/backbone/#Model-parse" target="_blank">parse data</a> before handed responses off to a view.</li>
</ul>
<h3>Views</h3>
<ul>
<li>knows how to display your models and collections.  You define the markup rules in the <a href="http://documentcloud.github.com/backbone/#View-render" target="_blank">render method</a></li>
<li>handles events (clicks, changes to markup, changes to models) and changes the markup appropriately.</li>
<li>can initialize your js plugins that should be attached to markup.</li>
</ul>
<p>Gabe had this to say about views:</p>
<p style="padding-left: 30px;">&#8220;I see two ways to use backbone views:</p>
<p style="padding-left: 30px;">1. A view can be bound directly to a model or collection.  Whenever that model/collection changes, the view would re-call it’s render method and redraw itself. In essence, the view’s job is to represent a model’s state in the DOM now.  Also keep in mind that the model doesn’t have to be something bound to your db.</p>
<p style="padding-left: 30px;">2. A view can be more of a <span style="text-decoration: underline;"><strong>stateful widget</strong></span> that remembers some of its own state.  In this widget style, the view would keep track of some state and maybe decide what parts of itself it should show/hide depending on its state.</p>
<p style="padding-left: 30px;">In conclusion, the two view philosophies are very similar:</p>
<p style="padding-left: 30px;">- one is more modular<br />
- one is more monolithic</p>
<p style="padding-left: 30px;"><strong>The view can be an island OR it can be obsessed with something.</strong>&#8220;</p>
<p>Thanks Gabe! <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Controllers/Router</h2>
<ul>
<li>handle all of your &#8216;#&#8217; routes.</li>
<li>the app is started by creating a new instance of this class.</li>
<li>your app only needs 1 controller/router</li>
</ul>
<h2>[5/7/2011 : Amendment]  A quick word about markup</h2>
<p>In a Backbone app you&#8217;ll have markup that lives on your page (index.html) &amp; markup that you&#8217;ll need to generate as new elements are added (This will become clearer when you see our tutorial app in action in the next post).  While Backbone gives you <a href="http://documentcloud.github.com/backbone/#View-make" target="_blank">view.make()</a> to create markup, you&#8217;ll want to use a templating library to help you out with more complicated stuff.  A fellow KAL member recently how I draw the line between what markup lives on the page and what markup lives in a template.</p>
<p><span style="text-decoration: underline;"><strong>My Rule</strong></span>: If the markup has an <span style="text-decoration: underline;"><strong>ID</strong></span>, then it should live on the <span style="text-decoration: underline;"><strong>page</strong></span>.  By maintaing this idea, you can create your page layout in it&#8217;s empty state.  The Views that you create will attach to ID&#8217;ed elements to dynamically fill/update them as events occur.  Also, with Backbone, you don&#8217;t need to have markup that contain the object&#8217;s ID (&#8220;foo_1&#8243;, &#8220;foo_2&#8243;, &#8220;foo_3&#8243;, etc).  The <span style="text-decoration: underline;"><strong>object is bound to the markup</strong></span> (if you do it correctly) which removes the need to parse it out of the ID in the markup (or other well known chicanery that we&#8217;ve all done at one point or another <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).  It&#8217;s often better to have your template markup use the &#8216;class&#8217; attribute declaration since they&#8217;re best used when you&#8217;re representing models in a collection.  This also fits with the W3C&#8217;s HTML spec which says that an ID/Name &#8220;<a href="http://www.w3.org/TR/html40/struct/global.html#h-7.5.2" target="_blank">must be unique in a document</a>&#8220;.</p>
<p>Consider my rule when constructing a table (the tutorial app will do this):  The table&#8217;s markup lives on the page with an ID (id=&#8221;MoviesTable&#8221;) without any rows.  We&#8217;ll generate/update the rows (class=&#8221;movie&#8221;) of the table on the fly via a template fueled by my View&#8217;s Collection.  The Collection is filled by the response from our movie API.</p>
<h2>That&#8217;s a lot to digest</h2>
<p>Stay tuned for Part 2 where we&#8217;ll build our app, &#8220;Comment on the Movies&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Quick Hits: UIActionSheet cancel button strange behaviour</title>
		<link>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/</link>
		<comments>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 02:41:39 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Quick Hits]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/</guid>
		<description><![CDATA[I just got bit by this and fixed it thanks to this StackOverflow post. http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour Long story short, if your launch an action sheet in a view that lives in a UITabBarController, the &#8220;hit&#8221; box for the cancel button gets &#8230; <a href="http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I just got bit by this and fixed it thanks to this StackOverflow post.</p>
<p><a href="http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour" target="_blank">http://stackoverflow.com/questions/1197746/uiactionsheet-cancel-button-strange-behaviour</a></p>
<p>Long story short, if your launch an action sheet in a view that lives in a UITabBarController, the &#8220;hit&#8221; box for the cancel button gets shifted in a VERY STUPID WAY!</p>
<p>The solution is to reference the view you&#8217;re displaying in by the UITabBarController like this:</p>
<pre><code>[sheet showInView:self.parentViewController.tabBarController.view];</code></pre>
<p>Freaking WOW!  Thanks a heap, Apple!</p>
<p>*grumble grumble*</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F07%2F03%2Fuiactionsheet-cancel-button-strange-behaviour%2F&amp;title=Quick%20Hits%3A%20UIActionSheet%20cancel%20button%20strange%20behaviour" id="wpa2a_12"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/07/03/uiactionsheet-cancel-button-strange-behaviour/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Becareful when returning inc’ed vars</title>
		<link>http://www.kickasslabs.com/2010/05/01/quick-hits-becareful-when-returning-inced-vars/</link>
		<comments>http://www.kickasslabs.com/2010/05/01/quick-hits-becareful-when-returning-inced-vars/#comments</comments>
		<pubDate>Sat, 01 May 2010 05:01:44 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[MonoTouch]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Quick Hits]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[noob]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=473</guid>
		<description><![CDATA[I noticed this in some MonoTouch code that I wrote recently, but I think it makes sense across other languages as well.  Let&#8217;s say you write a method that returns an incremented variable like this: private int MyAwesomeFunction(int pVar) { &#8230; <a href="http://www.kickasslabs.com/2010/05/01/quick-hits-becareful-when-returning-inced-vars/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I noticed this in some MonoTouch code that I wrote recently, but I think it makes sense across other languages as well.  Let&#8217;s say you write a method that returns an incremented variable like this:</p>
<p><span style="color: #0000ff;">private int</span> MyAwesomeFunction(int pVar)<br />
{<br />
<span style="color: #008000;">// coding magic</span><br />
<span style="color: #008000;"> <span style="color: #0000ff;"> return</span></span> pVar++;<br />
}</p>
<p>&#8230;where pVar = 10, the returned value will NOT be 11!  The returned value will still be 10.  If you want to return an incremented value for pVar, do the following:</p>
<p><code><span style="color: #0000ff;">private  int</span> MyAwesomeFunction(int pVar)<br />
{<br />
<span style="color: #008000;">//  coding magic</span></code><br />
<code> <span style="color: #0000ff;">return <span style="color: #000000;">++</span></span>pVar; <span style="color: #008000;">// or </span></code><span style="color: #008000;"><code>return   pVar+1</code></span>;<br />
<code>}</code></p>
<p>Just a case of postfix vs prefix.  In the previous example, the variable never gets incremented because the postfix operator would get evaluated after the line is processed, but that never happens because we&#8217;re returning the pVar.  By flipping to a prefix operator, we guarantee that we evaluate the opperator against the variable before we return it.</p>
<p>It&#8217;s also worth mentioning that being a little verbose here is also good.  Explicitly stating that you&#8217;re adding 1 to the variable (as displayed in the commented code) is the same number of characters and we eliminate the confusion over what&#8217;s getting returned.</p>
<p>Happy Coding!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F05%2F01%2Fquick-hits-becareful-when-returning-inced-vars%2F&amp;title=Quick%20Hits%3A%20Becareful%20when%20returning%20inc%26%238217%3Bed%20vars" id="wpa2a_14"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/05/01/quick-hits-becareful-when-returning-inced-vars/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The 5 stages of 3.3.1</title>
		<link>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/</link>
		<comments>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 04:32:36 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[MonoTouch]]></category>
		<category><![CDATA[331]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=449</guid>
		<description><![CDATA[Developers have been up in arms on the news broken by Daring Fireball and TechCrunch.  The reported change in the iPhone developer agreement definitely stops Flash developers from creating iPhone apps using the new tools available CS5, but the sword &#8230; <a href="http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Developers have been up in arms on the news broken by <a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler" target="_blank">Daring Fireball</a> and <a href="http://techcrunch.com/2010/04/08/adobe-flash-apple-sdk/" target="_blank">TechCrunch</a>.  The reported change in the iPhone developer agreement definitely <a href="http://theflashblog.com/?p=1888" target="_blank">stops Flash developers from creating iPhone apps</a> using the new tools available CS5, but the sword Apple used also cuts into the heart of the <a href="http://monotouch.net/" target="_blank">MonoTouch</a>, <a href="http://www.appcelerator.com/" target="_blank">Appcelerator</a>, <a href="http://unity3d.com/" target="_blank">Unity 3D</a>, <a href="http://anscamobile.com/corona/" target="_blank">Corona</a>, &amp; <a href="http://phonegap.com/" target="_blank">PhoneGap</a> communities.  Being a member of the MonoTouch community, I&#8217;m directly affected by this reported change.  Easily said, I&#8217;ve gone through the <a href="http://en.wikipedia.org/wiki/K%C3%BCbler-Ross_model" target="_blank">5 stages of grief</a> over the news:</p>
<p><span id="more-449"></span></p>
<h3>1] Denial</h3>
<p>It doesn&#8217;t really say that, does it?  I mean, they  must not realize what this will do to other projects not related to Adobe.  I&#8217;m sure they won&#8217;t enforce it.</p>
<h3>2] Anger</h3>
<p>Are you F*%#ING SERIOUS RIGHT NOW!?  Don&#8217;t they realize that some EA games use Lua!?  Are they going take those apps out of the store?  Don&#8217;t give me that &#8220;quality of apps&#8221; crap!  There are TONS of horrible apps written in native Objective-C!  &#8220;<a href="http://www.taoeffect.com/blog/2010/04/steve-jobs-response-on-section-3-3-1/" target="_blank">Crappy devs will make crappy apps regardless of how many layers there are &amp; it doesn’t make sense to limit source-to-source conversion</a>.&#8221;  This is creativity stifling!  Apple&#8217;s going to lose so many apps they&#8217;ll repeal this decision with the QUICKNESS!  I&#8217;m just going to bang out the best apps ever and we&#8217;ll see if Apple tries to take them out of the store.  I DOUBT THEY WILL!  What happened to the approval process!?  Shouldn&#8217;t that be enough!?  Don&#8217;t they understand how error prone manual memory management is!?  FURY!!!</p>
<h3>3] Bargaining</h3>
<p>Maybe we can team up with other developers and convince Apple to change this.  We can show them of the talent that&#8217;ll jump ship.  I mean, we&#8217;re not like those &#8220;sexy app&#8221; guys, right?</p>
<h3>4] Depression</h3>
<p>It&#8217;s over man!  It&#8217;s GAME OVER! Damn it!  I wasted all this time! What will become of my projects!?  I&#8217;m tossing out my iPhone &amp; I&#8217;m definitely not buying an iPad now.  It&#8217;ll just be too painful of a reminder that my app is available on it**.  Nothing to see here except a teary-eyed developer <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h3>5] Acceptance</h3>
<p>This sucks likes crazy, but I&#8217;ve still got time.  I&#8217;ll make updates to <a href="http://www.touchplaybook.com" target="_blank">Touch Playbook</a> for as long as I can.  MonoTouch is talking about giving developers the ability to create Droid apps and that will kick ass!  Windows Phone 7 is right around the corner and since my app is already written in C#, the port should be very easy.  The HP Slate runs Windows 7 and obviously Silverlight so there&#8217;s another port right there.  I&#8217;ll get started on that this weekend!  If it wasn&#8217;t for MonoTouch, I wouldn&#8217;t have gotten as far along as I did with Touch Playbook.  I don&#8217;t regret a moment.</p>
<h3>Conclusion</h3>
<p>I don&#8217;t know what the future of MonoTouch and iPhone development is.  Rather, I don&#8217;t want to admit what I fear the future is.  I&#8217;d love for a miracle to take place where the reported language is altered in 3.3.1 to allow MonoTouch and other quality iPhone development solutions.  However, if that doesn&#8217;t happen, MonoTouch still definitely rocks!  For the time being, it feels good to be in the final stage.  I don&#8217;t like being so angsty. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Update</h3>
<p>I do, however, remain hopeful.  I&#8217;ve signed the developer driven Tiny Petition <a href="http://tinypetition.com/NoBanFromTOSChange" target="_blank">against Apple&#8217;s reported TOS change and you can too</a>.  You might ask &#8220;Abel, isn&#8217;t this the barganing step?  Did you relapse?&#8221; and I would reply &#8220;Not exactly&#8221;.  In the bargaining step my thoughts came from desperation in the wake of anger.  Right now, signing the petition springs from hope and a desire to stand with my fellow MonoTouch devs and other devs effected by this.  This time the motivation is less about me and more about the community.</p>
<p>**I&#8217;ve already taken a stab at learning Objective-C and would rather use my time on other languages.  I don&#8217;t see myself taking up the effort again.  Life&#8217;s too short and I really like languages like C# &amp; Ruby.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F04%2F11%2Fthe-5-stages-of-3-3-1%2F&amp;title=The%205%20stages%20of%203.3.1" id="wpa2a_16"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/04/11/the-5-stages-of-3-3-1/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Localization strings in Monotouch</title>
		<link>http://www.kickasslabs.com/2010/02/21/quick-hits-localization-strings-in-monotouch/</link>
		<comments>http://www.kickasslabs.com/2010/02/21/quick-hits-localization-strings-in-monotouch/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 22:31:05 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[MonoTouch]]></category>
		<category><![CDATA[localization]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=439</guid>
		<description><![CDATA[It&#8217;s pretty straight forward. Check out this post: Internationalising my app &#8230;and make sure the folders you use follow this format &#8220;[Language Abbreviation].lproj&#8221; as commenter #4 points out If you miss one of the major languages, your app will default &#8230; <a href="http://www.kickasslabs.com/2010/02/21/quick-hits-localization-strings-in-monotouch/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s pretty straight forward.  Check out this post:</p>
<p><a href="http://forums.monotouch.net/yaf_postsm1381.aspx" target="_blank">Internationalising my app</a></p>
<p>&#8230;and make sure the folders you use follow this format &#8220;[Language Abbreviation].lpro<span style="text-decoration: underline;"><strong>j</strong></span>&#8221; as commenter #4 points out <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>If you miss one of the major languages, your app will default to English.  As of this post, the iPhone OS supports the following languages:</p>
<p>English (U.S), English (UK), French (France),  German, Traditional Chinese, Simplified Chinese, Dutch, Italian,  Spanish, Portuguese (Brazil), Portuguese (Portugal), Danish, Swedish,  Finnish, Norwegian, Korean, Japanese, Russian, Polish, Turkish,  Ukrainian, Arabic, Thai, Czech, Greek, Hebrew, Indonesian, Malay,  Romanian, Slovak, and Croatian</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2010%2F02%2F21%2Fquick-hits-localization-strings-in-monotouch%2F&amp;title=Quick%20Hits%3A%20Localization%20strings%20in%20Monotouch" id="wpa2a_18"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2010/02/21/quick-hits-localization-strings-in-monotouch/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

