<![CDATA[Mike Moran, software engineer, dad and baldie]]>https://www.houseofmoran.comRSS for NodeSun, 26 Dec 2021 14:49:43 GMT<![CDATA[The Diagonal Method vs. The Rule of Thirds]]>https://www.houseofmoran.com/DiagonalMethodVersusTheRuleOfThirdshttps://www.houseofmoran.com/DiagonalMethodVersusTheRuleOfThirdsSun, 26 Dec 2021 00:00:00 GMT<p>I am an occasional <a href="http://www.flickr.com/photos/schnickschnack/">photographer</a> and I became interested in how <a href="http://en.wikipedia.org/wiki/Composition_(visual_arts)">compositional techniques</a> could help me produce better pictures. I've been using the <a href="http://en.wikipedia.org/wiki/Rule_of_thirds">rule of thirds</a>, not least because <a href="http://www.flickr.com/cameras/canon/powershot_sd1200_is/">my camera</a> has an easy to use overlay for it. However, what method <em>should</em> I be using?</p> <p>I happened upon the <a href="http://www.diagonalmethod.info/">Diagonal Method</a> method website. The discussion references a few examples of paintings, adverts, and images which have key elements which overlap a diagonal. However, the validation of this technique is still very unscientific. It's easy to bias your selection towards choosing examples that support your method. Is there a less biased way to test this?</p> <p>Stepping back a bit, can we answer the question: <em>what are the areas of pictures that people find interesting</em>? If these generally overlapped with those recommended by a particular method then that would support its use.</p> <p>This is where flickr comes in. They some have idea of 'interestingness'; they don't define it, but we can use it as a proxy for how good the picture is. You can leave notes on areas of photos; let's use this as an indication of where the interesting areas of a picture are. You can follow <a href="http://www.flickr.com/photos/schnickschnack/sets/72157625607891279/">the history of my investigation on flickr itself</a>, but here's the end result:</p> <p><a style="float: left; margin-right: 5px;" data-flickr-embed="true" data-header="true" data-footer="true" href="https://www.flickr.com/photos/schnickschnack/5332425065/" title="first frame"><img src="https://farm6.staticflickr.com/5081/5332425065_30708c1741_m.jpg" width="240" height="240" alt="first frame"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p><a style="float: left; margin-right: 5px;" data-flickr-embed="true" data-header="true" data-footer="true" data-context="true" href="https://www.flickr.com/photos/schnickschnack/5332931792/in/album-72157625607891279/" title="heatmap.500x500.2004to2010.withnotes.r0"><img src="https://farm6.staticflickr.com/5290/5332931792_1d70d02cb0_m.jpg" width="240" height="240" alt="heatmap.500x500.2004to2010.withnotes.r0"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p><a style="float: left; margin-right: 5px;" data-flickr-embed="true" data-header="true" data-footer="true" href="https://www.flickr.com/photos/schnickschnack/5333041106/" title="final frame"><img src="https://farm6.staticflickr.com/5007/5333041106_a08cd80c73_m.jpg" width="240" height="240" alt="final frame"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <br style="clear: left" /> <p>What I did:</p> <ul> <li>I found the most interesting image that had been uploaded on each day between 2004 and 2010 (inclusive); to be exact I restricted to images that allowed re-use, just in case I wanted to do something else with them later.</li> <li>I then restricted this set to only those which have some notes. Here I ignore any note that was square, on the basis that if you've changed the size away from the default aspect ratio, then you've put more thought into the note.</li> <li>Each note in an image then contributes according to its specificity; the larger the note the smaller the contribution. I assumed that more specific notes were better indicators of points of interest.</li> <li>The note areas are normalised to a 500x500 pixel square.</li> <li>Each pixel in a note area then contributes something towards a pixel in the heatmap. If there are multiple notes in an image that overlap then I average the contribution from each note at each overlapping pixel. It is these combined contributions that then get added to the heatmap. In the image on the left, you can see an example heatmap after 10 images have been added.</li> <li>The heatmap is then simply the sum of all contributions.</li> <li>I create an image out of a heatmap using a simple linear scale which is visualised on a (Blue -> Green -> Red) scale.</li> </ul> <p>The final result is on the right. The movie is the result of iterating over the 707 images, and shows the heatmap accumulating over time, sampled and shown every 10 images.</p> <p>My conclusion is that there is a simple bias towards the centre of the image. This data doesn't give any support for either the diagonal method, or the rule of thirds. For both of these, I would have expected more activity away from the centre.</p> <p>There are some caveats here. The grid for the rule of thirds is unaffected by my normalisation to a square heatmap. However, the diagonal method grid changes depending on the aspect ratio. This means that any bias towards the cross-over points in the rule of thirds grid would show up clearly, whereas a similar bias from Diagonal Method focal points would be smeared out. However, I see no bias away from the centre at all, which I think removes the need to investigate and undo this deficiency. Aside: I can fix this, but it involves a reasonable amount of work to translate the collecting of heatmap hits out of image space and into something more like a parameter space. There are some nasty details to be careful about, like not overcounting grid hits because of the differences in areas of the two grids.</p> <p>What next? Flickr notes are used for many things, and I've just assumed they always indicate interesting areas. This may not be true often enough to bias the results. If so, I could look more at other information about notes which indicates what purpose they are being used for.</p> <p>I could also look for other sources of data.</p> <p>However, for now, I am sticking with the <a href="http://en.wikipedia.org/wiki/Rule_of_thirds">Rule of Thirds</a>.</p><![CDATA[L Systems]]>https://www.houseofmoran.com/LSystemshttps://www.houseofmoran.com/LSystemsSun, 26 Dec 2021 00:00:00 GMT<img style="float: left" src="https://lsystems.houseofmoran.com/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-8.200x200.png" /> <img style="float: left" src="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.png" /> <img style="float: left" src="https://lsystems.houseofmoran.com/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-4.200x200.png" /> <br style="clear: both"> <p>I first encountered <a href="http://en.wikipedia.org/wiki/L-system">LSystems</a> during university; this was in the mid-90s when fractals were becoming mainstream. However, it was only in 2009/2010, when I needed a toy problem to learn Scala and <a href="http://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services">JAX-RS</a> with, that I started writing renderers.</p> <p>The current version lives at <a href="https://lsystems.houseofmoran.com/">lsystems.houseofmoran.com</a> and I encourage you to play with it! The URLs are designed to be easy to hack. For example, the path <a href="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.png">/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.png</a> breaks down into</p> <pre><code>/&#x3C;rules>/&#x3C;stepsize>-&#x3C;angle>-&#x3C;iterations>.&#x3C;width>x&#x3C;height>.&#x3C;format> </code></pre> <p>Alternatively, just slap "/edit" on the end, to get an <a href="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.png/edit">editable</a> form. Here a few examples of what you can get:</p> <img style="float: left" alt="original" title="original" src="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.png" /> <img style="float: left" alt="more iterations" title="more iterations" src="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-4.200x200.png" /> <img style="float: left" alt="change angle" title="change angle" src="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-35.0-3.200x200.png" /> <img style="float: left" alt="animate over 10 seconds" title="animate over 10 seconds" src="https://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.gif.animOver10s" /> <br style="clear: both"> <h1>History</h1> <p>See the following for a history its development: <a href="/post/2009-06-27">2009-06-27</a>, <a href="/post/2010-02-28">2010-02-28</a>, <a href="/post/2010-03-08">2010-03-08</a>, <a href="http://www.flickr.com/photos/schnickschnack/sets/72157620457773888/">LSystem Explorations on Flickr</a> and a sort-of screencast of a <a href="http://www.youtube.com/watch?v=uf_wV8w9WJ0">previous version, using Java2D, on YouTube</a>.</p><![CDATA[Project 365]]>https://www.houseofmoran.com/Project365https://www.houseofmoran.com/Project365Sun, 26 Dec 2021 00:00:00 GMT<p><div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 50%; position: relative; height: 0; overflow: hidden;" > <div class="embedVideo-container"> <iframe src="https://www.youtube.com/embed/xVuUnvf7gq8?rel=0" class="embedVideo-iframe" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> <style> .embedVideo-iframe { border: 0 } </style> </div> </div></p> <p>Back in June 18, 2010, I started taking a photo a day, as part of the <a href="http://www.flickr.com/groups/project365/">Project365</a> flickr group. I <em>did</em> manage to almost always take one photo per day, but it wasn't until 2013 that I actually fiddled with and <a href="http://www.flickr.com/photos/schnickschnack/sets/72157624361695156/">uploaded them all</a>.</p> <p>I wondered if I was alone, in being so lax.</p> <p>I grabbed data for all submissions to the group from around 1800 members of the group over around the past two years. The plots below show the results of some initial investigations.<br /></p> <p><a href="http://www.flickr.com/photos/schnickschnack/5902349724/" title="Maximum Day vs Number of Days by MikeMoran, on Flickr"><img src="http://farm7.static.flickr.com/6004/5902349724_6f7014d4af_z.jpg" width="640" height="640" alt="Maximum Day vs Number of Days"></a></p> <p>The top graph shows the result of grabbing the maximum day reached by each person, and plotting how many people reached that date. There is a strange peak around 140 (the dotted line) followed by a thinning of submissions, and then a last gasp run to 365 (the peak on the right).</p> <p>The bottom graph shows that most people actually submitted very few pictures; the dotted line on the right marks 365 uploads. Some people submitted more than 365 pictures; this is either a bug in my scripts or some over-enthusiasm on their part.</p><![CDATA[Weekend Hack: Degrading QR Codes]]>https://www.houseofmoran.com/post/2020-11-15https://www.houseofmoran.com/post/2020-11-15Sun, 15 Nov 2020 00:00:00 GMT<p>My friends (Siwei and Hugo) and I were recently discussing some of the possible limitations of QR Codes. This re-animated an idea I'd had many years ago which relied on deliberately degrading QR Codes. One of the aspects was varying the bg/fg colors.</p> <p>So, I thought I'd challenge myself to get something working in a weekend which allowed me to test this out. However, I started this on a Friday evening and wanted something ready by Sunday, with plenty other stuff to do amongst that.</p> <p>So, I ended up with a fairly simple front-end implementation (<a href="https://github.com/mikemoraned/baton/tree/3ecce822513568e22094e77b51245e7693ce0e56">Github</a>):</p> <ul> <li>uses create-react-app</li> <li>uses a color scale from <code>d3-scale-chromatic</code> twice to get bg/fg color pairs</li> <li>randomly chooses a pair and renders it using an embedded Rust QR Code library</li> <li>allows people to say "Not Scannable"/"Scannable" and send this as a custom event to <a href="https://plausible.io/">Plausible.io</a> where it is recorded as Goals</li> <li>the Goal summaries can then be manually downloaded from <a href="https://plausible.io/">Plausible.io</a> as JSON, and sorted and rendered again in the app as QR Codes.</li> </ul> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.youtube.com/embed/mK-mY-ZgWP8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <h2>Learnings</h2> <p><del>Some QR Codes that are really easy to distinguish by eye are unreadable by pretty much all of the QR Code Apps I tried (on iOS). This likely means I'm going to have to be a lot more subtle in my degradations.</del> Update: turns out if you use the same qr code repeatedly, which I was, then the iOS Camera App will not re-identify it. So, I updated the site to show a unique code each time, and now have more successes.</p> <p>I really need to be more understanding of context when asking people for help. I'd asked people on a local Edinburgh Slack to help me collect data, but got frustrated when they pointed out a button wasn't obviously working; I'd deliberately went for the simplest possible thing (for me) of making the button do something behind the scenes, even if it didn't indicate it in the UI. Of course, that was the first thing people noticed!</p> <p>My reaction was quite negative on this. I was strongly forcing myself to not be a perfectionist as that would risk not completing something in a weekend. However, nobody else knew that, because I hadn't told them. As it turns out, making the button do <em>something</em> to indicate it worked wasn't too hard, so I did get something better out of this.</p> <p>I'd been doing a lot of Rust/WASM stuff for my Garibaldi project about 6 months ago, and I found the Rust/WASM parts a lot more buggy than expected. This time I encountered problems in <a href="https://github.com/mikemoraned/baton/blob/e66cb914291c714b9fae8f4c178d5ba45a162f9c/baton-lib/BUILDING.md#L13">publishing</a> and in <a href="https://github.com/mikemoraned/baton/blob/3ecce822513568e22094e77b51245e7693ce0e56/baton-lib/Cargo.toml#L42">building</a>. It didn't take me long to find workarounds, but this indicates that Rust/WASM is still not plain sailing.</p> <p>Btw, a Rust version of the QR Encoder is not strictly necessary. However, I am trying to follow the pattern of doing the UI parts in React and anything that could benefit from stronger-typing or performance in Rust. This also allows me to get more practice in Rust on real problems.</p> <h2>Next Steps</h2> <p>I will most likely return to this Baton project again, but probably not for a while. This was just a weekend hack as a bit of a "palette cleanser" before I return to my <a href="/post/2020-11-01">Playout</a> work.</p> <p>Finally, if you have a few minutes, please go to <a href="https://baton.houseofmoran.io/">https://baton.houseofmoran.io/</a> and give it a try yourself. All Data welcome, and I'll even accept criticism of the UI :-)</p><![CDATA[Playout 1.0, a Game for COVID times]]>https://www.houseofmoran.com/post/2020-11-01https://www.houseofmoran.com/post/2020-11-01Sun, 01 Nov 2020 00:00:00 GMT<p><a data-flickr-embed="true" style="float: left; margin-right: 10px;" href="https://playoutgame.app/" title="Playout 1.0.0"><img src="https://live.staticflickr.com/65535/50555827486_2e8b447f91_z.jpg" width="351" height="571" alt="Playout 1.0.0"></a></p> <p><b>TLDR: I've made a game: <a href="https://playoutgame.app/">Playout</a>. Please <a href="https://twitter.com/playoutgame">DM</a> any feedback or feature requests!</b></p> <p>The germ of this idea came from teams moving around at Skyscanner. <a href="https://www.linkedin.com/in/ewamleczko/">Eva</a> is an office manager there and often had to manually work out where to place teams when there was an office rearrangement. She had to take into account many preferences and constraints. <a href="https://www.linkedin.com/in/iva-babukova-06097596/">Iva</a> (a colleague) and I both thought this was something where a computer could be a helper, perhaps representing the task as a Constraint Satisfaction (CS) problem.</p> <p>There wasn't much spare time to take it further. However, this Summer I went down to four days a week at Skyscanner as part of a temporary COVID money saving plan. So, I thought I'd focus some of my new spare time on seeing if this was do-able.</p> <p>Iva had given me some pointers on how to represent this as a CS problem, but I was still far from familiar with the practicalities of CS. So, I split it: learn about the domain (make a game) and learn about CS (take a <a href="https://www.coursera.org/learn/basic-modeling/home/welcome">course</a> on it).</p> <p><a href="https://playoutgame.app/">Playout</a> is my "toy" version of the problem which I made into a standalone game, because that sounded fun :-)</p> <br style="clear: both"/> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.youtube.com/embed/GPlXArDAx_8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>The core look-and-feel hasn't changed all that much over time, but the internals and explanations repeatedly changed based on feedback from friends and family. There are still tonnes of things to add, but you have to draw a line somewhere, and <a href="https://github.com/mikemoraned/playout/releases">33 releases later</a>, 1.0 is it!</p> <p>Next steps are to integrate what I've learned about CS back into the game, and also gather ideas/bug-fixes/suggestions from people playing the game. So, please have a go at it and let me <a href="https://twitter.com/playoutgame">know</a>!.</p> <script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script><![CDATA[Map Maker: Ups and Downs]]>https://www.houseofmoran.com/post/2020-04-25https://www.houseofmoran.com/post/2020-04-25Sat, 25 Apr 2020 00:00:00 GMT<p>Ups and downs this week, ups:</p> <p><a data-flickr-embed="true" href="https://www.flickr.com/photos/schnickschnack/49817281507/in/datetaken-public/" title="Version 2"><img src="https://live.staticflickr.com/65535/49817281507_3e527a2dc2_z.jpg" width="640" height="145" alt="Version 2"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p>The talented <a href="https://twitter.com/king_carmen">King Carmen</a> of <a href="www.carmenland.com/">Carmenland</a> created a small Garibaldi Biscuit logo for me. This is even though she despises anything associated with squidgyness. Thank you for suffering through this Carmen.</p> <p>Downs:</p> <p><a style="float: left; margin-right: 2em;" data-flickr-embed="true" href="https://www.flickr.com/photos/schnickschnack/49816440488/in/datetaken-public/" title="Untitled"><img src="https://live.staticflickr.com/65535/49816440488_9714a47e70_z.jpg" width="480" height="640" alt="Untitled"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p>This here shows the same browser, same city, same area, but on different screen resolutions. Some areas are connected in one screen that are not in others. This is a known possible issue I have been putting off tackling for some time because I had some more important things to prove first. Thanks to Matt and Laurence for helping me find me this, and show now is becoming the time to fix it.</p> <br style="float: clear" /> <p>The problem occurs because I draw the streets on the HTML Canvas and then pass over an image of it (see below) to the Rust part to find connected regions and then return this as polygons.</p> <p><a data-flickr-embed="true" href="https://www.flickr.com/photos/schnickschnack/49816537798/in/datetaken-public/" title="Untitled"><img src="https://live.staticflickr.com/65535/49816537798_a0c1645fff.jpg" width="500" height="272" alt="Untitled"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p>For simplicity, I use the same canvas to do this as I do for display, which means it has the same resolution as the display area. However, I think this means that on smaller resolutions the image ends up with some blurring which causes some areas to become connected.</p> <p>The solution will likely be to have two canvases, one for doing crisp rendering at highest resolution (by making canvas bigger) and another for actual display. I've already thought about doing this for different reasons so have some idea of how it will work but will require a bit of refactoring.</p> <p>I'd really like to fix this bug, but I think I'll do the refactoring first.</p><![CDATA[Map Maker: Spiking on Plus Codes and Mapbox Turf]]>https://www.houseofmoran.com/post/2020-04-19https://www.houseofmoran.com/post/2020-04-19Sun, 19 Apr 2020 00:00:00 GMT<div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden;" > <iframe style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; " src="https://www.youtube.com/embed/Od7GYdVm6ow" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> </div> </div> <p>In the current version of <a href="https://garibaldi.houseofmoran.io/">Garibaldi</a> I have a thing called the "Reticule" which is the central area of the Map that is split apart into streets. This is defined as being some percentage reduction of the browser viewport size, so it is entirely relative to the current display. This was more than enough for me to get this far.</p> <div style="margin: auto"> <a data-flickr-embed="true" href="https://www.flickr.com/photos/schnickschnack/49817379777/in/datetaken-public/" title="Version 3"><img src="https://live.staticflickr.com/65535/49817379777_67d6001c2d_w.jpg" width="325" height="400" alt="Version 3"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script> </div> <p>However, to be able to mix and match segments of different Maps I'll need to register the segments as real physical objects with size and position. My planned way to do this is to make the Reticule correspond to a real physical area by having a defined center + a width and height in kilometres, and then use this as a reference area for the embedded segments. I also want something that can be used as a good canonical address for any interesting area.</p> <p>For this spike I've been looking at Open Location Codes (aka <a href="https://plus.codes/">Plus Codes</a>) for the center and <a href="https://docs.mapbox.com/help/glossary/turf/">Turf</a> for defining the width / height.</p> <p>I've got some good <a href="https://youtu.be/oX-rvIQzTgw">prior experience in using geohashes</a>, but wanted something with a bit more awareness; Plus Codes having Google Maps support is a biggy for this. The description of OLC in the official repo is also quite good at <a href="https://github.com/google/open-location-code/wiki/Evaluation-of-Location-Encoding-Systems">explaining why they invented it</a>. If I do find any problems, I can always switch over to geohashes as they work very similarly.</p> <p><a href="https://docs.mapbox.com/help/glossary/turf/">Turf</a> is another library from Mapbox and is as an easy way to use physical areas and distances. In this Spike I am using it in a slightly hacky way to get what I want:</p> <ul> <li> <p>get lat, lon point center from Plus Code</p> </li> <li> <p>for each of width and height, <a href="http://turfjs.org/docs/#buffer">buffer</a> this point by the corresponding km radius (so that it turns into a circle)</p> </li> <li> <p>get the <a href="http://turfjs.org/docs/#bbox">bounding box</a> for each of these circles</p> </li> <li> <p>construct a MapBox LngLatBounds by taking the latitudes of the corners from the buffered width circle and the longitudes from the buffered height circle</p> </li> </ul> <p>This is super inefficient but gives me what I need.</p> <p>I then combine these together into a summary text on top of the displayed Reticule, which updates as a I scroll around. <a href="https://github.com/mikemoraned/garibaldi-biscuits/pull/14">Job done!</a> (this Spike may still be <a href="https://deploy-preview-13--festive-spence-bf51b0.netlify.app/">previewable</a>, but if not see video at start).</p> <p>Likely next step: before I can incorporate this, I'll need to do a bit of refactoring in the main App.</p><![CDATA[The Journey to Map Maker (aka The Coronavirus Diaries)]]>https://www.houseofmoran.com/post/2020-04-11https://www.houseofmoran.com/post/2020-04-11Sat, 11 Apr 2020 00:00:00 GMT<p>My current WIP in the Biscuits Project (<a href="https://garibaldi.houseofmoran.io/">Garibaldi</a>) is now at parity with my <a href="https://github.com/mikemoraned/biscuits#april-2018--speculaas">previous iteration</a> on the things I care about: being able to segment a map based on the structure of its streets. Except that it is all now being done client-side.</p> <p>It's not obvious it's doing anything special as I deliberately just put them back in their original locations. Being able to take something to bits and put it back together again is a key ability! However, it's not very interesting to look at.</p> <p>Hence Map Mixer. The core idea is to see what a Map of a city looks like if I swap over similar-size blocks from another city. I don't know what this will look like, so time to explore.</p> <p>My general strategy for personal projects is similar to the <a href="https://medium.com/digital-experience-design/how-to-apply-a-design-thinking-hcd-ux-or-any-creative-process-from-scratch-b8786efbf812">Double Diamond</a> approach. The above is me doing "building the right thing" i.e. what am I gonna build next? What comes next is actually building it.</p> <p>Doing this seems to break down into these steps:</p> <ul> <li>take two pre-segmented Maps</li> <li>analyse segments by similarity in each Map</li> <li>take destination Map and lay it out</li> <li>take source Map and find segments in destination Map that most closely match destination</li> <li>replace segments in destination with source segments (do repeated fill if more segments in destination than source)</li> <li>allow it to re-layout</li> <li>solidify and re-draw i.e. turn it back into a Map with streets</li> </ul> <p>Next, I will try to see what I already have that can fit these needs, perhaps doing some re-factoring / clean-up to get there. I will also do various spikes on different technologies or approaches that fill the gaps. Then I will incrementally start re-integrating these learnings back into the main app, trying out examples as I go. Finally, I will apply iteratative optimisations on the code as I use it, where it seems sluggish.</p> <p>First spike: Layout. I am assuming that laying out the Map will not be as simple as drawing a Map because bits from each Map won't fit together cleanly. So, some "jiggling around" will be required. To make it look like a real Map, some constraints need to be followed, such as not having overlapping segments. An idea here is to use some sort of physics engine that can apply these constraints.</p> <p>I've been doing a lot of Rust recently; the small segmenting core of <a href="https://garibaldi.houseofmoran.io/">https://garibaldi.houseofmoran.io/</a> is built in it. So, my first choice for layout it out was seeing what was available in Rust. Specifically, nphysics2d for doing the layout.</p> <p>Unfortunately, I had some issues getting nphysics to compile under wasm, using wasm-binding. I don't think it's a dead-end, but I realised for the sake of experimentation, it may be simple to use an old-favourite of mine: d3-force layout. So, stay tuned on that.</p><![CDATA[Edinburgh Film Festival 2019 (Shortlist of Films, Updated for availability)]]>https://www.houseofmoran.com/post/2019-06-16https://www.houseofmoran.com/post/2019-06-16Sun, 16 Jun 2019 00:00:00 GMT<p><strong>Definitely want to see</strong></p> <ul> <li><del><a href="https://www.edfilmfest.org.uk/2019/memory-origins-alien/">Memory: The Origins of Alien</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/art-self-defense/">The Art of Self-defense</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/dead-dont-die/">The Dead Don't Die</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/never-look-away-werk-ohne-autor/">Never Look Away (Werk ohne Autor)</a></del></li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/extreme-jaob-geukhan-jikeop/">Extreme Job (Geukhan jikeop)</a></p> <ul> <li>date: Thu 27th</li> </ul> </li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/sakawa/">Sakawa</a></p> <ul> <li>date: Sat 29th</li> </ul> </li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/ever-after-endzeit/">Ever After (Endzeit)</a></p> <ul> <li>date: Fri 28th</li> </ul> </li> <li><del><a href="https://www.edfilmfest.org.uk/2019/abracadabra/">Abracadabra</a></del></li> </ul> <p><strong>Maybe</strong></p> <ul> <li><del><a href="https://www.edfilmfest.org.uk/2019/aniara/">Aniara</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/2040/">2040</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/foreign-land-en-tierra-extrana/">In a Foreign Land (En tierra extraña)</a></del></li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/modest-heroes-ponoc-short-films-theatre/">Modest Heroes — Ponoc Short Films Theatre</a></p> <ul> <li>date: Thu 27th</li> </ul> </li> <li><del>any of the <a href="https://www.edfilmfest.org.uk/whats-on?keywords=mclaren">Mclaren Animation</a> events</del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/children-universe/">Children of the Universe</a></del></li> </ul> <p><strong>Not sure, but could</strong></p> <ul> <li><del><a href="https://www.edfilmfest.org.uk/2019/strange-true/">Strange But True</a></del></li> <li><del><a href="https://www.edfilmfest.org.uk/2019/vast-night/">The Vast of Night</a></del></li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/hidden-city-la-ciudad-oculta/">The Hidden City (La ciudad oculta)</a></p> <ul> <li>time: Fri 28th</li> </ul> </li> <li><del><a href="https://www.edfilmfest.org.uk/2019/i-see-you/">I See You</a></del></li> <li> <p><a href="https://www.edfilmfest.org.uk/2019/schemers/">Schemers</a></p> <ul> <li>date: Sun 30th</li> </ul> </li> </ul><![CDATA[A look back at FOSDEM 2019]]>https://www.houseofmoran.com/post/2019-02-09https://www.houseofmoran.com/post/2019-02-09Sat, 09 Feb 2019 00:00:00 GMT<p><a style="float: left; margin-right: 2em" data-flickr-embed="true" data-context="true" href="https://www.flickr.com/photos/schnickschnack/46213729235/" title="Atomium, Brussels"><img src="https://farm8.staticflickr.com/7927/46213729235_1fdcab1de0_n.jpg" width="320" height="320" alt="Atomium, Brussels"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p>This year I am continuing my plan to do a mix of conferences. Last year it was GraphQL Europe and PyData Berlin. I'm starting 2019 with <a href="https://fosdem.org/2019/schedule/">FOSDEM 2019</a>. It's now just over a week since I was there, so it's time to reflect before I forget it all.</p> <p>First impression: <a href="https://fosdem.org/2019/schedule/events/">"My god that's a lot of talks"</a>. I sought out who'd been before and that impression was confirmed along with a subtle warning that it is a little chaotic.</p> <p>The whole conference is unticketed so in principle there is no limit to how many can arrive. This means it becomes a little bit of a race to get into talks. My first choice of the day was <a href="https://fosdem.org/2019/schedule/event/qosf_oss_meets_qc/">an introduction to Quantum Computing</a>. I soon realised that the people I had squeezed past weren't just coalesced around the hallway demonstrations, but were also in the queue for my talk. Not only that, it was people waiting to get into an already-full seminar room. Thankfully, next door was a somewhat less busy <a href="https://fosdem.org/2019/schedule/event/ada_introduction/">introduction to Ada</a> (outcome: I'm still not gonna use Ada, but I now have a first-hand summary from an expert).</p> <p>This ecleticism of subjects is something you struggle to find at other conferences. My strategy became to try to go for a mix of talks on topics I know and others I was far less knowledgeable about, and look for clusters of talks in the same room, back-to-back. I won't go over all the talks, but here's some that stand out for me.</p> <ul> <li> <p><a href="https://fosdem.org/2019/schedule/event/checkpoint_restore/">"Java Checkpoint/Restore" from Christine H Flood</a>.</p> <p>The gist of this is to bring to Java fast startup times based on taking a snapshot of a fully warmed JVM using <a href="foop.com">CRIU</a>, applying bespoke Java minimisations to this snapshot, and re-using this as the starting image of separate JVM's. The presentation is effectively: "I've got a prototype that shows this approach works for Java using CRIU, what do you think?".</p> <p>Given the audience are also experts into these technologies the Q/A part then becomes a lot more useful e.g. one of the audience members implemented this same thing for Smalltalk so could give direct advice and support for the approach. Combine this with the general egoless stance of the audience and the presenter and you get a short but illuminating talk out of it.</p> </li> <li> <p><a href="https://fosdem.org/2019/schedule/event/dns_over_http/">"DNS over HTTPS - the good, the bad and the ugly"</a>.</p> <p>This was weird in that I got more out of the chat about it on the way there with <a href="https://www.linkedin.com/in/barney-sowood-38845b9/">Barney</a> than the talk itself. This talk really suffered from another pattern I noticed at FOSDEM: late arrivals. In minute 25 of this 50 minute talk there were still people arriving through the very clunky fire doors, leading to "scrape, scutter, clunk" noises every 30 seconds. At the end the Q/A was ruined by the noise of people leaving as soon as the talk ended; I have to admit I became one of them as soon as it became obvious it was pointless to remain. This is a shame as this topic is controversial and very impactful to the future of the internet.</p> </li> <li> <p>Saturday: <a href="https://fosdem.org/2019/schedule/event/dotnet_open_source_panel/">Open Source .NET</a> / Sunday: <a href="https://fosdem.org/2019/schedule/event/open_source_microsoft/">Open Source C#, .NET, and Blazor - everywhere PLUS WebAssembly</a>.</p> <p>Hearing Hanselman speak on Sunday was a nice bookend to my .NET experience which started around the time I last saw him during his <a href="https://www.hanselman.com/scotland/">visit to Scotland in 2012</a>. I'd newly joined Skyscanner, which was largely a .NET / Python / SQL Server shop. The expectations of my colleagues were in stark constrast to what I was recently used to i.e. Microsoft leads the way with language change and useful libraries might need to be paid for, as opposed to a largely stagnant Java language with most meaningful features coming from open-source libraries or new JVM languages. Fast-forward to 2019: Microsoft have <a href="https://opensource.microsoft.com/">884 open-source projects</a> and they like Github so much that they bought the company.</p> <p>Hanselman's talk was entertaining, as always, but the real surprise was the Panel on Sunday. I'd went into it slightly blind and it was only when the chat started that I realised it was <a href="https://fosdem.org/2019/schedule/speaker/miguel_de_icaza/">Miguel De Icaza</a> doing most of the talking; it was technically a Panel, but probably should have been titled "a conversation with Miguel" ☺.</p> <p>He's obviously achieved somewhat more than me ☺ over his life but as Miguel and I are around the same age, I personally found it very relevant hearing his history and reflections and tying them back to what I was doing.</p> <p>It was particularly sad to hear how he ended up turning away from some of his projects due to "GamerGate" style death-threats. I recommend listening to all of this Panel talk, even if you're not in your 40's and have never used .NET.</p> </li> </ul> <h2> Full list of talks I went to, or attempted to</h2> <h3>Saturday</h3> <ol> <li><a href="https://fosdem.org/2019/schedule/event/keynotes_welcome/">https://fosdem.org/2019/schedule/event/keynotes_welcome/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/full_software_freedom/">https://fosdem.org/2019/schedule/event/full_software_freedom/</a></li> <li>Attempted: <a href="https://fosdem.org/2019/schedule/event/qosf_oss_meets_qc/">https://fosdem.org/2019/schedule/event/qosf_oss_meets_qc/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/ada_introduction/">https://fosdem.org/2019/schedule/event/ada_introduction/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/checkpoint_restore/">https://fosdem.org/2019/schedule/event/checkpoint_restore/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/java_docker/">https://fosdem.org/2019/schedule/event/java_docker/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/performance_graal/">https://fosdem.org/2019/schedule/event/performance_graal/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/dns_over_http/">https://fosdem.org/2019/schedule/event/dns_over_http/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/pargo/">https://fosdem.org/2019/schedule/event/pargo/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/kubernetesclusterfuck/">https://fosdem.org/2019/schedule/event/kubernetesclusterfuck/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/dotnet_open_source_panel/">https://fosdem.org/2019/schedule/event/dotnet_open_source_panel/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/dotnet_typescript_lightning_talks/">https://fosdem.org/2019/schedule/event/dotnet_typescript_lightning_talks/</a></li> </ol> <h3>Sunday</h3> <ol> <li><a href="https://fosdem.org/2019/schedule/event/ml_on_code_code_review_mailing_list/">https://fosdem.org/2019/schedule/event/ml_on_code_code_review_mailing_list/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/ceph_storage_with_rook/">https://fosdem.org/2019/schedule/event/ceph_storage_with_rook/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/validating_big_data_jobs/">https://fosdem.org/2019/schedule/event/validating_big_data_jobs/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/beam_cross_language/">https://fosdem.org/2019/schedule/event/beam_cross_language/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/open_source_microsoft/">https://fosdem.org/2019/schedule/event/open_source_microsoft/</a></li> <li> <p>Lighting talks:</p> <ul> <li><a href="https://fosdem.org/2019/schedule/event/real_time_merging_of_config_management_and_monitoring/">https://fosdem.org/2019/schedule/event/real_time_merging_of_config_management_and_monitoring/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/lets_use_centralized_log_collection_to_make_incident_response_teams_happy/">https://fosdem.org/2019/schedule/event/lets_use_centralized_log_collection_to_make_incident_response_teams_happy/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/writing_asynchronous_snmp_agents/">https://fosdem.org/2019/schedule/event/writing_asynchronous_snmp_agents/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/saymon_object_oriented_monitoring_and_management_for_both_ict_and_iot_/">https://fosdem.org/2019/schedule/event/saymon_object_oriented_monitoring_and_management_for_both_ict_and_iot_/</a></li> <li><a href="https://fosdem.org/2019/schedule/event/slapdcheck/">https://fosdem.org/2019/schedule/event/slapdcheck/</a></li> </ul> </li> </ol><![CDATA[About time for a (site) change]]>https://www.houseofmoran.com/post/2019-01-04https://www.houseofmoran.com/post/2019-01-04Fri, 04 Jan 2019 00:00:00 GMT<img style="float: left; margin-right: 1em" src="https://i.imgflip.com/2qcv56.jpg" /> <p>Now that <a href="https://boingboing.net/2018/12/03/the-death-of-tumblr.html">Tumblr is showing signs of being on it's way to death</a> I am wary of leaving my content on there. This angst is not reduced by the behaviour of other companies like Flickr, <a href="https://gizmodo.com/flickr-is-going-to-delete-a-bunch-of-photos-back-up-you-1830177165">deciding maybe it wouldn't be keeping all those photos for you after all</a>.</p> <p>The world has also moved on since I last seriously touched this setup years ago, with HTTPS now expected and lots more choices. So, I decided to bring it all back under my control again as a static site.</p> <p>I'd been eyeing <a href="https://www.gatsbyjs.org/">Gatsby</a> for the past year as something I wanted to learn. I finally got round to going through the tutorials over xmas and liked the simplicity.</p> <p>The first pass port of Tumblr content went well. I then ported over the remainder of the content that was reachable via the old front-page. More details available under <a href="/AboutThisSite">"about this site"</a>.</p> <p>The final thing to do was add https support for things I link to as embedded images, like <a href="/LSystems">LSystems</a> and <a href="/post/163952918683/when-backend-is-frontend-and-back-again">Sham Tartans</a>.</p> <p>I wanted to improve my understanding of how Kubernetes fits together, whilst not spending too much, so took advantage of the new <a href="https://www.digitalocean.com/products/kubernetes/">Kubernetes support</a> on <a href="https://m.do.co/c/405fabda074f">Digital Ocean</a>. I've opted for a <a href="https://github.com/mikemoraned/k8s-clusters/blob/master/do/README.md">single cluster</a> which provides ingress and https to services embedded in it e.g. <a href="https://github.com/mikemoraned/lSystemsEd/blob/master/README.md">LSystems</a>.</p> <p>Rather than beefing up the cluster with lots of monitoring and observability from the start I am instead working from the outside-in by starting with a cheap external monitor, <a href="https://updown.io/">updown.io</a>, and will add more detailed monitoring as and when I need it. This is sufficient for hobby projects like this where I am trying to minimise costs whilst learning incrementally, as opposed to going for 100% availability. This is WIP, but so far, after a week or so, I am finding it good.</p><![CDATA[When backend is frontend, and back again]]>https://www.houseofmoran.com/post/163952918683/when-backend-is-frontend-and-back-againhttps://www.houseofmoran.com/post/163952918683/when-backend-is-frontend-and-back-againTue, 08 Aug 2017 00:00:00 GMT<p>If you're building a mostly-frontend dynamic site, but want to make it share-able on Facebook/Twitter with a nice preview image, then here's one new (slightly weird) way to do it.</p> <p><a href="https://shartan.houseofmoran.com/"><img src="https://shartan.houseofmoran.com/preview.png" alt="an image generated using this method" style="width: 50%; float: left; margin-right: 10px"></a> I was playing around with a <a href="https://shartan.houseofmoran.com/">Sham Tartan</a> generator because, well, why not? I started off rendering this as overlapping divs, but this is no good as an og:image or twitter:image, as Facebook/Twitter won't pick these up as images.</p> <p>I changed the React front-end to instead render these on canvas with the intent that I then re-use this JS code in the back-end. However, after <a href="https://medium.com/@dschnr/using-headless-chrome-as-an-automated-screenshot-tool-4b07dffba79a">reading about</a> what the recent headless mode of Chrome gives you, I realised I had another option.</p> <p>The core of the idea is to run an instance of Chrome alongside your backend. When a request comes in for a preview image you ask it to take a screenshot of the page you want to use as a preview which you then proxy back to the browser.</p> <p>For example, on <a href="https://shartan.houseofmoran.com/">https://shartan.houseofmoran.com/</a> I set the og:image in the meta tag to <a href="https://shartan.houseofmoran.com/preview.png">https://shartan.houseofmoran.com/preview.png</a>. A request for <a href="https://shartan.houseofmoran.com/preview.png">https://shartan.houseofmoran.com/preview.png</a> then causes a screenshot of <a href="https://shartan.houseofmoran.com/">https://shartan.houseofmoran.com/</a> to be taken as a PNG which I then return.</p> <p>The page being used for the preview image here is the same as the homepage, but could be a different url.</p> <p>My implementation of this is on <a href="https://github.com/mikemoraned/shartan">github</a>, but there are bound to be better versions out there.</p> <p>You'll notice you <em>still</em> need a backend, so what's the benefit of this? The main benefit is that any technology that runs quickly in Chrome can be used to make a preview image. If I wanted to, I could go back to my div-based Tartan rendering method and it would all still work.</p> <p>There are sure to be limitations to this, not least the stability of chrome headless itself. But, in summary, if you want to write most of your code on the front-end and want a generic method to create a preview image, then consider this pattern.</p><![CDATA[Tautona: Visualising similarities between Slack channels]]>https://www.houseofmoran.com/post/149145855383/tautona-visualising-similarities-between-slackhttps://www.houseofmoran.com/post/149145855383/tautona-visualising-similarities-between-slackThu, 18 Aug 2016 00:00:00 GMT<p>I hadn't done any lo-fi text analysis for ages, and since we've been using Slack at <a href="http://skyscanner.net/">my job</a> for a little while now, it was time to get munging!</p> <p>My MVP was really simplistic, but actually surprisingly good. I didn't record the output of the <a href="https://github.com/mikemoraned/tautona/blob/54848c3e4f3dfb976ad2b22435609c2d33210459/crawl.py#L50">implementation</a> at the time, but in summary it used the <a href="https://en.wikipedia.org/wiki/Jaccard_index">Jaccard Index</a> between channel memberships as a measure of similarity.</p> <p>I then did a fairly standard thing of inverting this into a distance measure, and visualising this with a <a href="https://github.com/d3/d3-3.x-api-reference/blob/master/Force-Layout.md">D3 Force Layout</a>. So far, so good, without even touching any messages!</p> <p>Enter: <a href="https://radimrehurek.com/gensim/about.html">Gensim</a>. This is a really neat little Python library that I discovered via <a href="https://www.linkedin.com/in/danil-serdyuchenko-26605387">a colleague at Skyscanner</a>.</p> <p>It focusses on doing a small number of jobs, but well. I've been playing about with its word2vec implementation in another project, but here I used TF-IDF + Latent Semantic Indexing to produce channel similarities:</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 75%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.youtube.com/embed/URINAa2NOTQ" frameborder="0" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>The procedure is similar to my MVP, except I treat each channel as a document, consisting of a big bag of words from up to the last 1000 messages. TF-IDF is applied to boost up effect of unusual words and LSI extracts topics. I then compute all channel to channel similarities, convert to distances, and visualise as a force layout.</p> <p>You can see the video of the output above, but you can also play with <a href="https://mikemoraned.github.io/tautona/">a visualisation of Skyscanner</a>, lightly <a href="https://github.com/mikemoraned/tautona#sharing-channel-similarity-visualisation">obfuscated</a>.</p> <p>To run this, you literally only <a href="https://github.com/mikemoraned/tautona#prerequisites">need Python and a Slack <code>API_TOKEN</code></a>. I would <em>love</em> to see visualisations of other people's Slack channels. Please share them, or <a href="https://twitter.com/mike_moran">ping me on Twitter</a>, and I can host them on Github!</p><![CDATA[The (lack of) relationship between price and value]]>https://www.houseofmoran.com/post/129502119763/the-lack-of-relationship-between-price-and-valuehttps://www.houseofmoran.com/post/129502119763/the-lack-of-relationship-between-price-and-valueSun, 20 Sep 2015 00:00:00 GMT<figure class="tmblr-full" data-orig-height="1024" data-orig-width="768" data-orig-src="https://pbs.twimg.com/media/CPTUWixWcAEX94Q.jpg"><img src="https://66.media.tumblr.com/596cbe63510f7bf22ff11757d5df23cc/tumblr_inline_pk0op0PytX1r786jr_540.jpg" data-orig-height="1024" data-orig-width="768" data-orig-src="https://pbs.twimg.com/media/CPTUWixWcAEX94Q.jpg"></figure> <p>In Vienna I had <a href="https://twitter.com/mike_moran/status/645374132180402176">an espresso-fueled discussion with Dimo and Georgi</a> about how the price of goods relates to their value. We got through quite a few different ways in which they are indirectly connected, so I thought I’d write them all down, even if only for my future reference.</p> <ol> <li><strong>Choice paradoxes</strong>. For example, if you want people to tend to choose a product at a particular price, you can present it in order with two others: one which is far more expensive, and another which is far cheaper.</li> <li><strong>Price as independent signal of value</strong>. For example, vases, which are sometimes valued because of uniqueness, do not have that aspect as a directly visible property. If one is initially advertised at a “bargain” low price then people may not buy it because this is interpreted as a signal that the seller does not think it is rare. The seller can then raise the price to remove this effect. As long as it is still cheap enough that the buyer does not do an extensive check before purchase, then they may be able to sell a vase which is actually quite common.</li> <li><strong>Price as future resell value</strong>. Similarly to above, prices for extensive pieces of Art are hard to determine. Many collectors buy and sell on the basis of what a group of experts think a piece will sell for at a future auction. To some extent this price is then self-fulfilling, particularly since collectors are often independently rich and can wait to sell when they think the price they want can be reached.</li> <li><strong>Artificial scarcity</strong>. This is the classic "available only today" scam, where the price is reduced for a limited time. A vendor can easily do this across a large catalogue of products where any given product is given a synthetic limited availability.</li> <li><strong>Misleading discounting</strong>. Similar to above, except a product is sold at a high price for some minimum duration, before being "discounted" and advertised at the sellers desired price.</li> <li><strong>Multi-item bundles, or volume discounts, irrespective of need</strong>. This is things like "2 for the price of 1", where only 1 item is really needed. For example, you may only want a small coffee, but the per-volume cost is noticeably more than the medium size, so you are pushed into choosing it instead. You could argue this is also a form of item 1, since you often see small/medium/large as options.</li> <li><strong>Artificial correlation</strong>. For the airline industry alone, I suspect you could write a book on these. For example, typically a seller will have to pay a fee to the credit card issuer on each purchase. However this is a per-transaction cost and does not have any relation to, for example, the number of people travelling, but some airlines use that as a multiplier of the credit card charge.</li> <li><strong>Brand uplift</strong>. For two similar items in two separate catalogues, the company with the better brand is able to charge a higher price. To some extent this is reasonable, because there is value in the expectation of higher quality, reliability, better servicing and possible future resell value. However, these extras come at a cost to the seller, so there is an incentive to smear out the benefits of the brand whilst reducing costs. Brands are built on reputation, but if you can skimp on quality, whilst keeping it hard to notice it has been reduced, or get disproportionate gain in positive publicity from a loss-leading set of products, then you get the benefits of a good brand whilst reducing costs.</li> <li><strong>Brand as the product itself</strong>. There are extreme examples, like trainer brands, where wearing the same brand as your peers is more important than the shoe itself.</li> <li><strong>Negotiable prices</strong>. For example, tipping. There is not a preset price, but you must balance the shame of a too low price against not wanting to spend too much. There may be a generally accepted service charge percentage, which the the buyer just has to know. In some ways, this is a purer price because the buyer, within some constraints, can use the charge as a signal of the true value for them of the service.</li> </ol> <p>Phew. There are almost certainly more, but 10 is enough for now. Suffice to say that advertised prices alone are not a valid direct indicator of true value for all the reasons highlighted above. Technically, yes, "a price is what a buyer is willing to pay", but in the context of all the above, this is just a weightless tautology which does not tell you much about value.</p><![CDATA[The Global Minotaur: a review]]>https://www.houseofmoran.com/post/128554882283/the-global-minotaur-a-reviewhttps://www.houseofmoran.com/post/128554882283/the-global-minotaur-a-reviewMon, 07 Sep 2015 00:00:00 GMT<p><a href="http://yanisvaroufakis.eu/books/the-global-minotaur/"><figure class="tmblr-full" data-orig-height="642" data-orig-width="830" data-orig-src="https://varoufakis.files.wordpress.com/2011/12/screen-shot-2013-02-15-at-12-02-46-pm.png"><img src="https://66.media.tumblr.com/99c4c96b6159424177a4fc68229352d4/tumblr_inline_pk1qu7osC11r786jr_540.png" data-orig-height="642" data-orig-width="830" data-orig-src="https://varoufakis.files.wordpress.com/2011/12/screen-shot-2013-02-15-at-12-02-46-pm.png"></figure></a></p> <p>I occasionally read books on economics, and they uniformly scare me.</p> <p>As a parent, you look back to your own chlld-hood and realise your parents did not know what they were doing. Not because they did something bad, but because you know now that you don’t have all the answers, so they can’t have had them either. The veil of authority is removed but you can still have some degree of respect, even if not 100% agreement.</p> <p>Not so with economics.</p> <p>The typical economist, commentator, or politician on the Today programme will ooze confidence in their own reasoning. However, read almost anything on the fundamentals of economics, and you soon realise most of it is founded on large-scale bets, fuzzily-defended confidences and ridiculously dodgy assumptions.</p> <p>I can respect practitioners, like Entrepreneurs, and to a certain extent, Bankers; more specifically, anyone who has “skin in the game”, as <a href="http://www.econtalk.org/archives/2013/09/taleb_on_skin_i.html">Taleb</a> would say. They have to work with the horrific uncertainties of buying, selling, loaning and building, and make appropriate accommodations to get by. They support no illusions.</p> <p>Go back now to the voices of Radio 4 and hear the timbre of authority, unchanged. Recent events, such as the Scottish Independence vote, and the Euro crisis, have revealed this to be nothing but bluff and bravado. As pointed out by the book, Yanis Varoufakis is disliked by the establishment because he is erudite, capable, and more than willing to point out the many flaws in the mechanisms of the modern world.</p> <p>Surprisingly, this is not really a book about Greece. Against the themes of this book, Greece is at the level of roadkill. This is not a book about blame either. Many people are discussed as potent and deliberate actors but there is no desire for retribution.</p> <p>This is mostly a book about balance at the macro-economic level, with a side-order of theoretical sleight-of-hand thrown in as horrific entertainment on the side.</p> <p>His main thrust is that the required mechanisms of balance between exchange rates, surpluses and trade that were set up in the post-war period, based on sound fears of a repeat of the Great Depression, were deliberately manipulated in the 70s by America in a way which inevitably led to over-exploitation in the '90s, '00s, and ultimately, to the Crash of ’08.</p> <p>In my reading of this, the madness of instruments like Collateralised Debt Obligations and Credit Default Swaps was just one possible way an inherently unstable system (The Global Minotaur) could have fallen.</p> <p>Overall, the book is a great compacted history lesson. My knowledge of the inter-country economic history of the past 100 years is limited, so this is welcome, but this also means I can’t say what he is leaving out. For what my opinion is worth, it was enjoyable and consistent. It also makes me want to go read up on Keynes (for his part in post-war negotiations) and the '70s (for when the madness really started). Whether I’ll have the time is yet to be seen, but it has definitely provided the motivation.</p> <p>The writing style, pre-minotaur period, is quite strong and easy to read. I read most of this book on the bus and/or on the walk from school to work, so needed to pick it up again repeatedly. However, I found this hard to do when he got into his explanation of The Global Minotaur, for two reasons.</p> <p>If you’ve heard Yanis speak, you know he can be clear, but sometimes get distracted by florid descriptions, and over-dramatic framing. The same goes here, with repeated entwining of the real with the simile. Regardless of whether you already knew the Greek myth, he makes it work as an explanatory tool, initially. However, he returns to it too often, stretching the isomorphism to make a point when the facts themselves, once you’ve understood the framing, can stand alone.</p> <p>Over and above the re-use of the simile, he generally repeats himself too often. It’s as if the later chapters are a series of blog posts which have been concatenated together. In that context, where the reader may not have seen all previous instances, it makes sense to re-state. However, here it made me wonder if I’d accidentally skipped back a page, after re-engaging with the book.</p> <p>Once you get to the end, does he offer any hope, any solution?</p> <p>Early in the book, he suggests that from great turmoil comes great change. These Crises (with a capital C) are expected, and are almost a built-in razing to the ground in which new seeds can grow. He offers no new ideas, at least not in this book. In a way, he just documents the large scale needs that the global economy has now, and always has had, effectively reminding us that there is no free lunch.</p> <p>He also repeatedly points out that most of what is happening now, whether it is Austerity or the European Financial Stability Facility, is just more fiction; distractions and abstractions over impotence.</p> <p>The latest commentary from Yanis in the book is in the preface from 2013. In it he recommends that we resist, that we say “No!” to the mechanisms that he demonstrates in this book as illogical, and that make no accommodation for the <a href="http://yanisvaroufakis.eu/books/the-global-minotaur/">The Global Minotaur</a> that has so recently fallen. As we’ve seen, this strategy has not done him, nor Greece, a whole lot of good, but I honestly can’t see what else would have been better.</p><![CDATA[Looking for Bobby but found Paris instead]]>https://www.houseofmoran.com/post/126043044893/looking-for-bobby-but-found-paris-insteadhttps://www.houseofmoran.com/post/126043044893/looking-for-bobby-but-found-paris-insteadThu, 06 Aug 2015 00:00:00 GMT<p><a href="https://twitter.com/mandalovelyyy/status/627229546731810816"><img src="https://pbs.twimg.com/media/CLRd8hcUMAAEAu2.jpg" width="30%" style="float: left; margin-right: 15px; margin-bottom: 10px;"></a></p> <p>Go to any local attraction and you'll see people taking selfies with statues, towers, all sorts of sights. Once, walking past tourists taking pictures of <a href="https://twitter.com/search?f=images&#x26;vertical=default&#x26;q=greyfriars%20bobby&#x26;src=typd">Greyfriars Bobby</a> in Edinburgh, I reckoned that some of those will be posted on Twitter. I should be able to find these, and similar pictures, automatically. How difficult could it be?</p> <p>Problem: Porn. If you do a search for tweets containing "selfie" in the <a href="https://dev.twitter.com/streaming/reference/get/statuses/firehose">raw firehose</a>, then you'll find about it's about 60% Porn. I suspect the equivalent <a href="https://twitter.com/search?f=images&#x26;vertical=default&#x26;q=selfie&#x26;src=typd">live search on twitter</a> is doing <a href="https://github.com/mikemoraned/msw">some sort of filtering</a>.</p> <p>Even apart from the problem of Porn, there is no gaurantee they'll even use the term "selfie", so we need a different kind of filter.</p> <p>My hypothesis was that the selfies I was after would have one person in the foreground on the bottom left or right, with the object of interest in the background. I <a href="https://github.com/mikemoraned/selfies">coded this up</a>, and left it running for a bit.</p> <p>Umm, ok.</p> <blockquote class="twitter-tweet" lang="en"><p lang="th" dir="ltr">&#3586;&#3635;&#3626;&#3633;&#3626;&#3626; <a href="http://t.co/aEJcf5iYjR">pic.twitter.com/aEJcf5iYjR</a></p>&mdash; &#3600;&#3634;&#3609;&#3636; (@Purepareal) <a href="https://twitter.com/Purepareal/status/627842362136375296">August 2, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><blockquote class="twitter-tweet" lang="en"><p lang="th" dir="ltr">&#3652;&#3617;&#3656;&#3605;&#3629;&#3610;&#3652;&#3617;&#3656;&#3652;&#3604;&#3657;&#3649;&#3611;&#3621;&#3623;&#3656;&#3634;&#3627;&#3618;&#3636;&#3656;&#3591; &#3649;&#3605;&#3656;&#3617;&#3638;&#3591;&#3605;&#3633;&#3657;&#3591;&#3594;&#3639;&#3656;&#3629;&#3648;&#3615;&#3626;&#3591;&#3637;&#3657;&#3648;&#3629;&#3591;&#3609;&#3632; <a href="http://t.co/DHBqWxAhS7">pic.twitter.com/DHBqWxAhS7</a></p>&mdash; &#3591;&#3633;&#3623;&#3614;&#3637;&#3594; (Official) (@PeacHZ_YYY) <a href="https://twitter.com/PeacHZ_YYY/status/475658711671644160">June 8, 2014</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>I seem to have written a chat app detector. What else fits my description?</p> <p>Tv shows?</p> <blockquote class="twitter-tweet" lang="en"><p lang="tr" dir="ltr">1 y&#305;l &ouml;nce bug&uuml;n &#304;&#350;iD &#350;engale sald&#305;rd&#305; Binlerce Ezidi katledildi binlercesi esir al&#305;nd&#305;... <a href="http://t.co/kuIMIw8465">http://t.co/kuIMIw8465</a> <a href="http://t.co/ybijb5dvEV">pic.twitter.com/ybijb5dvEV</a></p>&mdash; Nurcan Baysal (@baysal_nurcan) <a href="https://twitter.com/baysal_nurcan/status/628080465866543104">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><blockquote class="twitter-tweet" lang="en"><p lang="und" dir="ltr"><a href="http://t.co/9jwY1lQsZu">pic.twitter.com/9jwY1lQsZu</a></p>&mdash; &#1582;&#1575;&#1604;&#1583; &#1575;&#1604;&#1593;&#1608;&#1587;&#1610; (@ousika) <a href="https://twitter.com/ousika/status/628337932265373696">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>Framed quotes, inspirational or otherwise.</p> <blockquote class="twitter-tweet" lang="en"><p lang="ja" dir="ltr">&#12300;&#26449;&#23665;&#35527;&#35441;&#12301;&#23455;&#24907;&#26126;&#12425;&#12363;&#12395;&#65281; &#20869;&#38307;&#12434;&#28961;&#35222;&#12384;&#12414;&#12375;&#35342;&#12385;&#12398;&#12424;&#12358;&#12395;&#30330;&#34920;&#12373;&#12428;&#12383;&#65281; &#35527;&#35441;&#12398;&#20013;&#12395;&#12399;&#20013;&#22269;&#20849;&#29987;&#20826;&#12300;&#20154;&#27665;&#26085;&#22577;&#12301; &#12364;&#12424;&#12367;&#20351;&#29992;&#12377;&#12427;&#12501;&#12524;&#12540;&#12474;&#12364;&#20351;&#12431;&#12428;&#12390;&#12356;&#12427;&#12290; &#20107;&#21069;&#12395;&#20013;&#22269;&#12392;&#35519;&#25972;&#12375;&#12383;&#30097;&#12356;&#12364;&#12354;&#12427;&#65309;&#21644;&#30000;&#35696;&#21729; <a href="http://t.co/E6DdpoLt99">http://t.co/E6DdpoLt99</a> <a href="http://t.co/yOl4Rah2WY">pic.twitter.com/yOl4Rah2WY</a></p>&mdash; &#12394;&#12394;&#12415;9019 (@superneoblack) <a href="https://twitter.com/superneoblack/status/628147719203258369">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">Privatisation is nothing more than shifting wealth from everybody to a privileged few. <a href="https://twitter.com/Corbyn4Leader">@Corbyn4Leader</a> will stop it. <a href="http://t.co/sI0xK175Wk">pic.twitter.com/sI0xK175Wk</a></p>&mdash; George Aylett (@GeorgeAylett) <a href="https://twitter.com/GeorgeAylett/status/627912503201284096">August 2, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>And headlines :-/</p> <blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">Larries: <a href="http://t.co/zU3BUbTnHW">pic.twitter.com/zU3BUbTnHW</a></p>&mdash; liv (@drunkpaIs) <a href="https://twitter.com/drunkpaIs/status/628551835658235904">August 4, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>With the above, it's easy to see how it matched, but some others are a bit more obscure. For each of the following, have a look at the tweet image for a bit before clicking through to the highlighted <em>face</em>.</p> <blockquote class="twitter-tweet" lang="en"><p lang="th" dir="ltr">&#3615;&#3636;&#3609;&#3648;&#3621;&#3632;&#3648;&#3607;&#3632; &#3615;&#3636;&#3609;&#3614;&#3633;&#3591;&#3614;&#3636;&#3609;&#3634;&#3624; &#3648;&#3629;&#3632;&#3629;&#3632;&#3621;&#3634;&#3585;&#3648;&#3586;&#3657;&#3634;&#3617;&#3640;&#3617; &#3648;&#3629;&#3632;&#3629;&#3632;&#3585;&#3629;&#3604; <a href="https://twitter.com/hashtag/%E0%B8%A3%E0%B8%B4%E0%B8%A7%E0%B8%88%E0%B8%B4?src=hash">#&#3619;&#3636;&#3623;&#3592;&#3636;</a> <a href="https://twitter.com/hashtag/AF12?src=hash">#AF12</a> <a href="http://t.co/gUjExo6Tn2">pic.twitter.com/gUjExo6Tn2</a></p>&mdash; &#3627;&#3609;&#3640;&#3591;&#3627;&#3609;&#3636;&#3591; (@niing_jaoka) <a href="https://twitter.com/niing_jaoka/status/628087289814495232">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p><a href="https://github.com/mikemoraned/selfies/blob/5e3d7e022be49d1bf9e8c622276edcaf52440235/examples/ye_ok/CLdqC43UEAAONqR.faces.jpg"><em>face</em></a></p> <blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">It's 2 A Day Monday.Good luck to Harlandale Lady Indians Volleyball.U had a Great Camp last week. <a href="https://twitter.com/hashtag/E3P?src=hash">#E3P</a> <a href="https://twitter.com/hashtag/Winning?src=hash">#Winning</a> <a href="http://t.co/OC3UOjuMxz">pic.twitter.com/OC3UOjuMxz</a></p>&mdash; E3Ptraining (@E3Ptraining) <a href="https://twitter.com/E3Ptraining/status/628174471757586432">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p><a href="https://github.com/mikemoraned/selfies/blob/5e3d7e022be49d1bf9e8c622276edcaf52440235/examples/ye_ok/CLe5WVKUcAAJ5SW.faces.jpg"><em>face</em></a></p> <blockquote class="twitter-tweet" lang="en"><p lang="ja" dir="ltr">&#12304;&#12500;&#12520;&#21091;&#20081;&#33310;&#12305;&#12388;&#12356;&#12395;&#20840;&#12500;&#12520;&#12381;&#12429;&#12356;&#12414;&#12375;&#12383;&#65281;&#65281;&#65281;&#12426;&#12388;&#12405;&#12353;&#12412;&#24540;&#25588;&#12375;&#12390;&#12367;&#12384;&#12373;&#12387;&#12383;&#26041;&#12293;&#12354;&#12426;&#12364;&#12392;&#12358;&#12372;&#12374;&#12356;&#12414;&#12377;&#65281;&#65281;&#65281;&#65281;&#65281;&#12500;&#12520;&#12467;&#12399;&#12392;&#12387;&#12390;&#12418;&#12363;&#12431;&#12356;&#12356;&#12391;&#12377;&#65281;&#65281;&#65281;&#65281;&#65281;&#27425;&#12395;&#35504;&#12363;&#12364;&#23455;&#35013;&#12373;&#12428;&#12383;&#12425;&#12414;&#12383;&#12424;&#12429;&#12375;&#12367;&#12362;&#39000;&#12356;&#12375;&#12414;&#12377;&#65288;&#30011;&#20687;&#12398;&#12500;&#12520;&#12398;&#38918;&#30058;&#12399;&#24859;&#29992;&#12375;&#12390;&#12356;&#12427;&#19968;&#35239;&#12363;&#12425;&#65289; <a href="http://t.co/0vkwJ7UbAP">pic.twitter.com/0vkwJ7UbAP</a></p>&mdash; &#12511;&#12521;&#12391;&#21407;&#31295;&#12375;&#12424;&#12358; (@sauri_uto) <a href="https://twitter.com/sauri_uto/status/626411592943407104">July 29, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p><a href="https://github.com/mikemoraned/selfies/blob/5e3d7e022be49d1bf9e8c622276edcaf52440235/examples/ye_ok/CLF2BgYUsAA1mPk.faces.png"><em>face</em></a></p> <p>You can see more of these <a href="https://github.com/mikemoraned/selfies/blob/5e3d7e022be49d1bf9e8c622276edcaf52440235/examples/ye_ok">examples</a> and <a href="https://github.com/mikemoraned/selfies/blob/5e3d7e022be49d1bf9e8c622276edcaf52440235/examples">other types</a> in my github <a href="https://github.com/mikemoraned/selfies">repo</a>.</p> <p>But, did I actually find anything? It took me a about an hour of trawling through around a thousand tweets it had found, but here's a perfect example of what I wanted:</p> <blockquote class="twitter-tweet" lang="en"><p lang="es" dir="ltr">Sin lugar a dudas una de las ciudades m&aacute;s hermosas y m&aacute;gicas ! <a href="https://twitter.com/RestoDelMundo13">@RestoDelMundo13</a> <a href="https://twitter.com/hashtag/IvanEnPar%C3%ADs?src=hash">#IvanEnPar&iacute;s</a> <a href="http://t.co/B32iQUbFas">pic.twitter.com/B32iQUbFas</a></p>&mdash; Facundo Gamband&eacute; (@facugambande) <a href="https://twitter.com/facugambande/status/628052502873796608">August 3, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>A one in a thousand hit-rate is <em>not great</em>, but given this was barely a days worth of implementation and tweaking, it's not bad. It's also obviously improvable. For example:</p> <ul> <li>I'm using the most <a href="https://github.com/mikemoraned/selfies/blob/a1ec58b410b256c1761f6fc97d02e6f4d7b43162/src/main/scala/com/houseofmoran/selfies/FacesCrawlerApp.scala#L47">basic face detector</a> available in <a href="http://www.openimaj.org/">OpenIMAJ</a>, and I'm not even filtering that by confidence.</li> <li>I can easily filter by relative size as well e.g. only include those faces which take up around 25% to 20% of the image.</li> <li>There is probably a text recogniser I can use to exclude images with mostly text outside the face.</li> <li>I can use a more focussed source than the firehose. For example, look for geotagged tweets nearby tourist destinations, or use a larger set of keywords than just "selfie". However, the wide-open nature of the firehose is appealing, so I'd like to see how far I can get with only image analysis.</li> <li>It's really a single-process app, even though I'm using Spark. If I had a bigger sample, and more limiting filters, then perhaps I could find more examples. I'm limited by the built-in firehose throttle, but I could probably scale out the image lookup, as long as <em>that</em> isn't then throttled.</li> </ul> <p>This is a work in progress, and I'm quite happy with what I have so far, so might leave this for a bit. Always other projects on the go!</p> <p>Finally, I'll end with one example I found which doesn't <em>quite</em> fit my original intent but which I like nonetheless:</p> <blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">Soon. <a href="http://t.co/fuPfEfsRqh">pic.twitter.com/fuPfEfsRqh</a></p>&mdash; Arsenal Related (@ArsenalsRelated) <a href="https://twitter.com/ArsenalsRelated/status/627870604788543488">August 2, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><![CDATA[Drone Futures]]>https://www.houseofmoran.com/post/120344203593/drone-futureshttps://www.houseofmoran.com/post/120344203593/drone-futuresSun, 31 May 2015 00:00:00 GMT<p>According to <a href="http://www.bloomberg.com/news/articles/2015-05-14/daimler-s-freightliner-tests-self-driving-truck-in-nevada">BusinessWeek</a>, long-haul trucks in America could be the first beneficiaries of self-driving technology. As far as safety and productivity goes, this should be a win.</p> <p>However: self-driving cars are already <a href="http://www.technologyreview.com/news/520746/data-shows-googles-robot-cars-are-smoother-safer-drivers-than-you-or-i/">arguably</a> safer than people in urban areas, driving between states is a <a href="http://en.wikipedia.org/wiki/DARPA_Grand_Challenge">comparatively easy problem</a>, and the occupant of a truck is not a necessary part of the cargo. So, it’ll be hard to argue to keep a driver behind the wheel.</p> <p><a href="http://en.wikipedia.org/wiki/Trucking_industry_in_the_United_States#Economic_impact">Around 3% of people in the US are directly employed by the trucking industry</a>. <a href="https://medium.com/basic-income/self-driving-trucks-are-going-to-hit-us-like-a-human-driven-truck-b8507d9c5961">A large fraction of these jobs will disappear, and related jobs will also be at risk. For example, there are many small towns whose livelyhoods are dependent on truck stops for trickle-down income. When truck drivers stop less, or are removed completely, then these towns will disappear, like the towns who were decimated when the highways came along</a> (see: <a href="http://en.wikipedia.org/wiki/Cars_%28film%29#Plot">Cars</a> :-) ).</p> <p>Even so, there may still be a net increase in overall happiness if more companies (e.g. <a href="http://www.theguardian.com/technology/2015/may/22/uber-self-driving-car-pittsburgh">Uber</a>) get their wish of self-driving vehicles. Not least because it would stop Uber applying their apparent policy of <a href="https://twitter.com/mike_moran/status/599958577474863104">treating their human employees like this centuries systematised labor</a>.</p> <blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr"><a href="http://t.co/Xu8Yw4WGbu">http://t.co/Xu8Yw4WGbu</a> : I would like to see some counterpoint, because I worry that Uber is just this centuries systematised slave labour</p>&mdash; mike_moran (@mike_moran) <a href="https://twitter.com/mike_moran/status/599958577474863104">May 17, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>The changes coming from self-driving vehicles will be big, and may even be positive. However, vehicles are something we already have and mostly understand. The infrastructure we have now limits where they can go and how fast they can travel. They still have to interact with pedestrians, even if they do it more efficiently than we can. Ultimately, they will be limited by having to follow 2D constraints. Drones, however, have no such limitations. </p> <p>There is a lot of <a href="http://www.forbes.com/sites/gregorymcneal/2014/07/14/alleged-drone-peeping-tom-photo-reveals-perils-of-drone-related-journalism/">hyperbole</a> said about drones, but a lot of it is just slightly ahead of real events. Easy availability of cheap drones that can act individually or collectively in a clever way is the sort of change that affects system-level assumptions, because what used to be hard will now be easy.</p> <p>On the walk to school, my son and I take turns making up imaginary machines. There is a rough theme, and one day it was construction. <a href="https://www.youtube.com/watch?v=JnkMyfQ5YfY">Inspired</a> by <a href="https://www.youtube.com/watch?v=w2itwFJCgFQ">youtube</a>, I came up with a “carpet of drones”. If you wanted a new build of something you'd hire a rolled up carpet of drones for a day, and perhaps a mini fabrication machine. You’d unroll the carpet, lay it flat, attach power, start up the fab, and upload your plan from your phone. The drones would auto-organise by role, some carrying bricks, some small dollops of binder, some straightening out the bricks to cover small mistakes. Come back in a few hours, pack them all up, and you’re done.</p> <p>Drones are numerous, adaptable, and already cheap enough to almost be disposable. The drone future is combinatorial and far less bounded than self-driving cars. Any prediction I make is going to be wrong or wildly unambitious, so I won’t make any right now. I’ll just leave you with <a href="http://www.brickdrones.com/story">something</a> which, as a fan of Lego, I can't believe I've only just discovered now:</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.youtube.com/embed/jbS9i54Mlrc" frameborder="0" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div><![CDATA[The Microservices Elephant]]>https://www.houseofmoran.com/post/110390636423/the-microservices-elephanthttps://www.houseofmoran.com/post/110390636423/the-microservices-elephantSun, 08 Feb 2015 00:00:00 GMT<p><a title="By Hanabusa Itchō [Public domain], via Wikimedia Commons" href="http://commons.wikimedia.org/wiki/File%3ABlind_monks_examining_an_elephant.jpg"><img width="512" alt="Blind monks examining an elephant" src="//upload.wikimedia.org/wikipedia/commons/thumb/4/45/Blind_monks_examining_an_elephant.jpg/512px-Blind_monks_examining_an_elephant.jpg"/></a></p> <p>The term “microservices” is going through a phase where everybody has their own conceptions of it, so as soon as you start talking about it in any detail you quickly realise you all mean something slightly different, and you start questioning the value of language and why you bother talking at all. However, given there is now <a href="http://shop.oreilly.com/product/0636920033158.do">a book out</a>, and a <a href="http://microxchg.io/">conference</a> on it next week, it feels like it’s about to become a lot more definite. I thought I’d brain-dump my own thoughts on a few of the conceptions that are out there, before my own stance gets hopelessly clouded by many others.</p> <p><em>modules + network = microservices</em></p> <p>This is from an <a href="http://programmingisterrible.com/post/110292532528/modules-network-microservices">article</a> by <a href="https://twitter.com/tef">@tef</a>, whose opinion I generally respect and, whilst I agree that “spreading bits of state across a network is a ... world of pain and suffering” and that “keeping data in sync across a network while tolerating failure is an incredibly hard engineering problem”, I really don’t think that’s the problem that microservices are meant to solve. Note that there are plenty of other things I do agree with in that <a href="http://programmingisterrible.com/post/110292532528/modules-network-microservices">article</a>, so please go read it.</p> <p>As in so many things, if you’re faced with a very hard problem, the first thing to seriously ask yourself is whether there is actually a far easier problem lurking within, that is the one you should be solving. In this case, the problem is not keeping state in sync. Bits of state, encapsulated behind a network interface maybe, but <em>separate</em> bits of state, which don’t even need to always be consistent. For example, I wouldn’t build a networked filesystem using microservices techniques, but I would build an advertising system using them.</p> <p><em>microservices = contractors for hire</em></p> <p>Some of my contractor friends might be offended by the following, but here goes :-) Microservices collaborating within a microservices architecture don’t fully trust each other. They make reasonable demands of each other, and expect responses, based on an agreed contract, but there is always a need to be ready for that contract to be cut short, or expectations to not be met. Microservices are about wrapping unreliable actors, and making them reliable in aggregate and/or ensuring unreliability at the micro scale does not become a macro problem.</p> <p>This analogy also captures the aspect of taking advantage of heterogeneity: microservices allow you to select the right tool/library/language for the job, as long as it presents itself as a semi-standard service.</p> <p>A microservices architecture should treat some demands as contractually required and others as nice-to-haves. For example, all services should guarantee a low-latency response, but the quality of response can be varied, or be a partial response, so that the latency remains guaranteed. High quality should be optimised for, but low quality allowed; high latency should be survivable, but low latency expected.</p> <p><em>microservices = a portfolio of risks</em></p> <p>This is analogy doesn’t fit all microservice contexts, but does fit the ones I like working with. Here, you actively hedge one microservice against another, so that when one fails, or gives a low quality answer, you can fall back on another. This is actually a tactic which works within a service as well as across them. For example, within service: using an in-memory out-of-date cached copy when an external service fails; across service: use recommendations from a less-personalised service when the personalised one times out.</p> <p><em>microservices = agent programming for the web</em></p> <blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/robstewartUK">@robstewartuk</a> <a href="https://twitter.com/russmiles">@russmiles</a> <a href="https://twitter.com/boicy">@boicy</a> <a href="https://twitter.com/russmiles">@russmiles</a> no, no, and three times: no. AOP was a pie-in-the-sky dream, MS is derived from implementations.</p>&mdash; mike_moran (@mike_moran) <a href="https://twitter.com/mike_moran/status/564191450414727170">February 7, 2015</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>(Gack; I wasted a lot of time in the 90’s thinking about agents).</p> <p>As you’ll have read above, my own take on Microservices very much treats co-operating services as a network of partially trusted actors, each with their own behaviours and preferences. It’s fine for myself and others to think about them that away, and to design libraries and tools that work well together given these assumptions, but there is absolutely no need to embed this understanding in the systems themselves. I’m not saying you can't build robust, flexible, and apparently clever systems with agents, but rather that they are not necessary.</p> <p>In conclusion, based on the above, my own idea of what microservices are is very much tied up with what I want to do with them, as opposed to the more wide-ranging meanings of others. No surprise there really, but now I’ve got that brain-dump out of the way, I look forward to finding out more and/or being usefully proved wrong in my assumptions about how to build systems well!</p><![CDATA[Cost of Delay vs Cost of Failure: a balance of forces]]>https://www.houseofmoran.com/post/105783767463/cost-of-delay-vs-cost-of-failure-a-balance-ofhttps://www.houseofmoran.com/post/105783767463/cost-of-delay-vs-cost-of-failure-a-balance-ofSun, 21 Dec 2014 00:00:00 GMT<p>This article presents my understanding of how the Cost of Delay model, in combination with Cost of Failure, can be used to choose between and decompose alternatives.</p> <p>TLDR: A DevOps team can get long-term rewards of minimising Cost of Delay by balancing it against the stabilising force of Cost of Failure.</p> <p>I went to a <a href="http://www.bcs.org/content/conEvent/8649">presentation</a> on <a href="http://blackswanfarming.com/cost-of-delay/">Cost of Delay</a> many months ago; thanks to <a href="https://twitter.com/ozzieyuce">Ozlem Yuce</a> for presenting it, and to <a href="https://twitter.com/sebrose">Seb Rose</a> and <a href="http://www.bcs.org/">BCS</a> for organising it.</p> <p>There is a lack of clarity below over whether we are measuring possible cost or actual benefit, but you’ll just have to live with this until I integrate/understand this further myself! Think of this as a progress report on my understanding. <a href="https://twitter.com/mike_moran">Feedback appreciated</a>, as always.</p> <h1>An aside on numerical interpretations (can be skipped):</h1> <p>I’m currently interested in using Cost of Delay as a qualitative method, partly because I don’t yet fully understand the implications of the quantitative side. However it is mostly because I am wary of numerical interpretations of methods that affect people (where “people" includes both “employees” and “customers”). As soon as a qualitative measure is represented as a number there is a strong tendency to start doing number-like things with it e.g. summing, averaging, comparing. This is often done very naively and can lead to pain for both the producer of the number and ultimately the consumer. It’s not that it is impossible to do correctly, or even necessarily hard, but it requires a bit of nuance to keep the number attached to it’s history e.g. some measure of uncertainty, like error bounds. To some this may come across as elitist or an over complication, but to me it’s about having respect for the numbers and the people they ultimately effect.</p> <h1>Cost of Delay</h1> <p>The basic idea behind Cost of Delay is to consider the loss you make as a result of not making an investment. The accumulated cost over time is some function of time. This is a very bland way of putting it, so I think it deserves a sketch:</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 35.6%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.flickr.com/photos/schnickschnack/16072126875/player/" frameborder="0" allowfullscreen webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>The shapes on the right illustrate some of the different ways that the cost function can behave. To pick one example (green rectangle): say you currently have an account on a cloud provider. They have a deal where you can use their services for free for 12 months, but thereafter you have to pay a yearly fee. This highlighted graph shows the cost over the next 12 months (it would look like a step function if extended indefinitely). Another example (blue ellipse), the classic compound interest on debt: you incur some debt, and then the interest on the debt becomes part of the debt itself, cost increases exponentially.</p> <p>I hope you get the gist, but let’s try an example closer to home. You have a great new idea you are working on, but you know it could take months to make it perfect, and you are not totally sure of it’s eventual worth. You think there may be a simpler idea you can ship pretty-much immediately, but it’s a bit crap in comparison. Let’s call these choices A ("definitely ok but available now”) vs B ("probably great, but not available for a while”):</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 23%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.flickr.com/photos/schnickschnack/15884849060/player/" frameborder="0" allowfullscreen webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>Maybe I just think more in terms of functions, but to me the diagram on the left is already helpful in forcing us to think about choices. So, what are some of the possible futures, based on this formulation? Note that now we are talking about possible futures, so these costs are turned into predicted benefits. From left to right:</p> <ol> <li>B<em>2 is a tweak on B which has higher value than A (larger gradient), not as much as B, but which is shippable now. We never come back and do B, because B</em>2 was good enough.</li> <li>We go ahead and ship A, and let it make some money in production, whilst we work on B. B replaces A when it is ready, and it turns out to be great.</li> <li>This is like 2, except another more important priority comes up and we don’t do B. Regardless, we’ll have made money on A in the mean time.</li> <li>We decide to immediately do an experiment on B, but on a cut-down version which will only work for two weeks. It turns out it wasn’t so great (perhaps customers don’t like it). We end up going with A after-all.</li> </ol> <p>There are many more choices or combinations than these, but I’ll leave you to come up with those yourself. My point is that thinking this way, even just diagrammatically, allows us to compare these various choices against each other, and provides a means to communicate these choices to others.</p> <p>Great, is this all we need to consider? No, but before we go further, let’s call out one aspect I am explicitly not emphasising here: waste. One of the things that can hold you back from shipping an A followed by a B (future 2 above) is that option A is work that you plan to discard later. There is no way round this; it’s definitely the plan. However, we are not optimising to minimise total work done. If anything, we are optimising for expected total value accrued over time. It’s not that efficiency is unimportant, but more that it should not be considered first. I could write more on this but not here; perhaps another blog post :-)</p> <p>Ok, back to Cost of Delay: there is some risk in these choices which we are not considering, which brings us to Cost of Failure.</p> <h1>Cost of Failure</h1> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 54.6%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.flickr.com/photos/schnickschnack/16071427822/player/" frameborder="0" allowfullscreen webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>A very simple model of the Cost of Failure consists of:</p> <ul> <li>“probability”, or 'time till failure': how long from now until it fails</li> <li>“impact”: when it does fail, how bad is it?</li> <li>“time to recover”: once you’ve identified it has failed, how quickly can it be rectified or limited in cost?</li> </ul> <p>Variation in each of these produces different models of cost, which dictates the accrued cost over time.</p> <p>Here, cost may be measured in units of ‘downtime’, in actual money lost, or some other measure. These formulations are still qualitative and the ‘cost' in ‘Cost of Delay’ is not exactly the same as the ‘cost’ above.</p> <p>The relevance of this comes when you see this as the flip-side of a choice that you want to make for Cost of Delay reasons. For example, consider option 4 previously, where we want to do an experiment over two weeks on B to measure value. If the failure curve looks like an escalation curve (red rectangle above, for example a small increase in site latency suddenly turns into an outage) then we won’t take the risk. However, if we can make it auto-recover (green rectangle above, for example an auto-restart of a service to clear memory leaks) then we may be happy with that for the duration of the experiment. The key aspect here is that the same team, or group of decision makers, must be willing and able to take both types of cost into account.</p> <p>The great thing about DevOps teams, if you’ve set them up properly, is that you have awareness of both sides, and can choose the best compromise at all times; you see the pain and the gain. If you only see one side, then then there is an imbalance.</p> <p>In summary: A DevOps team can reap the long-term rewards of minimising Cost of Delay by balancing it against the stabilising force of Cost of Failure.</p><![CDATA[Sharing applied to Healthcare]]>https://www.houseofmoran.com/post/86590770038/sharing-applied-to-healthcarehttps://www.houseofmoran.com/post/86590770038/sharing-applied-to-healthcareFri, 23 May 2014 00:00:00 GMT<blockquote class="twitter-tweet" lang="en"><p>Can we ever bring the sharing economy to health care coverage? If you are not using your insurance, give it to someone else. <a href="https://twitter.com/yeohsiewhoon">@yeohsiewhoon</a></p>&mdash; Filip Filipov (@Filipov) <a href="https://twitter.com/Filipov/statuses/469634939445858304">May 23, 2014</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>The idea of sharing unused insurance has a lot of assumptions baked in, and to be frank, I am no expert on emerging economies (referenced in a <a href="https://twitter.com/Filipov/status/469724321192366080">later tweet</a>). However, let's unpack this.</p> <p>Let's start with our goal. Can we assume, for the sake of argument, that it is to provide both protection of the individual against ailments and collective protection of the 'herd' against transmissible diseases ? To keep this simple, let's assume this is provided in the scope of a single country i.e. we don't attempt any cross-border solution.</p> <p>The choices for a solution come down largely to what degree collective versus individual responsibility is assumed. At one end of the scale we have the USA, where the individual largely expects to have to pay a company for insurance, and then claim on this per usage. The government covers some collective responsibility in the form of disease control, and Obamacare is changing things, but the assumption is largely that you have to look after yourself.</p> <p>At the other end is the UK where we still pay insurance, but it is a largely flat payment and we don't tend to pay a significant amount per usage. It is a hybrid in that private insurance also exists but that is typically used as an add-on rather than for primary care. Disease control is solidly in the domain of the government.</p> <p>The notion of "sharing" what you individually have only arises on the USA end of the scale. The implication is that since you've paid for something but not used it, why not enable altruism and allow it to be passed on? In this light, maybe it does make sense to enable this in some way.</p> <p>At the UK end, individual sharing makes no sense, since there is nothing for you to pass on. In fact, you're already sharing it with others by giving money to the government who does it on your behalf, except you have no control over who it's shared with (unless indirectly via elections).</p> <p>However does re-sharing even make sense at the USA end of the scale? To be exact, do you actually own your lack of a claim? I suspect insurance companies would say no. The insurance has been sold to you at a particular price on the basis of actuarial data about likelihood of a claim. You have been sold an option to claim healthcare at some future point. That option is not transferable because it would upset the model of expected claims.</p> <p>Now there is nothing stopping an insurance company from changing the way they sell it at the beginning so that it is transferable in some way. However, I suspect you'd then pay more for that and there would still be restrictions (e.g. only shareable amongst family members). An insurance company would not allow a very open interpretation of sharing because they make a lot of their money on people who pay but don't claim.</p> <p>I'm reading between the lines here a little and assuming you mean "sharing economy" in a very open sense. Given this interpretation, we're already doing it in the UK, just not under our individual control, in the form of the NHS. At the USA end of the scale, it would only be possible in a very circumscribed form. This implies that more sharing is possible in a Healthcare system like the UK.</p> <p>When it comes to how this applies to emerging economies, I really don't know. I suspect the level of sharing of unallocated resource depends on where it falls on the spectrum between USA and the UK.</p><![CDATA[Naked only please]]>https://www.houseofmoran.com/post/72101679688/naked-only-pleasehttps://www.houseofmoran.com/post/72101679688/naked-only-pleaseFri, 03 Jan 2014 00:00:00 GMT<p>Navigating a newly-discovered German swimming baths is a bit like an episode of the <a href="http://en.wikipedia.org/wiki/The_Crystal_Maze">Crystal Maze</a>. For those younger than me: this involved a series of rooms with dastardly puzzles which you needed to solve to get to the prize. Except the 'prize' here is men's bare arses.</p> <p>If you're used to the slightly prudish British swimming baths, where full nakedness is explicitly called out as something you <strong>must not do</strong>, then it comes as a bit of a shock. It's only really made acceptable because of stereotypical German efficiency.</p> <p>In a typical Edinburgh swimming bath, showers and locker areas are generally unisex with small changing cubicles along the sides in which you can hide your private parts from view. This flexibility makes the building very open, <em>architecturally</em>.</p> <p>Unfortunately, this seems to coincide with greater responsibility put on the bather. In <a href="http://www.edinburghleisure.co.uk/venues/portobello-swim-centre">Portobello baths</a> you must remember to bring a pound to put in the locker as deposit; you <em>can</em> choose the locker yourself, which is good, because about one in ten are broken. In contrast, today at <a href="http://www.hofwiesenbad-gera.de/index.html">Hofwiesenbad Gera</a> I paid and received a key for my locker. How did I know which one is mine? Well, I read the number on the key and used that one, of course.</p> <p>German baths are like a factory line, where everything has been worked out for you in advance, if only you can go the right way. Once I did, I found a very well looked after private men's shower area. Unfortunately, it came with some less well-kempt buttocks on display.</p> <p>I've yet to decide if the efficiency is worth the prize.</p><![CDATA[Looking back on my 5:2 diet]]>https://www.houseofmoran.com/post/71992882415/looking-back-on-my-52-diethttps://www.houseofmoran.com/post/71992882415/looking-back-on-my-52-dietThu, 02 Jan 2014 00:00:00 GMT<p>So, a year on, how's my 5:2 diet going? The good news is that, <a href="http://mikemoraned.github.io/52diet/">looking at the data</a>, I've lost a whole, umm, 2kg over the past year ... hmm, wait. Ok, maybe not so good. The full graph tells a bigger story:</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 33.4%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.flickr.com/photos/schnickschnack/11714695053/player/0632abf1a1" frameborder="0" allowfullscreen webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>I reached my lowest weight of 86kg first on the 28th June 2013. If you compare that to my maximum of 97kg on the 5th of January then a reduction of 11kg over 6 months isn't too bad. However, as you can see from the graph, I started trending up again soon after.</p> <p>The second axis, of total_calories expended through exercise, probably explains a large part of why. It shows that the extent and frequency of my exercise reduced soon after mid-year. Also, If I remember correctly, I kept bingeing a bit too much on off-days, <a href="http://blog.houseofmoran.com/post/46154894757/min-weight-90-0kg-gotta-work-on-avg-weight">as I was afraid of</a>.</p> <p>So, conclusions? All I can really say based on this is that a combination of exercise and 5:2 fasting worked for me. Now I just need to back to doing it properly again!</p><![CDATA[Spikes vs Tests: Brothers not Enemies]]>https://www.houseofmoran.com/post/71193279260/spikes-vs-tests-brothers-not-enemieshttps://www.houseofmoran.com/post/71193279260/spikes-vs-tests-brothers-not-enemiesThu, 26 Dec 2013 00:00:00 GMT<p>I write this post with a certain amount of guilt. If you look at my public coding persona (<a href="https://github.com/mikemoraned">https://github.com/mikemoraned</a>) it’s not unusual to see code with minimal tests, and a wide variety of styles and libraries. Compare that to my ‘at work’ style and, you’ll have to take my word on this, you’ll find a lot more tests and consistency. Why the difference? Most of my non-work code is the result of a Spike.</p> <p>In a similar vein to <a href="http://blog.houseofmoran.com/post/70701458720/pair-programming-the-good-the-bad-and-the-ugly">my other article</a>, it’s important to know why you are doing something, and what ‘done’ looks like.</p> <p>I do a Spike for various reasons, like wanting to explore a new language, or I’ve got an idea about how something might work, but I’m not totally sure it’s feasible. A Spike could possibly go on forever, so you have to choose a semi-arbitrary limit on when to stop. If I’m on holiday then I’ve got more free time, but that also means it’s easy to get distracted into <a href="http://en.wiktionary.org/wiki/yak_shaving">Yak Shaving</a> territory and I also usually have a stack of ideas waiting to try out. In practice, I’m usually ‘done’ either when I’ve learned what I needed to, or a couple of days have passed. </p> <p>Analogy hat on. Spikes serve the purpose that mockups do in other disciplines. It’s easy to have an idea in the shower, a lala-land where things always work, and think you are done. However, when you try to make it you find the bits are too heavy and fall apart when put together. Let’s consider a couple of recent examples. </p> <p>My <a href="http://blog.houseofmoran.com/post/70835570249/playing-music-when-someone-is-typing">Playing music when someone is typing</a> idea came when I was on a plane. After breaking it down I identified what I thought was the most difficult technical part and I did a Spike on that. I almost ran out of time, because I’d made a <a href="https://github.com/mikemoraned/msw/commit/f91b41abb80bdc0062dd06ed9b31dbab62da803c">stupid mistake interpreting radians as degrees</a>. However, I got to the point where I thought it was proven feasible, so I stopped and wrote it up.</p> <p>Should you use tests during Spikes? Maybe. Should it be test-driven? Definitely not. If I’d done this Spike that way, then I probably would have found the radians bug, but the whole process would have taken a lot longer. Test-driven development is good for situations where you need to go from no software, to working software, delivering small units of working, valuable software along the way. With Spikes you’re taking on the risk of either delivering nothing, or, at-best, ending up with something which basically proves the point but which is very fragile. This is ok, because this is balanced against the risk of not finding out anything at all.</p> <p>The reason I suspect most people who do Spikes still advocate doing them in a test-driven way is because they suspect the Spike-produced code will be taken from their hands and used for realz. You can make this less likely by using technical hints, like doing it on a branch. Ultimately, the problem of “shipping the prototype” is a social problem, not a technical one, and not one I have any easy solution to. However, for me, personally, on my own projects, I can just not be stupid.</p> <p>This first example was about proving if it’s technically possible to detect fingers moving a keyboard. Any final product would look nothing like this. My second example is different, and is more akin to a working mock-up. It started out as this (excuse my ridiculously bad sketching):</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 70.6%; position: relative; height: 0; overflow: hidden;" > <iframe src="https://www.flickr.com/photos/schnickschnack/11562143504/player/0159272f5e" frameborder="0" allowfullscreen webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>As <a href="http://blog.houseofmoran.com/post/71157450893/just-playing-around-with-using-geohashes-as-an">explained in the post</a>, I have some ideas about using GeoHashes to show geocoded images. This formed in my head as way of exploring a series of pictures, and I did the sketch above around what it might look like. Over <a href="https://github.com/mikemoraned/geosummary/commits/master">a day or so</a>, I found a source of images, and started exploring how to show them. It was important to use real images, because I wanted to get a feel of whether exploring a real, but pseudo-geocoded, space made sense. I soon dropped a lot of what I’d originally envisaged, such as sliding your finger over images to browse them, because although it would be fun to implement, it wouldn’t help me with my larger mission. In the end, I ran out of time, but I did get as far as seeing what it felt like to explore the space, and what the problems were (“where the bits were too heavy"). I haven’t learnt as much as I’d liked but it’s important to not just blindly bludgeon your way forward, because that way leads to eventual pain.</p> <p>So, in summary, use a Spike when you want to explore, don’t be ashamed to not use tests, limit your time, and keep the learning, but not the code.</p><![CDATA[Playing music when someone is typing]]>https://www.houseofmoran.com/post/70835570249/playing-music-when-someone-is-typinghttps://www.houseofmoran.com/post/70835570249/playing-music-when-someone-is-typingSun, 22 Dec 2013 00:00:00 GMT<p>It all started when Carmen asked me (something like): "couldn't you play that <a href="http://www.youtube.com/watch?v=Ir5czCiOpsk">music from Murder She Wrote</a> at work whenever you're typing?" Given I was on a plane at the time, with nothing much else to do, why not think about it?</p> <p><strong>Requirement: Play music when someone is typing</strong></p> <p>Basic idea: play that random <a href="http://www.youtube.com/watch?v=Ir5czCiOpsk">annoying music from Murder She Wrote</a> in the office whenever someone is typing</p> <p>Parts: detect typing + interpret as instructions of when to play music + play music</p> <p>The hard part is detecting the typing, not because you couldn’t write a program to listen to key presses, but more because people wouldn’t want to install it.</p> <p>All we actually care about is a ‘key stream’ of activity, which indicates someone is typing, so we don’t care about the individual key presses, or even what the keys were. We can also accept a high false positive rate on individual key press, as long as we smooth out any variability over time.</p> <p>Some ideas that don't involve having direct access to a key-press stream:</p> <ul> <li>Listen to the noise of people typing. Probably technically possible, but hard to get right. Would vary a lot over keyboards, and need calibrated.</li> <li>Detect when people’s hands are over the keyboard and moving.</li> </ul> <p>This last one has legs. We could actually look for moving flesh i.e. we look at the keyboard area, detect the pixels which are probably from someones hands, and look to see if the number of them change rapidly over time. This is a very low-level detector which would ‘detect’ lots of other things, if it wasn’t looking at a keyboard, but is probably good enough for this problem.</p> <p>We can validate this perhaps by using an existing flesh-detector and feeding it pictures taken from a camera looking at a keyboard and see if it sees changes. The sampling rate would probably need to be quite high because peoples fingers flit over a a keyboard very fast.</p> <p>To smooth out any noise, we could interpret the %-age of fleshy pixels that are moving as ‘energy’. This could be used with a simple threshold, or used as energy of a 1D ball being thrown up in the air, which we let decay, so that small gaps in energy don’t show up.</p> <p>We then just need to turn this into either a 'stop playing' or 'start playing' signal. And hire an orchestra. Job done. (Carmen adds: "Also, somebody needs to make a hairdresser’s appointment for everyone typing so that they can all have blue rinse perms done.")</p> <p><strong>Having a go</strong></p> <p>Since I'm on holiday, and I've done something similar before, I decided to <a href="https://github.com/mikemoraned/msw">have a go</a> at the 'flesh-detector' part. Overall, it basically works. The video below shows me using a mirror to get my laptops camera seeing both the keyboard and my hands:</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 75%; position: relative; height: 0; overflow: hidden;" > <iframe src="//www.youtube.com/embed/SazYTnYMvsg" frameborder="0" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>The output is very noisy, and show's a reasonable amount of non-skin pixels, but given I've skipped over quite a few of the steps of the Fleck and Forsyth (described in <a href="http://www.cs.hmc.edu/~fleck/naked-skin.html">"Naked People Skin Filter"</a>) algorithm, I'm sure it could be cleaned up. For example, I don't try to filter skin-pixels not surrounded by other skin-pixels.</p> <p><strong>Next steps?</strong></p> <p>I'm not gonna take this any further, even though it was fun, because I've got plenty of other projects to make progress on. If I was I would most likely look for an existing library and see if that works better. If I couldn't find any better library, the minimum to turn this into a 'typing detector' is probably to do diffs between successive skin-pixel snapshots, and look for motion; something very similar to the method in the <a href="http://timtaubert.de/blog/2013/02/getusermedia-part-3-simple-motion-detection-in-a-live-video/">article</a> I used as a template.</p> <p>So, in summary, no need to book the orchestra quite yet.</p><![CDATA[Pair Programming, the Good, the Bad and the Ugly]]>https://www.houseofmoran.com/post/70701458720/pair-programming-the-good-the-bad-and-the-uglyhttps://www.houseofmoran.com/post/70701458720/pair-programming-the-good-the-bad-and-the-uglySat, 21 Dec 2013 00:00:00 GMT<p>Reading <a href="http://phinze.github.io/2013/12/08/pairing-vs-code-review.html">http://phinze.github.io/2013/12/08/pairing-vs-code-review.html</a> has made me consider again what I think of as "pair programming". It’s a phrase that is misinterpreted, so let me clarify what it means to me. </p> <p>I’ve worked on different teams where, none, some and constant pair programming was done.</p> <p>Not doing any is dangerous, and leads to the classic rock-star/lone/hero programmer situation where, by the time you realise you have a codebase consisting of a series of opaque but clever hacks, it’s too late to change anything.</p> <p>Pair programming all-day, every-day can be liberating to begin with, but degenerates into absurdity e.g. pair reading of documentation. It’s not as bad as none at all, but it covers up the benefits, and provides plenty of ammunition to those who are against it entirely.</p> <p>So, I definitely come down in the favour of ‘some’ pair programming, but if not all of the time, then when? Rather than prescribe a schedule, it’s important to realise why you might be doing it, and apply it as a tool.</p> <p>During pairing for knowledge transfer, between an expert and a learner, then you can expect the task to take longer, because the primary goal is learning, not fast completion of the task. These sorts of sessions are best triggered as a result of a planning session conversation, where it’s obvious only one person on the team can do the task. The pairing session is ‘done’ when it becomes clear the learner can now do the task on their own. It’s important to realise that pairing for knowledge transfer is not always the best way to pass on knowledge. Repeated pairing is effectively a very slow ‘flood fill’ algorithm. Sometimes, it’s good to spend time doing a short one-to-many presentation on what you know.</p> <p>If we are instead pairing to solve a problem, then the expectation is that one half of the pair is stuck in some way, or a larger problem needs to be discussed. Here, ‘done’ is when the person becomes unstuck, or a plan has been reached that looks feasible. These sessions can last seconds, minutes, or hours. Some of my most useful pairing sessions have lasted a few minutes, ending as soon as it becomes clear I’ve missed something obvious.</p> <p>That last example is one reason why I mis-trust code-review, since it can too easily come at the end of a unit of work. The right feedback at the start of a task can totally change how it’s done. Once you have a functional bunch of code that’s ready to check-in or to deploy, it’s hard to push back on a bad design. A lot of the differences are down to social context. Code-reviews typically happen in a context of challenge, where one programmer presents a completed artefact for others to find fault with, whereas pair programming is typically collaborative, where you work together to share knowledge or solve a problem.</p> <p>In conclusion, "pair programming” for me is a tool, not a way of life, and should be applied based on a clear statement of why you are doing it.</p><![CDATA[Playing around with Verlet JS]]>https://www.houseofmoran.com/post/69374409444/playing-around-with-verlet-jshttps://www.houseofmoran.com/post/69374409444/playing-around-with-verlet-jsSun, 08 Dec 2013 00:00:00 GMT<p>I'm considering using <a href="http://subprotocol.com/verlet-js/">Verlet.JS</a> as a minimal Physics engine for another project of mine. I tried it out by porting over my little <a href="https://github.com/mikemoraned/lSystemsCrochet">LSystems Crochet</a> project to use it. You can see the results here: <a href="http://mikemoraned.github.io/lSystemsCrochet/verlet.html">http://mikemoraned.github.io/lSystemsCrochet/verlet.html</a></p> <p>It mostly works, apart from one crucial aspect: repulsion. Without it, there is nothing forcing the nodes to bunch up and form interesting patterns. The D3-based version (<a href="http://mikemoraned.github.io/lSystemsCrochet/">http://mikemoraned.github.io/lSystemsCrochet/</a>) does this by default.</p> <p>This is not really a fault of <a href="http://subprotocol.com/verlet-js/">Verlet.JS</a>, as it could probably be implemented as a constraint, but it is interesting how such a seemingly small difference can lead to such a boring outcome!</p> <p>I'm gonna leave this here for now, as I most likely don't need repulsion for my other project. Give <a href="http://subprotocol.com/verlet-js/">Verlet.JS</a> a try, it's pretty easy to get going.</p><![CDATA[Web Performance Days, New York: "Load Testing" Open Spaces Session]]>https://www.houseofmoran.com/post/64707426137/web-performance-days-new-york-load-testinghttps://www.houseofmoran.com/post/64707426137/web-performance-days-new-york-load-testingMon, 21 Oct 2013 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/10425712164/" title="Web Perf Days NY by MikeMoran, on Flickr"><img src="http://farm6.staticflickr.com/5503/10425712164_2f8b3cc85b.jpg" width="500" height="375" alt="Web Perf Days NY"></a></p> <p> One of the best hours I spent in New York was in an open spaces section of <a href="http://www.webperfdays.org/events/2013-newyork/index.html">web performance days</a>, which followed on after <a href="http://velocityconf.com/">Velocity</a> NY. It was on &quot;Load Testing&quot; and was led by <a href="http://www.alexanderpodelko.com/">Alexander Podelko</a> and had a few other contributors, including myself. </p> <p>I'm writing this partly for my own benefit because it was one of the few sessions where I didn't take any notes straight after, and I want to brain dump whilst it's still relatively fresh. Below, what I remember us saying is in normal text whilst my follow-on thoughts and commentary are in <i>[italics]</i>.</p> <p>Load Testing can be broken down into three kinds: Smoke Testing, Regression Testing and Scalability Testing <i>[aka: 'Did I just break the build?', 'Will this affect production?', and 'Oh frack, we're on Reddit, what now?']</i></p> <p><i>[We didn't talk much about Smoke Testing, but ...]</i> Smoke Testing is all about doing enough to sanity check that you haven't done something incredibly stupid. <i>[In the context of Load Testing this means hitting the system under test with enough load and with enough variety of requests to trigger obviously bad behaviour. For example, for a search service this could be submitting a mix of query difficulties over a short period of time, and asserting that the response time is always below some threshold. The most simplistic way to derive a synthetic set of tests is to run your integration tests repeatedly.]</i></p> <p>How you go about Regression Testing depends a lot on how you do releases. If you have big-bang releases where the time between them is large, e.g. weeks, then Regression Testing is more about modelling and/or testing your system under expected inputs, and seeing how it responds. </p> <p>If you have releases that take hours or days, then you have the luxury of up-to-date samples of system behaviour, but very little time to understand the model that underlies it all. <i>[It wasn't stated explicitly, but I think there was also general skepticism that straight-forward models even exist]</i>. Given this context it's possible to think of your systems performance as one of the many measures in an A/B test, and to skip Regression Testing. As long as you have a way to quickly roll back your changes and have bounded your possible losses as part of normal A/B test procedure then this can be a way to test in production safely. If full A/B test rigour is not required, then an even simpler version is to have a canary (aka staging) box in production, which is examined for performance degradations over time.</p> <p>Another technique blurs the Smoke/Regression test distinction: replaying a subset of your real traffic against a pre-production system and checking for performance regressions against what production did with the same input. <i>[This can be automated to an extent by comparing summary statistics e.g. differences in standard deviations.]</i> If your system under test can't be fully isolated from outside influence, which is typical, then you'll have to allow for some skew between production and test. <i>[For example, if you're storing information about a customer then there will typically be more of it later on so performance of anything based on it will be different. ]</i></p> <p><i>[If you want to minimise the effect of the skew, then you could replay the traffic against two non-prod systems, one running production code and the other running the new code. However, this has a lot of setup cost and isn't too dissimilar from an A/B test, or canary in production, so why not just do that?]</i> Additionally, each call replayed may have a real monetary cost, over and above the hardware required, which could become significant if calls are replayed in bulk.</p> <p><i>[Replay testing may be justified if what you're testing isn't ready for production for non-performance reasons. For example, if you're re-implementing an API using a different back-end, but it isn't functionally complete yet. In these cases, it's desirable to treat the performance of the existing system as a feature that has to be maintained in parallel with any features added.]</i></p> <p><i>[We didn't talk much about Scalability Testing, which is what people normally associate with Load Testing, unless I missed something?]</i></p> <p><i>[Here endeth the braindump. If you were at the meet-up and any of the above is incomplete, misleading, or just plain wrong, then please let me know and I'll update it.]</i></p><![CDATA[min(weight) = 90.0kg! (gotta work on avg(weight))]]>https://www.houseofmoran.com/post/46154894757/minweight-900kg-gotta-work-on-avgweighthttps://www.houseofmoran.com/post/46154894757/minweight-900kg-gotta-work-on-avgweightSun, 24 Mar 2013 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/8584803389/" title="weight snapshot month by MikeMoran, on Flickr"><img src="http://farm9.staticflickr.com/8507/8584803389_6b17da1f4f_n.jpg" width="320" height="143" alt="weight snapshot month" /></a></p> <p>I've been doing the 5:2 diet now for around three months now, and just this week my min weight hit 90.0kg! As you can see from above there is a lot of volatility in my measurements; I measure myself every weekday at around the same time, but there is still easily a range of 2kg in the measurements. My fast days are Monday and Thursday, and my weight, unsurprisingly, is lowest after those days.</p> <p>If you look at the data since my records began, you see the effect on the weekly average:</p> <p><a href="http://www.flickr.com/photos/schnickschnack/8585904248/" title="weight snapshot year by MikeMoran, on Flickr"><img src="http://farm9.staticflickr.com/8235/8585904248_5a91dd7b92.jpg" width="370" height="379" alt="weight snapshot year" /></a></p> <p>It'll still be a while before I average below 90kg, but it's encouraging to see it going down.</p> <p>Overall, the fasting days are a lot easier to do than I'd thought. You have 600 calories to spend, and I usually split these between 300 calories for coffee/lattes in the morning and during the day, followed by 300 calories for a meal in the evening. I don't have much variety in meals; typically it's some pitta bread with sliced meat. When I do vary, I stick to what I can easily scan into <a href="http://www.myfitnesspal.com/">http://www.myfitnesspal.com/</a></p> <p>I chose Mondays and Thursdays as fast days because I don't do much in the evenings on those days, which makes it easier to stick to. I've found I can do exercise on these days too; I'm up to 6 mile runs with no obvious ill-effect.</p> <p>On off-days I've been taking advantage of "eat what you like" a little too much. The freedom is nice, but to be honest, I do sometimes binge. I don't think this will ultimately effect whether I will reach my goal, just when. I've done around 3kg in 3months, and being down to 87kg by June would be nice, but 85kg would be even nicer!</p><![CDATA[BrowserStack: thumbs up on first minimal try-out.]]>https://www.houseofmoran.com/post/41231695412/browserstack-thumbs-up-on-first-minimal-try-outhttps://www.houseofmoran.com/post/41231695412/browserstack-thumbs-up-on-first-minimal-try-outTue, 22 Jan 2013 00:00:00 GMT<p>I just tried out <a href="http://www.browserstack.com/">http://www.browserstack.com/</a> for testing my minimal IE8/IE9 changes for <a href="https://trello.com/card/make-it-work-in-ie8/50d4b39f3d7039c91b001237/5">Nice to have</a>. It's actually really quite handy. Take my review below with a pinch of salt though, as I only used it for 30 mins. I did a free registration around xmas and forgot about it, so that's all I had left today! Silly mike.</p> <p>All the standard debugging tools are set up (e.g. firebug lite), and you get a single window to play in. You set up a tunnel through a signed app so that it sees your server, choose your OS/browse combo, and your off. You do your edits locally, as normal, using whatever libraries and editor you fancy. It is a bit laggy, but usable, and that could have been my connection to blame.</p> <p>It's around £12 ($19) dollars a month. Given I can set up a VM locally for IE testing if I really need to, that's not in the range where I'd immediately upgrade to paid, but I'll definitely consider it next time I'm doing a bunch of IE testing.</p><![CDATA[Brickman Experiment 1]]>https://www.houseofmoran.com/post/41142093343/brickman-experiment-1https://www.houseofmoran.com/post/41142093343/brickman-experiment-1Mon, 21 Jan 2013 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/sets/72157632581282738/show/" title="Best of friends by MikeMoran, on Flickr"><img src="http://farm9.staticflickr.com/8055/8402525749_889435c08f.jpg" width="500" height="333" alt="Best of friends"></a></p> <p>I had some fun making snow bricks at the weekend. Technically, Nils was present but it would be unfair to say I was playing with him; "directing", perhaps.</p> <p>So, anyway, obviously you should try to use snow bricks to make a Lego man. Obviously.</p> <p>It turns out that <a href="http://www.moomilk.co.uk/index.html">moo milk</a> cartons are quite good brick molds if you <a href="http://www.flickr.com/photos/schnickschnack/8403614792/in/set-72157632581282738/">cut off one side and leave the flap on</a>.</p> <p>This one got to the point where I was just about to make a head, but then thought I should defer until later to give me a chance to get Nils interested. Unfortunately, headlessness was the least of its problems: it fell over a minute after I came in. Oh well. Looks like balance is gonna be a bigger problem than structural strength.</p> <p>Here's hoping it snows again next weekend!</p><![CDATA[Reading the Tea Leaves]]>https://www.houseofmoran.com/post/39226309653/reading-the-tea-leaveshttps://www.houseofmoran.com/post/39226309653/reading-the-tea-leavesSun, 30 Dec 2012 00:00:00 GMT<p>When I was at Amazon I looked at a lot of graphs. Graphs of hits, graphs of cpu, graphs of all sorts of shit. Graphs are great, I loves them. However, the problem is that if you aren't in a habit of looking at the relevant graphs every day, and then something happens, you're faced with the problem of deciding what's normal. It is <em>so easy</em> to find patterns, especially if you have a good reason to think something important is happening (either for a good or bad reason).</p> <p>I'm reminded of all this when I happen on a GeoCities-tastic page like this: <a href="http://www.trading-naked.com/headandshouldersREVERSE.htm">http://www.trading-naked.com/headandshouldersREVERSE.htm</a> I am no stock expert but I'm willing to bet the patterns he is using are tenuous at best. Then again, maybe the market wouldn't work without people like him?</p><![CDATA["Nice to have" v0.0000001]]>https://www.houseofmoran.com/post/39084311065/nice-to-have-v00000001https://www.houseofmoran.com/post/39084311065/nice-to-have-v00000001Sat, 29 Dec 2012 00:00:00 GMT<p>Ugh. Enough holiday hacking for now. I had an idea for an app a few weeks ago, and finally had some time between xmas celebrations to hack up a first version. Here it is: <a href="http://nicetohave.houseofmoran.com/">http://nicetohave.houseofmoran.com/</a> (source: <a href="https://github.com/mikemoraned/nicetohave-app">https://github.com/mikemoraned/nicetohave-app</a>)</p> <p>I'm not gonna talk much more about it until I've dog-fooded it a bit myself for my own personal backlog. Feel free to use it though, I always appreciate feedback.</p> <p>For now, I'll just leave some links which helped me to write it.</p> <p>Trello:</p> <p><a href="https://trello.com/docs/gettingstarted/clientjs.html">https://trello.com/docs/gettingstarted/clientjs.html</a> <a href="http://jsfiddle.net/E4rLn/">http://jsfiddle.net/E4rLn/</a> <a href="https://trello.com/docs/gettingstarted/index.html">https://trello.com/docs/gettingstarted/index.html</a> <a href="https://trello.com/docs/api/card/index.html#put-1-cards-card-id-or-shortlink-pos">https://trello.com/docs/api/card/index.html#put-1-cards-card-id-or-shortlink-pos</a></p> <p>D3:</p> <p>Scales: <a href="http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color/">http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color/</a></p> <p>Ordinals aren't great to work with: <a href="https://github.com/mbostock/d3/pull/598">https://github.com/mbostock/d3/pull/598</a></p> <p>Brushes/selections: <a href="http://people.ucsc.edu/~pmerritt/d3/examples/brush/brush.html">http://people.ucsc.edu/~pmerritt/d3/examples/brush/brush.html</a> <a href="http://bl.ocks.org/1667367#index.html">http://bl.ocks.org/1667367#index.html</a></p> <p>Knockout custom bindings:</p> <p><a href="http://knockoutjs.com/documentation/custom-bindings.html">http://knockoutjs.com/documentation/custom-bindings.html</a></p> <p>Knockout Event bindings:</p> <p><a href="http://knockoutjs.com/documentation/event-binding.html">http://knockoutjs.com/documentation/event-binding.html</a></p> <p>Twitter bootstrap form examples:</p> <p><a href="http://www.w3resource.com/twitter-bootstrap/forms-tutorial.php">http://www.w3resource.com/twitter-bootstrap/forms-tutorial.php</a></p> <p>Ejs/express:</p> <p><a href="http://robdodson.me/blog/2012/05/31/how-to-use-ejs-in-express/">http://robdodson.me/blog/2012/05/31/how-to-use-ejs-in-express/</a></p> <p>Sammy + Knockout example:</p> <p><a href="http://learn.knockoutjs.com/WebmailExampleStandalone.html">http://learn.knockoutjs.com/WebmailExampleStandalone.html</a></p> <p>"Less" middleware:</p> <p><a href="http://www.andyjarrett.co.uk/blog/index.cfm/2012/4/11/Express-Less-and-lessmiddleware">http://www.andyjarrett.co.uk/blog/index.cfm/2012/4/11/Express-Less-and-lessmiddleware</a></p> <p>Annoyances:</p> <p>"top" and "left" css attributes don't work in FF unless you specify a unit i.e. "px". Why do I always forget this?</p><![CDATA[Resources for a designer transitioning from print to the web?]]>https://www.houseofmoran.com/post/39123060084/resources-for-a-designer-transitioning-from-printhttps://www.houseofmoran.com/post/39123060084/resources-for-a-designer-transitioning-from-printSat, 29 Dec 2012 00:00:00 GMT<p>A friend of mine who has a background in print design (copy, layout, some photography) is wanting to move his skills over into web design. I am most definitely on the other-side of this divide, so I asked another web designer friend what resources (website/book/whatever) they'd recommend: </p> <blockquote> <ul> <li>Most things by <a href="http://www.amazon.co.uk/s/ref=nb_sb_ss_i_0_10?url=search-alias%3Dstripbooks&#x26;field-keywords=jacob%20nielsen&#x26;sprefix=Jacob%20Niel,stripbooks,520&#x26;rh=n:266239%2Ck%3Ajacob%20nielsen">Jakob Nielsen</a></li> <li><a href="http://www.amazon.co.uk/About-Face-Essentials-Interaction-Design/dp/0470084111">About face 3</a></li> <li>Steve Krugs <a href="http://www.amazon.co.uk/Dont-Make-Me-Think-Usability/dp/0321344758">Don't Make Me Think!</a></li> <li><a href="http://www.amazon.co.uk/Seductive-Interaction-Design-Effective-Experiences/dp/0321725522">Seductive Interaction Design</a></li> <li><a href="http://www.amazon.co.uk/UX-Book-Guidelines-Ensuring-Experience/dp/0123852412">The UX Book</a></li> <li><a href="http://www.amazon.co.uk/Sketching-User-Experiences-Getting-Design/dp/0123740371/">Sketching User Experiences</a></li> <li>Any book by <a href="http://www.amazon.co.uk/s/ref=ntt_athr_dp_sr_1?_encoding=UTF8&#x26;field-author=Bill%20Buxton&#x26;search-alias=books-uk">Bill Buxton</a></li> </ul> <p>I think that's a good start I've purposely left out any core design as he should have a solid foundation in that already</p> </blockquote> <p>Any more recommendations?</p><![CDATA[Heed!]]>https://www.houseofmoran.com/post/28372563011/heedhttps://www.houseofmoran.com/post/28372563011/heedTue, 31 Jul 2012 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/7680480396/" title="Heed! by MikeMoran, on Flickr"><img src="http://farm9.staticflickr.com/8429/7680480396_168caf5e5c.jpg" width="500" height="375" alt="Heed!"></a></p> <p>And so, the saga continues, baldie once again.</p> <p>Interestingly, this time, I was very conscious of when it started happening. It may just be my imagination, but soon after I got a few midgy (or <a href="http://dict.tu-chemnitz.de/dings.cgi?lang=en&#x26;service=deen&#x26;opterrors=0&#x26;optpro=0&#x26;query=M%FCcken">Mücken</a>) bites in Germany, I noticed my head was a bit itchy. In the following days, the hair loss seemed to accelerate rapidly.</p> <p>My hypothesis is that given that <a href="https://www.alopecia.org.uk/Pages/FAQs/Category/types-of-alopecia">aa</a> is an auto-immune disease a reaction to a bite could somehow start my immune system off, but I obviously can't prove it. However, it's about as good as any hypothesis I ever heard from my doctor since she basically had no idea. To be fair, she was very apologetic about it.</p> <p>Anyway, c'est la vie. Now I can go back to disturbing people by absent-mindedly rubbing my head in meetings ;-)</p><![CDATA[Truth is more depressing than fiction?]]>https://www.houseofmoran.com/post/27635184834/truth-is-more-depressing-than-fictionhttps://www.houseofmoran.com/post/27635184834/truth-is-more-depressing-than-fictionFri, 20 Jul 2012 00:00:00 GMT<p>This holiday, I finally finished <a href="http://www.amazon.co.uk/gp/product/B003E2UQLO?ie=UTF8&#x26;camp=1634&#x26;creativeASIN=B003E2UQLO&#x26;linkCode=xm2&#x26;tag=houseofmoran-21">"The City &#x26; The City"</a> by <a href="http://www.amazon.co.uk/China-Mi%C3%A9ville/e/B001IQUN20">China Miéville</a>.</p> <p>My paper version of the <a href="http://www.amazon.co.uk/China-Mi%C3%A9ville/e/B001IQUN20">Miéville</a> book was a gift. Its <em>hugeness</em> makes it hard to carry, so I never got round to reading it. I bought it again for my Kindle (I wonder how often that happens?). Alongside his newly coined words there are many that lie <em>just</em> outside my vocabulary, so the built-in Kindle dictionary was very handy. Some of his invented words, e.g. "<a href="http://www.shelfari.com/glossary/grosstopically">grosstopically</a>" and "<a href="http://archives.dawn.com/archives/13250">toppelganger</a>", make so much sense. I almost wish I lived in his cleaved world of seeing and unseeing, just so I could use them.</p> <p>I'm reading another book of his, <a href="http://www.amazon.co.uk/gp/product/B004WE003C?ie=UTF8&#x26;camp=1634&#x26;creativeASIN=B004WE003C&#x26;linkCode=xm2&#x26;tag=houseofmoran-21">Embassytown</a>, right now. It is more outright Science Fiction, and is <em>spattered</em> with new words. A main subject of the book is language, so this richness makes sense in this context, but I imagine I would grow sick of it if the usage wasn't so relevant.</p> <p>I seem to be into a 'divided city' shtick this holiday, as I also read <a href="http://www.amazon.co.uk/gp/product/1770460713?ie=UTF8&#x26;camp=1634&#x26;creativeASIN=1770460713&#x26;linkCode=xm2&#x26;tag=houseofmoran-21">Jerusalem</a> by <a href="http://en.wikipedia.org/wiki/Guy_Delisle">Guy Delisle</a>. A lot of it is just day-to-day errands and looking after his kids; not surprising, given it's basically a diary. However, it is leavened by the many WTF moments when he encounters another bizarre behaviour of the locals. The strange but rigid rules of movement in <a href="http://www.amazon.co.uk/gp/product/B003E2UQLO?ie=UTF8&#x26;camp=1634&#x26;creativeASIN=B003E2UQLO&#x26;linkCode=xm2&#x26;tag=houseofmoran-21">The City &#x26; The City</a> seem pedestrian in comparison to the complex enforcements in place in Israel and Palestine.</p> <p>Delisle isn't primarily there for journalistic purposes; he mostly just happens to be there with his wife, who works for <a href="http://www.msf.org/">MSF</a>. This make Delisle a lot softer than other authors, like <a href="http://www.amazon.co.uk/gp/product/0224069829?ie=UTF8&#x26;camp=1634&#x26;creativeASIN=0224069829&#x26;linkCode=xm2&#x26;tag=houseofmoran-21">Sacco</a>. I find it hard to read more than one of <a href="http://www.amazon.co.uk/Joe-Sacco/e/B001K7T7NI">Sacco's books</a> in quick succession. They are lively, in-depth, but simply too depressing.</p> <p>However, I haven't read one of Sacco's in a while, so it may be time to spend more holiday money on Amazon ... recommendations?</p><![CDATA[Boomeranging returns]]>https://www.houseofmoran.com/post/22963380829/boomeranging-returnshttps://www.houseofmoran.com/post/22963380829/boomeranging-returnsSun, 13 May 2012 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/7187506944/" title="A Grand Day Out by MikeMoran, on Flickr"><img src="http://farm6.staticflickr.com/5160/7187506944_27f78fc3c2.jpg" width="500" height="299" alt="A Grand Day Out"></a></p> <p>Yesterday, I went out with Nils and threw my boomerangs for the first time in 10 years. It was really cool, not least because Nils decided to go get them for me, unbidden! On a windy day like that it makes a big difference having someone fetching them.</p> <p>None of my boomerangs are suitable for Nils, so I've ordered some <a href="http://www.boomerangs.com/kids.html">online</a>. Apart from <a href="http://boomerangs.com">boomerangs.com</a> most of the sites seem to have been last updated when I stopped throwing!</p> <p>I'd be interested to hear of anyone else throwing boomerangs in Edinburgh, not least because I want to try out their 'rangs (see what I did there?).</p><![CDATA[LEDs in the rain]]>https://www.houseofmoran.com/post/22090683415/leds-in-the-rainhttps://www.houseofmoran.com/post/22090683415/leds-in-the-rainMon, 30 Apr 2012 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/7126394915/" title="IMAG0346 by MikeMoran, on Flickr"><img src="http://farm8.staticflickr.com/7254/7126394915_e8eb599bed.jpg" width="500" height="299" alt="IMAG0346"></a></p> <p>The <a href="http://speedoflight2012.org.uk/">NVA Speed of Light</a> practice session was the best time I've spent in the rain for a while! However, I am sooooo glad I bought myself a proper thermal top and rain jacket. Not cheap, but worth it.</p> <p>I really enjoyed myself tonight. I would love to have seen the faces of any passers-by stumbling upon the lines of led-encrusted runners, all trotting along like some sort of Alien Congo dance.</p> <p>It's a pity the weather meant we aborted practicing more of the moves on the crags for real, but hopefully there will be some free spaces in future training slots. Regardless, I can't think of a better reason to stand around wearing LEDs in the rain.</p><![CDATA[The hair, eet ees back ...]]>https://www.houseofmoran.com/post/20979832205/the-hair-eet-ees-backhttps://www.houseofmoran.com/post/20979832205/the-hair-eet-ees-backThu, 12 Apr 2012 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/7071693479/" title="Da hair #1 by MikeMoran, on Flickr"><img src="http://farm8.staticflickr.com/7256/7071693479_3b38b5d84e.jpg" width="500" height="375" alt="Da hair #1"></a></p> <p>... sort-of. As I had expected might happen, my <a href="https://www.alopecia.org.uk/Pages/FAQs/Category/types-of-alopecia">Alopecia</a> has receded and the patches that were bald before are now white. I'm gonna give it a go, as I'm happy having a bald head but to be honest I'd be happier not having to shave it every other day. However, I'm not gonna change my <a href="http://www.gravatar.com/avatar/0471bd275449e64fc43e4502e16ce93a.png">Gravatar</a> <em>just</em> yet.</p> <p>I took the photo above during our visit to the <a href="http://www.life.org.uk/">Newcastle Centre for Life</a>. <a href="http://www.carmenland.com/">Carmen</a> did the (excellent, if I may say so) illustrations for the <a href="http://www.life.org.uk/whats-on/events/naughty-monsters-explore-the-planets">"Naughty Monsters Explore the Planets"</a> planetarium show that just started recently.</p><![CDATA[La Grand Weekend, Gromit]]>https://www.houseofmoran.com/post/20741431957/la-grand-weekend-gromithttps://www.houseofmoran.com/post/20741431957/la-grand-weekend-gromitSun, 08 Apr 2012 00:00:00 GMT<p>On Friday, I had the opportunity to see <a href="http://en.wikipedia.org/wiki/Grand_Illusion_(film)">La Grand Illusion</a> at the Filmhouse,</p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 75%; position: relative; height: 0; overflow: hidden;" > <iframe src="http://www.youtube.com/embed/hctrYzVYmfM" frameborder="0" allowfullscreen style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>I can totally see why this film was <a href="http://en.wikipedia.org/wiki/Grand_Illusion_(film)#Europe">so hated</a> by the Nazis, because it portrays war as ultimately pointless. There is no great 'enemy' within these prison camps, on either side. There are only world-weary men waiting, and hoping, for the end to come.</p> <p>My only criticism is that the characters seem almost <em>too</em> humane; but perhaps this is my cynicism speaking. Regardless, it's a wonderful film that well lives up to expectation.</p> <p>If you like this film, then you may be interested in others from <a href="http://bldgblog.blogspot.co.uk/2012/01/breaking-out-and-breaking-in.html">'Breaking Out and Breaking In: A Distributed Film Fest of Prison Breaks and Bank Heists'</a>; don't worry too much about the timetable, I'm already three months behind.</p> <p>All change on Saturday for <a href="http://www.imdb.com/title/tt1430626/">"The Pirates! In an Adventure with Scientists!"</a>. It's been a while since I've seen an Aardman film, but thanks to cheap tickets via Hugh (thanks Hugh!) and a resounding answer of "YES" when I asked Nils, we went along.</p> <p>I'm beginning to think I'm very conservative when it comes to violence in kids films. <a href="http://www.imdb.com/title/tt1430626/">Pirates</a> isn't a particularly scary film, compared to some others, but it still has plenty of knives, killing (off-screen) and impending doom. Nils survived, and there were no nightmares, but he was keen to point out that he had to hide next to me <em>three times</em> during the film (perhaps this number should be a new indicator of scaryness?).</p> <p>I think I lolled three times and at one point Nils made a noise I've never heard before which was 20% anguish and 80% joy, so overall, a hit.</p> <p>I'm going to see <a href="http://www.imdb.com/title/tt0090605/">Aliens</a> on Tuesday, so this month is turning into a proper film-fest after months of nothing. Don't worry, I won't be taking Nils along to that one ;-)</p> <p>Finally, the weekend was rounded off on Sunday by searching for Easter eggs in the garden. The chocolate was very nice, but the "Easter Bread" made by Carmen was even better (it's like Mr Kiplings Exceedlingly Good cakes, but with the marsipan top spread liberally <em>throughout the bread</em>). Carmen claims she made it a bit too sweet, by accident. I can live with these mistakes.</p><![CDATA[You've never had it so good]]>https://www.houseofmoran.com/post/19828963519/youve-never-had-it-so-goodhttps://www.houseofmoran.com/post/19828963519/youve-never-had-it-so-goodSat, 24 Mar 2012 00:00:00 GMT<p><a href="http://michaelfoody.com/?p=4">What's the opposite of Nostalgia?</a> Nowadays, I can think of an idea, code it up and have it on heroku in minutes. Working at a <a href="http://investing.businessweek.com/research/stocks/private/snapshot.asp?privcapId=9530711" title="NetPhysic">start-up in 2001--2004</a> was somewhat different.</p> <p>Back then, the first task was to decide which of the many (over-priced) Cisco routers you should stick in your closet. The people at our <a href="http://www.scolocate.com/" title="ScoLocate">service provider</a> were all friendly and helpful, but the idea of personally visiting your boxes now seems mildly archaic.</p> <p>Going with a cloud-based provider is still not a trivial choice. Little sysadmin-level expertise within-company means you are more beholden to AWS/Azure/Who-ever to keep your service running. Security and trust are issues to be settled, but it's a welcome choice to be able to spend on your unique selling points.</p> <p>In summary: you've never had it so good.</p> <p>p.s. We also had to sweep the lake.</p><![CDATA[Beach Facts]]>https://www.houseofmoran.com/post/19450749467/some-things-established-today-on-the-beach-thehttps://www.houseofmoran.com/post/19450749467/some-things-established-today-on-the-beach-theSat, 17 Mar 2012 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/6844129232/" title="IMAG0201 by MikeMoran, on Flickr"><img src="http://farm8.staticflickr.com/7210/6844129232_7f21e3edab_m.jpg" width="144" height="240" alt="Beach Facts" style="float: left; margin-right: 10px; margin-bottom: 5px;"></a></p> <p>Some things established today on the beach:</p> <ul> <li>The statutory countdown sequence for throwing stones is "3, 2, 1, &#x3C;throw>", and not "10, 9, ... 1, 0" which is reserved for Rockets.</li> <li>It is surprisingly hard to guide water pools to the sea.</li> <li>Nils didn't do anything interesting, and wanted just to pretend he was pushing a car (rock) through snow (sand), but he enjoyed himself anyway.</li> </ul><![CDATA[Normal service will resume ...]]>https://www.houseofmoran.com/post/19177902958/normal-service-will-resumehttps://www.houseofmoran.com/post/19177902958/normal-service-will-resumeMon, 12 Mar 2012 00:00:00 GMT<p>You may have noticed some blog posts are missing. This is because I am migrating them across gradually from my old blogging system to Tumblr.</p> <p>Also, the RSS feed for tumblr (which I use on the main site) takes a <em>super-long</em> time to update; may have to work round that.</p> <p>S'all</p><![CDATA[Note to self: do not invent time machine]]>https://www.houseofmoran.com/post/17724723635/note-to-self-do-not-invent-time-machinehttps://www.houseofmoran.com/post/17724723635/note-to-self-do-not-invent-time-machineThu, 16 Feb 2012 00:00:00 GMT<p>If I did have a time machine, I'd be spending a lot of my life getting slapped in the face by my future self.</p> <p>Last week I spent far too long debugging why Heroku was refusing to accept my rails app when I did a "<code>git push heroku master</code>". I had all sorts of theories and learned about the <a href="https://www.google.com/search?q=Heroku+push+rejected,+no+Cedar-supported+app+detected+3.0.5&#x26;hl=en&#x26;qscrl=1">various reasons</a> Heroku has for saying "Heroku push rejected, no Cedar-supported app detected". The actual reason? I was on a local git branch and Heroku was being pushed to from my master branch, which was not a rails app.</p> <p>SLAP!</p> <p>Incidentally, future Mike, if you do want to push from a non-master branch (e.g. "stuff"), then do this:</p> <pre><code>git push heroku stuff:master </code></pre><![CDATA[Glasgow Science Centre Visit]]>https://www.houseofmoran.com/post/17678673294/glasgow-science-centrehttps://www.houseofmoran.com/post/17678673294/glasgow-science-centreWed, 15 Feb 2012 00:00:00 GMT<p><a title="View 'Spinning disks (grrr, for not rotating the camera)' on Flickr.com" href="http://www.flickr.com/photos/96305352@N00/6883470251"><img style="float: left; margin-right: 10px;" title="Spinning disks (grrr, for not rotating the camera)" src="http://farm8.staticflickr.com/7037/6883470251_12ff122919_m.jpg" border="0" alt="Spinning disks (grrr, for not rotating the camera)" width="144" height="240" /></a></p> <p>Once again, simple physics wins against ambitious simulations on computer displays.</p> <p>For example, we briefly played with an illustration of a red/cyan <a href="http://en.wikipedia.org/wiki/Anaglyph_image">Anaglyph</a>. It allowed some very simple computer models (e.g. a box, a molecule) to be rotated on-screen and viewed through glasses. However the refresh rate was abysmal and overall the interface was not responsive. Nils' attention was lost in seconds.</p> <p>In this high-distraction environment, you need to immediately show or do <strong>something</strong>, even if it's not the main feature.</p> <p>My favourite display of the whole day was a rotating disk on which you could place plastic wheels. If you let them spin up in the right way, and then let go, they'll stay in the same place for a surprisingly long time. Even when they start drifting off, they can orbit a few times in interesting ways, before eventually flying off. And when they fly off, you just <em>have</em> to have another go.</p> <p>In these physics-only displays, if you do come up with a cunning workaround or variation, reality is ready to simulate it perfectly, and reward your ingenuity.</p><![CDATA[Getting in the holiday mood]]>https://www.houseofmoran.com/post/19145407556/getting-in-the-holiday-moodhttps://www.houseofmoran.com/post/19145407556/getting-in-the-holiday-moodMon, 26 Dec 2011 00:00:00 GMT<p>Got in the holiday mood last night by watching the film of <a href="http://en.wikipedia.org/wiki/The_Road">The Road</a>. This is right up there with "Grave of the Fireflies" on the brilliant-but-sad scale (see <a href='http://blog.houseofmoran.com/day/2008/03/22'>2008-03-22</a>).</p><![CDATA[That's it, all gone!]]>https://www.houseofmoran.com/post/17731990650/thats-it-all-gonehttps://www.houseofmoran.com/post/17731990650/thats-it-all-goneSun, 20 Nov 2011 00:00:00 GMT<p>Those of you who've seen me around recently will have noticed a gradual disappearance of hair on my left side. This was accompanied by a gradual <em>increase</em> in attempts to make a comb-over look like a real haircut. No more.</p> <p>About a year ago I started developing a small bald patch on each side of my head. This developed into a <em>large</em> patch on one side. I got this diagnosed as <a href="https://www.alopecia.org.uk/Pages/FAQs/Category/types-of-alopecia">Alopecia Areata</a>. See the <a href="https://www.alopecia.org.uk/Pages/FAQs/Category/types-of-alopecia">BAD</a> website for details, but in summary, it's an Auto-Immune disease that attacks my hair follicles, causing them to fall out. It's not uncommon, but it is still annoying, particularly because it's <em>possible</em>, <em>maybe</em>, <em>cross your fingers</em>, that it'll grow back. And it has. In patches. S l o w l y.</p> <p>Today I noticed a large area missing on the <em>other side</em>. So, enough is enough, a stereo comb-over is <em>definitely</em> not sustainable. I declare 20/11/2011 an auspicious day to shave all my hair off!</p> <p>Let's not forget, there are many advantages to having a shaved head:</p> <ol> <li>I can realise massive savings on shampoo.</li> <li>I have a <a href="http://basicinstructions.net/">web-comic</a> all about me.</li> <li>I can be mistaken for <a href="http://en.wikipedia.org/wiki/Zed_Shaw">Zed Shaw</a>; ok, maybe not a benefit.</li> <li>It is impossible to catch head-lice (disclaimer: only advantageous if you have a child)</li> </ol> <p>... and so on, the list is endless!</p> <p>Here's what I look like now (I took this just after I shaved it all off):</p> <p><a href="http://www.flickr.com/photos/schnickschnack/6631377425/" title="New Year, new picture by MikeMoran, on Flickr"><img src="http://farm8.staticflickr.com/7146/6631377425_dd0589c4f4.jpg" width="500" height="500" alt="New Year, new picture"></a></p><![CDATA[Frazzled]]>https://www.houseofmoran.com/post/19369684214/frazzledhttps://www.houseofmoran.com/post/19369684214/frazzledSun, 28 Aug 2011 00:00:00 GMT<p>Totally frazzled. Between work, festival, and home-life, I've been burning the candle at three ends. It's been good though. Hopefully, when I regain some energy, I'll write-up what I saw that's worth shouting about. However, for now, I hereby declare my festival: OVER.</p><![CDATA[EIFF top picks]]>https://www.houseofmoran.com/post/19369912981/eiff-top-pickshttps://www.houseofmoran.com/post/19369912981/eiff-top-picksSun, 10 Jul 2011 00:00:00 GMT<p>Despite overly expensive films and the usual EIFF website broken-ness, I managed to see a few films this year.</p> <p>There were five shorts in <a href="https://www.google.co.uk/search?ie=UTF-8&#x26;q=Mapping+the+Extraordinary+eiff">Mapping the Extraordinary</a>. All were good, but these three make me we want to see more from the directors:</p> <p><em><a href="http://www.imdb.com/title/tt1866218/">Pentecost</a> by Peter McDonald</em></p> <p><div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 62.32142857142857%; position: relative; height: 0; overflow: hidden;" > <object style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></object> </div> </div><param name="movie" value="http://www.youtube.com/v/Hobilcdk0Rc?version=3&hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Hobilcdk0Rc?version=3&hl=en_US" type="application/x-shockwave-flash" width="560" height="349" allowscriptaccess="always" allowfullscreen="true"></embed></object></p> <p>I suspect this will mean more to you if you had any sort of Catholic upbringing. The end is a righteous, well deserved, FU to the local church establishment. The football analogy was a little overplayed at times, but it didn't spoil it.</p> <p><em><a href="http://www.imdb.com/title/tt1647995/">Animal Control</a> by Kire Papput</em></p> <script type="text/javascript" src="http://en.sevenload.com/pl/oO1ukI0/500x314"></script><p>Link: <a href="http://en.sevenload.com/videos/oO1ukI0-Animal-Control-Kire-Papput"><img src="http://static.sevenload.net/img/sevenload.png" width="66" height="10" alt="Animal Control – Kire Papput" /></a></p> <p>The trailer doesn't do this justice. The very spare use of dialogue and the repetition of the same shots, with subtle but significant changes, build up nicely to illustrate the change in the inner life of the main character. </p> <p><em><a href="http://www.imdb.com/title/tt1719631/">Six Strands</a> by Chaitanya Tamhane</em></p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 75%; position: relative; height: 0; overflow: hidden;" > <iframe src="http://player.vimeo.com/video/18051845?title=0&amp;byline=0&amp;portrait=0" frameborder="0" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe><p><a href="http://vimeo.com/18051845">Six Strands Trailer</a> from <a href="http://vimeo.com/user5542414">Chaitanya Tamhane</a> on <a href="http://vimeo.com">Vimeo</a>.</p> </div> </div> <p>Though just a short, the story is well-developed and deep. It leaves you satisfied and wanting to return and watch it again.</p> <p>The only main feature I saw was <a href="http://www.imdb.com/title/tt1630027/">Almanya, Welcome to Germany:</a></p> <div> <div class="gatsby-resp-iframe-wrapper" style="padding-bottom: 61.25000000000001%; position: relative; height: 0; overflow: hidden;" > <iframe title="Distrify video player" id="distrify-player-46" class="distrify-player" type="text/html" src="http://widgets.distrify.com/widget.html#46" frameborder="0" scrolling="no" style=" position: absolute; top: 0; left: 0; width: 100%; height: 100%; "></iframe> </div> </div> <p>This had me laughing for half of it and with a lump in my throat the rest of the time. If you've ever stayed in Germany for any length of time then I'm sure you'll recognise some of their reactions (particularly to the food). Not only is this a great story with emotional depth, it's also cleverly told. I'm definitely buying this on DVD.</p><![CDATA[Taking R for a drive]]>https://www.houseofmoran.com/post/19370104961/taking-r-for-a-drivehttps://www.houseofmoran.com/post/19370104961/taking-r-for-a-driveMon, 04 Jul 2011 00:00:00 GMT<p>I've been playing with data from the <a href='http://www.houseofmoran.com/Project365'>Project365</a> group I am a member of. I would usually do this analysis using some combination of perl, ruby, and unix shell (sort, uniq etc). This time I thought I'd stretch myself a bit.</p> <p><a href="http://www.amazon.co.uk/Action-Data-Analysis-Graphics/dp/1935182390"><img src="http://ecx.images-amazon.com/images/I/418C5bStPcL._SL500_AA200_.jpg" style="float: left; margin-right: 5px" /></a></p> <p><a href="http://www.amazon.co.uk/R-Cookbook-Paul-Teetor/dp/0596809158"><img src="http://ecx.images-amazon.com/images/I/51ZWUV2DEyL._SL500_AA200_.jpg" /></a></p> <p>These are the two books I've been using to learn <a href="http://www.r-project.org/">"R"</a>. Why R? Apart from being 'interesting' to google for, "R" is distinguished by often popping up on the visualisation blogs I subscribe to. It also offers another way to slice and dice data. Although I can achieve some of these things in a combination of Excel and shell, it always feels very brittle and throwaway. R offers the hope of some re-usability, or at least, repeatability.</p> <p>Taking the <a href='http://www.houseofmoran.com/Project365'>Project365</a> data as a driving example, I plunged into learning R.</p> <p>From a first pass, "R" is definitely 'new Lego': lots of large pre-formed parts that look great, when they fit. However, it doesn't really feel like a cohesive language. For example, what do you think <code>as.vector()</code> does? It sounds like it should always return a vector, yes? Nope, it <em>tries its best</em>, and if it doesn't work, well, then you get back what you put in. There may be a perfectly valid reason for this, but it still feels 'perly'. I like my languages to tell me when something hasn't worked.</p> <p>If you follow along with the documentation, then you can get a lot done. However, I found myself often falling flat whenever I tried to generalise; it did not follow the principal of least surprise.</p> <p>There is power there but it is often frustrating getting to it. I'm going to leave it for a bit before I dive back in.</p><![CDATA[No Java, no Eclipse]]>https://www.houseofmoran.com/post/19370377212/no-java-no-eclipsehttps://www.houseofmoran.com/post/19370377212/no-java-no-eclipseFri, 07 Jan 2011 00:00:00 GMT<p>This is the first time I've been on holiday in Germany and not launched Eclipse. Also: not a single line of Java. It's refreshing.</p> <p>I now know I can write incredibly slow Ruby, albeit for a good cause (<a href="http://www.houseofmoran.com/DiagonalMethodVersusTheRuleOfThirds">"The Diagonal Method vs. The Rule of Thirds"</a>). I rediscovered a love for Unix. I finally admit: maybe this Rails thing is quite good, and: git is better than svn.</p> <p>Oh ye, and I got loads of presents ;-)</p><![CDATA[Aim Low]]>https://www.houseofmoran.com/post/19370652685/aim-lowhttps://www.houseofmoran.com/post/19370652685/aim-lowSat, 01 Jan 2011 00:00:00 GMT<a style="float: left; margin-right: 5px;" href="http://nedroid.com/2010/12/annual-regrets-day/"> <p><img src="http://farm6.static.flickr.com/5001/5359877179_a63e7467d6_o.png" title="The Most Excellent Nedroid" /></a></p> <p>The key to achieving a New Years resolution seems to be to aim low and then forget about it. </p> <p>Wired magazine has always been high on style and low on content. This didn't stop me from buying it once every few months. Not only that, but reading about geeks doing cool stuff was actually consuming the time <em>I</em> could be doing, well, <em>something</em>. My one and only resolution was to give up buying Wired magazine for a year.</p> <p>Standing in the airport looking at another puff-piece cover story powered by garish American enthusiasm, I realised: I'd made it.</p> <br style="clear: left" /><![CDATA[Waterstones is a Charity]]>https://www.houseofmoran.com/post/19481550636/waterstones-is-a-charityhttps://www.houseofmoran.com/post/19481550636/waterstones-is-a-charitySun, 17 Oct 2010 00:00:00 GMT<p><a href="http://www.amazon.co.uk/Art-Digital-Photography-John-Hedgecoe/dp/1405340932"><img style="float:left" src="http://ecx.images-amazon.com/images/I/51npe7cBAaL._AA330.jpg" /></a>Waterstones: £18.99. Amazon: £11.89, free delivery. This is one of the books I flipped through whilst sitting in the Starbucks. I may never buy this book, but if I do, I'm not paying an extra 7 quid out of the goodness of my heart. I feel a little bit guilty for writing this, as they let me flip through it without first purchasing it. But hey, maybe that's a quid max of guilt money I'd pay.</p> <p>I don't feel too sorry for Waterstones, as they've always had a large amount of crappy books. However, I really value Blackwells, particularly the one on North Bridge. Being in a physical bookshop gives you a chance to peruse through the whole book, which you still can't get online. Maybe I'm a little old-fashioned, but I like being surrounded by books. Blackwells gives me that, and I'm willing to pay a little, but not a lot, over the minimum to prop up the institution.</p> <p>We are surely in a transitionary period. At least two other tables in Waterstones had someone reading from an iPad. Next time, I'll look out for kindles. How long before bookshops like this can only afford to carry mainstream pap that punters off the street will buy who can't or won't look up the price online?</p><![CDATA[Today, I accidentally ran 10k]]>https://www.houseofmoran.com/post/19481663065/today-i-accidentally-ran-10khttps://www.houseofmoran.com/post/19481663065/today-i-accidentally-ran-10kSat, 09 Oct 2010 00:00:00 GMT<p>It started as a 5k <a href="http://www.runforburma.org/">run for burma</a> in Inverleith park. After a frantic ride on my bike to make registration, I started at 11. We looped round a couple of times and I passed the steward, who said "go right if you've seen me twice". I couldn't remember seeing her in particular, but it felt about right. I ran on and, curious about my time, checked my phones <a href="http://www.sportypal.com/">SportyPal app</a>. Unfortunately, it said I had only ran 1.86km. Shit.</p> <p>I dutifully turned around, passed by the steward again, and trudged off for another few laps, wondering how the hell I'd managed to do 5k in half an hour <a href="http://www.walkjogrun.net/routes/current_route.cfm?rid=459B5035-D6C0-E6A4-BF4873E128051D09">only a few weeks previously</a>. I finally finished about thirty minutes later, feeling quite embarrassed as I ran past people already heading home.</p> <p>What I didn't know, is that <a href="http://www.sportypal.com/Workouts/Embed/700107">my app had stopped at 1.86km</a>. <a href="http://www.walkjogrun.net/routes/current_route.cfm?rid=A01DD562-054E-9500-8474067A5C67C917">One time around Inverleith park</a> is just under 2km. I had <a href="http://www.walkjogrun.net/routes/current_route.cfm?rid=9308D3B8-A0D0-9CFF-C5F6D69582E754F0">done closer to four or five times around</a>.</p> <p>What's the lesson from this story? That I can run 10k without realising it, or that I put far too much trust in electronic devices?</p><![CDATA[Who was in Tron and Babylon 5?]]>https://www.houseofmoran.com/post/19481732278/who-was-in-tron-and-babylon-5https://www.houseofmoran.com/post/19481732278/who-was-in-tron-and-babylon-5Mon, 04 Oct 2010 00:00:00 GMT<p>More specifically, how can I find this out using freebase? Turns out the steps you <em>should</em> take are:</p> <ol> <li> <p>Find <a href="http://www.freebase.com/view/en/tron">the film you want to use as a constraint</a>.</p> </li> <li> <p>Slap <a href="http://tinyurl.com/2vxkoem">the film id and type as constraints into the query editor, using "*": null to get all properties of that type</a>.</p> </li> <li> <p>Expand your query <a href="http://tinyurl.com/379k7x3">until you find the actor somewhere within the tree</a> (keep on using <code>"*": null</code> at each level down to get more detail)</p> </li> <li> <p>Select the actor leaf in the query and <a href="http://tinyurl.com/2b4etba">use "Turn inside out" to arrange the query so that it will return actors constrained by film</a>.</p> </li> <li> <p>Repeat the above for the tv series</p> </li> <li> <p>Combined the film and tv series constraints into one query.</p> </li> <li> <p>Voila, you have <a href="http://tinyurl.com/26bv2bz">all actors who appeared in Tron and Babylon 5</a>.</p> </li> </ol> <p>You can easily extend this to do things like <a href="http://tinyurl.com/34e6sqx">finding all Science Fiction films that anyone in Babylon 5 has starred in</a>.</p> <p>What you definitely <em>shouldn't</em> do is:</p> <ol> <li> <p>Find the MQL documentation</p> </li> <li> <p>Read it</p> </li> <li> <p>Wonder why you need to know so much about type theory</p> </li> </ol> <p>Now, <em>that</em> was a wasted hour. Honestly, just go straight to the Query Editor. You know it makes sense.</p><![CDATA["How can I tell which of these damn tabs is making a sound?"]]>https://www.houseofmoran.com/post/19518296083/how-can-i-tell-which-of-these-damn-tabs-is-makinghttps://www.houseofmoran.com/post/19518296083/how-can-i-tell-which-of-these-damn-tabs-is-makingWed, 18 Aug 2010 00:00:00 GMT<p>Hmm, I'm out two for two on random summer holiday projects. First, the <a href="http://twitter.com/mike_moran/status/21445879593">hadoop quickstart example doesn't reduce</a>. Now, my idea to list what tabs in Chrome are making a noise is also a non-starter. Seems <a href="http://ask.metafilter.com/79855/How-can-I-tell-which-of-these-damn-Firefox-tabs-is-making-a-sound"> I'm not alone in wanting this</a>. It's pretty trivial to make a Chrome extension, quite nice in fact, but there seems to be no api to help find what tabs contain something which is making a sound.</p> <p>In general, anything other than YouTube which makes a noise in my browser pisses me off. Even then, you can have the problem of re-opening a bunch of restored tabs and having to hunt down the one playing that video you watched two weeks ago and forgot to close the tab of. It doesn't happen often, but when it does, it's pretty damn annoying.</p> <p>I was hoping for one central point that everything went through to play sound, but the answer to that may be 'the operating system'. That's a little too gross a level. I want those tabs, dammit.</p><![CDATA[Segway tour of Berlin]]>https://www.houseofmoran.com/post/19518400506/segway-tour-of-berlinhttps://www.houseofmoran.com/post/19518400506/segway-tour-of-berlinMon, 09 Aug 2010 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/4893390973/" title="53/365 by MikeMoran, on Flickr"><img src="http://farm5.static.flickr.com/4143/4893390973_6fbec7c5ee_m.jpg" width="240" height="240" alt="53/365" style="float: left; margin-right: 10px;" /></a> The Segway has always intrigued me. Even after the <a href="http://www.youtube.com/watch?v=DuwLVOPtQeg">overblown hype of 2001</a> died away.</p> <p>Given I was in Berlin, I took the chance to look like a dork and try out a <a href="http://citysegwaytours.com/berlin/tours/berlin-mini-segway-tour">Segway tour of the area</a>.</p> <p><em>How do you they drive them?</em> Simple answer, to go forward: lean on your toes, backwards: stick out your ass. Friends I talked to after were surprised that there really are no controls. There is <em>some</em> steering via an upright which you can move to turn. Even then, it is more of an indication; if you're stationary then a bend left means "turn on the spot", if moving forward, it produces a smooth turn, with the centre of the circle outside the machine.</p> <p>I've never ridden a horse but riding a Segway feels like I'd imagine it to be. You give it guidance, and it responds appropriately. Another example: the feedback to speeding is a slight push back on the upright so that it presses lightly against your stomach. It's subtle, but hard to ignore and the meaning is obvious. If you continue to speed (by leaning straight forward) then it'll refuse and go slower and slower until it stops. Again, a nice organic reaction: it is in a huff.</p> <p>Beware though, it can also bolt; the tour guide was at pains to point out that it will continue forward if you leave it leaning a little when you get off. Here the animal illusion breaks down; even the stupidest horse would surely be better than this.</p> <p><a href="http://www.flickr.com/photos/schnickschnack/4908509442/" title="Untitled by MikeMoran, on Flickr"><img src="http://farm5.static.flickr.com/4138/4908509442_17da4dda03_m.jpg" width="180" height="240" alt="" style="float: right; margin-left: 10px;" /></a></p> <p>Would I use this for real, for commuting? My <a href="http://www.segway.com/individual/models/i2-commuter.php">Segway</a> was fun, but I was basically standing up, forever. Fat people would hate it. Here's a telling (translated) quote for the "mobile rescue" version on the <a href="http://www.segway.de/type-rettung.php">German site</a>:</p> <blockquote> <ul> <li>Comfort mats reduce fatigue occurring after standing for long</li> </ul> </blockquote> <p>The Segway <a href="http://en.wikipedia.org/wiki/Segway_PT#Restrictions_on_use">doesn't easily fit into any category</a> of existing vehicle. In the middle of Berlin we didn't look too out of place because of the smorgasborg of various transport options present. However, when on the road, we <a href="http://www.youtube.com/results?search_query=segway+vs.+bike&#x26;aq=f">interfered with bikes</a>. Whilst on the paths, we surprised pedestrians.</p> <p>This versatility is felt as a positive by the Segwayer (?), but just means everyone else is pissed off. In the better bike towns there is a clear demarcation between bike and non-bike areas; Berlin is a good example. The Segway breaks these legal (and social) rules. Once the shiny newness of it all wears off, this will become more obvious. Outside of the <a href="http://www.youtube.com/watch?v=VSWBcizzpKM">feel-good TED talk</a>, I don't see this as much more than a footnote in transport history.</p> <p>Also, given that it costs <del>£WeWontTellYouHowMuchWithoutAnAppointment</del> (<em>Update: you can of course find out the huge price on <a href="http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&#x26;field-keywords=segway">amazon</a></em>) , I don't see myself buying one anytime soon.</p> <p><em>Would I do it again?</em> Hell yes! Though, next time, I'll bring a lighter bag.</p><![CDATA[Festival goers + Bike = ...]]>https://www.houseofmoran.com/post/19518969459/festival-goers-bikehttps://www.houseofmoran.com/post/19518969459/festival-goers-bikeSat, 07 Aug 2010 00:00:00 GMT<p>Day six of Carmen and Nils being way and I've started talking to myself. The day after she left I went to work and realised, "shit, I've not talked to anyone for over twelve hours".</p> <p>In other time-based news, in one day I have gone from avoiding cycling into tourists to actively aiming for them. If you visited Edinburgh this year and had some arsehole on a bike go 'ping ping ping' on his bell and almost run you over, that was me. Or maybe, it was any other cyclist in Edinburgh at the moment. This is why I love the Festival.</p><![CDATA[Back on the road again ...]]>https://www.houseofmoran.com/post/19147723605/back-on-the-road-againhttps://www.houseofmoran.com/post/19147723605/back-on-the-road-againSat, 24 Apr 2010 00:00:00 GMT<p><a href="http://www.flickr.com/photos/schnickschnack/4547891498/" title="Back on the road again"><img class="article-top" src="http://farm5.static.flickr.com/4001/4547891498_4b008d6a4f.jpg" width="500" height="281" alt="IMG_0995_3" /></a></p> <p>And so, another german holiday ends. As always, there are regrets; I didn't get to wander around Berlin for long, I missed some nice german bread by staying in bed too long, etc. On the plus side, I got a regular (wonderful) lie-in, and made some solid progress on a programming project (not as interesting to link to as LSystems).</p> <p>What have I been reading?</p> <p><a href="http://www.amazon.com/dp/1563899809"><img style="float: left; margin-right: 5px;" src="http://ecx.images-amazon.com/images/I/51WESsvXhxL._SX150_.jpg" /></a> What would you do if you were the last man on earth? Get beat up by women seems to be one answer. Flashbacks back and forth are cute but a little annoying, though used to good effect to set it all up; very cinematic. The story is so-so, but this simplicity means that I'm going to buy the german version to help me get some reading practise.</p> <br style="clear: both" /> <p><a href="http://www.amazon.de/Fahrenheit-451-Graphic-Ray-Bradbury/dp/3821861061"><img style="float:left; margin-right: 5px;" src="http://ecx.images-amazon.com/images/I/51j6ZVjSkbL._SX150_.jpg" /></a> Which brings me to this one. It is <em>way</em> too much for my current german reading level. It took me about 10 minutes to get through the first couple of pages with a dictionary next to me. Admittedly, there is a lot of setup text before we get into the main story, but even so, I need that setup! Currently on loan to a family friend in Germany. Will try again later!</p> <br style="clear: both" /> <p><a href="http://www.amazon.de/Liebe-schaut-weg-Line-Hoven/dp/3938511664"><img style="float:left; margin-right: 5px;" src="http://ecx.images-amazon.com/images/I/51BZMF1JM6L._SX150_.jpg" /></a> Liebe Schaut Weg (Love looks away) is more my level; it has little text and only half of it is in german, mostly uttered by children! It's a simple biography of the authors American and German roots. As a story, there isn't much drama, and so you aren't really drawn in. The drawing style is subtle and the textures are just very nice. Overall, a relaxing nice book, but wouldn't have been too disappointed to miss it. </p> <br style="clear: both" /> <p><a href="http://www.amazon.com/Museum-Vaults-Excerpts-Journal-Expert/dp/1561635146"><img style="float:left; margin-right: 5px;" src="http://ecx.images-amazon.com/images/I/518CWBQyezL._SX150.jpg" /></a> This is my pick of the holiday, and not just because it's all in english! There are touches of M.C.Escher here in style and recursiveness of the story. It's an investigation into the depths of The Louvre, told from the viewpoint of a newly-arrived cataloguer of artifacts. No garish colours here, just challenging perspectives, I recommend a <a href="http://www.amazon.com/reader/1561635146?_encoding=UTF8&#x26;ref_=sib_dp_pop_sup&#x26;page=random#reader-link">look inside</a> to see what I mean.</p> <br style="clear: both" /> <p><a href="http://www.amazon.com/Many-Friends-Does-Person-Need/dp/0571253423"><img style="float:left; margin-right: 5px;" src="http://ecx.images-amazon.com/images/I/51CMXlkmRmL._SX150_.jpg" /></a> I've got a <a href="/Review_of_How_Many_Friends_Does_One_Person_Need">fuller review of this</a> but in summary: interesting but I prefer The Human Story.</p> <br style="clear: both" /><![CDATA[LSystem Sunday]]>https://www.houseofmoran.com/post/19147340835/lsystem-sundayhttps://www.houseofmoran.com/post/19147340835/lsystem-sundayMon, 08 Mar 2010 00:00:00 GMT<p>It's LSystem Sunday! I was curious about investigating an assertion that I'd made the other day: that the dragon curve loops back and traces over itself. Turns out, I was talking nonsense:</p> <table> <tr> <td> <img src="http://lsystems.houseofmoran.com/FX:X->X+YF+,Y->-FX-Y:FXY/1.0-90.0-7.150x150.png" /> </td> <td> <img src="http://lsystems.houseofmoran.com/FX:X->X+YF+,Y->-FX-Y:FXY/1.0-90.0-7.150x150.animOver70s.gif" /> </td> </tr> </table> <p>The above shows the dragon curve at it's 7th expansion, with an animation of how this is drawn on the right. As you can see, it has overlapping points, but not overlapping line segments. I was wrong.</p> <p>Btw, yes, I know, but today is still logical Sunday for me. </p> <p>Note: animated gif rendering supported by <a href="http://elliot.kroo.net/software/java/GifSequenceWriter/">http://elliot.kroo.net/software/java/GifSequenceWriter/</a></p> <p>Btw, <a href="http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features">doing conditional GET</a> in <a href="https://jersey.dev.java.net/">Jersey</a> using <a href="http://www.mnot.net/blog/2007/08/07/etags">ETags</a> is piss-easy. Combine this with <a href="http://httpd.apache.org/docs/2.2/caching.html">apache server-side caching</a> and you have a very nice persistent caching solution. I can now do some pretty inefficient LSystem drawing without worrying about my server melting ;-) For example:</p> <img style="float: left" src="http://lsystems.houseofmoran.com/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-16.150x150.animOver180s.gif" /> <img style="float: left" src="http://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-4.150x150.animOver180s.gif" /> <img style="float: left" src="http://lsystems.houseofmoran.com/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-8.150x150.animOver180s.gif" /><![CDATA[LSystem Sunday: Does Dragon Curve trace over itself?]]>https://www.houseofmoran.com/post/2010-03-08https://www.houseofmoran.com/post/2010-03-08Mon, 08 Mar 2010 00:00:00 GMT<p>It's LSystem Sunday! I was curious about investigating an assertion that I'd made the other day: that the dragon curve loops back and traces over itself. Turns out, I was talking nonsense:</p> <table> <tr> <td> <img src="/projects/lsystems/FX:X->X+YF+,Y->-FX-Y:FXY/1.0-90.0-7.400x400.jpg" /> </td> <td> <img src="/projects/lsystems/FX:X->X+YF+,Y->-FX-Y:FXY/1.0-90.0-7.400x400.animOver70s.gif" /> </td> </tr> </table> <p>The above shows the dragon curve at it's 7th expansion, with an animation of how this is drawn on the right. As you can see, it has overlapping points, but not overlapping line segments. I was wrong.</p> <p>Btw, yes, I know, but today is still logical Sunday for me.</p> <p>Note: animated gif rendering supported by <a href="http://elliot.kroo.net/software/java/GifSequenceWriter/">http://elliot.kroo.net/software/java/GifSequenceWriter/</a></p> <p>Btw, <a href="http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features">doing conditional GET</a> in <a href="https://jersey.dev.java.net/">Jersey</a> using <a href="http://www.mnot.net/blog/2007/08/07/etags">ETags</a> is piss-easy. Combine this with <a href="http://httpd.apache.org/docs/2.2/caching.html">apache server-side caching</a> and you have a very nice persistent caching solution. I can now do some pretty inefficient LSystem drawing without worrying about my server melting ;-) For example:</p> <img style="float: left" src="/projects/lsystems/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-16.200x200.animOver180s.gif" /> <img style="float: left" src="/projects/lsystems/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-4.200x200.animOver180s.gif" /> <img style="float: left" src="/projects/lsystems/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-8.200x200.animOver180s.gif" /> <hr/><![CDATA[LSystem Distractions]]>https://www.houseofmoran.com/post/19146932825/lsystem-distractionshttps://www.houseofmoran.com/post/19146932825/lsystem-distractionsSun, 28 Feb 2010 00:00:00 GMT<p>LSystems have once-again distracted me, this time from German homework:</p> <img style="float: left" src="http://lsystems.houseofmoran.com/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-16.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-4.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-8.150x150.png" /> <hr style="clear: both;" /> <img style="float: left" src="http://lsystems.houseofmoran.com/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-8.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-4.150x150.png" /> <hr style="clear: both;" /> <img style="float: left" src="http://lsystems.houseofmoran.com/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-2.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-2.150x150.png" /> <img style="float: left" src="http://lsystems.houseofmoran.com/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-2.150x150.png" /> <hr style="clear: both;" /><![CDATA[LSystems distractions]]>https://www.houseofmoran.com/post/2010-02-28https://www.houseofmoran.com/post/2010-02-28Sun, 28 Feb 2010 00:00:00 GMT<p>LSystems have once-again distracted me, this time from German homework:</p> <img style="float: left" src="/projects/lsystems/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-16.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-4.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-8.200x200.jpg" /> <hr /> <img style="float: left" src="/projects/lsystems/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-8.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-3.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-4.200x200.jpg" /> <hr /> <img style="float: left" src="/projects/lsystems/FX:X-%3EX+YF+,Y-%3E-FX-Y:FXY/1.0-90.0-2.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/F:F-%3EFF+(+F-F-F)-(-F+F+F):F/1.0-25.0-2.200x200.jpg" /> <img style="float: left" src="/projects/lsystems/L:L-%3E+R-L-R+,R-%3E-L+R+L-:LR/1.0-60.0-2.200x200.jpg" /> <hr /><![CDATA[More arsing around with Scala]]>https://www.houseofmoran.com/post/17732462119/more-arsing-around-with-scala-this-time-tryinghttps://www.houseofmoran.com/post/17732462119/more-arsing-around-with-scala-this-time-tryingTue, 07 Jul 2009 00:00:00 GMT<p>More arsing around with Scala. This time, trying to reimplement <a href="http://lesscss.org">lesscss</a>. This is about two hours worth of hacking:</p> <pre><code>object LessParser extends RegexParsers { def parse(spec: String) : Sequence = { parseAll(sequence, spec) match { case Success(l, _) => l case Failure(m, _) => throw new IllegalArgumentException(m) case Error(m, _) => throw new IllegalArgumentException(m) } } def sequence = rep(namedNested | atom) ^^ { Sequence(_) } def namedNested = nestedName~"{"~rep(atom)~"}" ^^ { case name~"{"~contents~"}" => NamedNested(name, contents) } def nestedName = """[\.\#][a-zA-Z]+""".r def atom = variableDef | variableUse | text def text = "[^@{}]+".r ^^ { Text(_) } def variableDef = "@"~variableName~":"~variableValue~";" ^^ { case "@"~name~":"~value~";" => VariableDef(name, value) } def variableUse = "@"~variableName ^^ { case "@"~name => VariableUse(name) } def variableName = "[a-z-]+".r def variableValue = "[^;]+".r } abstract class Tree { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] } case class Sequence(parts: List[Tree]) extends Tree { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = { parts.foldLeft (defs) { (accumDefs : Map[String, String], part : Tree) => part.eval(accumDefs, out) } } } case class NamedNested(name: String, contents: List[Atom]) extends Tree { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = { out.append(name) out.append(" {") contents.foldLeft (defs) { (accumDefs : Map[String, String], part : Tree) => part.eval(accumDefs, out) } out.append("}") defs } } abstract case class Atom() extends Tree case class VariableDef(name: String, value: String) extends Atom { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = { defs + (name -> value) } } case class VariableUse(name: String) extends Atom { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = { out.append(defs(name)) defs } } case class Text(value: String) extends Atom { def eval(defs: Map[String, String], out: StringBuffer) : Map[String, String] = { out.append(value) defs } } object Less { def main(args : Array[String]) : Unit = { println(LessParser.parse("@nice-blue: #5B83AD;")) println(LessParser.parse("@nice-blue")) println(LessParser.parse("@nice-blue: #5B83AD; @nice-blue")) println(LessParser.parse("@nice-blue: #5B83AD; #header { background-color: @nice-blue; }")) var fullExample = """ @nice-blue: #5B83AD; #header { background-color: @nice-blue; } """ var buf = new StringBuffer LessParser.parse(fullExample).eval(Map(), buf) println(buf) } } </code></pre> <p>Output:</p> <pre><code>Sequence(List(VariableDef(nice-blue,#5B83AD))) Sequence(List(VariableUse(nice-blue))) Sequence(List(VariableDef(nice-blue,#5B83AD), VariableUse(nice-blue))) Sequence(List(VariableDef(nice-blue,#5B83AD), NamedNested(#header,List(Text(background-color: ), VariableUse(nice-blue), Text(; ))))) #header {background-color: #5B83AD; } </code></pre> <p>It does variables and the beginnings of mixins. It's actually quite lame e.g. it throws away whitespace. Hohum, time to learn more about parsers in Scala...</p><![CDATA[LSystem Explorations]]>https://www.houseofmoran.com/post/19146149332/lsystem-explorationshttps://www.houseofmoran.com/post/19146149332/lsystem-explorationsSat, 27 Jun 2009 00:00:00 GMT<p>So, another summer holiday is at an end, and another programming interval. This time I was using my <a href="http://www.flickr.com/photos/schnickschnack/sets/72157620457773888/">LSystem Explorations</a> as a way to get more practice with Scala and Android. </p> <p><em>Random aside</em>: I find it hard to get excited about non-JVM languages nowadays. I develop on a Mac and deploy to Linux, Windows (sometimes) and now Android. I really don't want to worry about whether the language or platform I'm using has native components hidden somewhere inside. I've spent enough time doing "./configure" in the past to be seriously bored with non-portability. That was even going between two <a href="http://www.binrev.com/forums/index.php?showtopic=16846&#x26;pid=155481&#x26;mode=threaded&#x26;start=">Unixes</a> (Solaris and Linux)! I know Java is really "write once, debug everywhere" (e.g. <a href="http://twitter.com/mike_moran/status/2325524583">Graphics2D problems on the Mac</a>), but at least these are problems in particular library features, not a total inability to run.</p> <p>Anyway, what have I learned? <em>Scala in Eclipse has become usable enough for me with the latest Eclipse plugin for me to use Scala as my main Programming Language</em>. It's still the case that the Scala builder gets confused too often and you have to do a Project->Clean. This even happens with pure Scala builds, and not just with mixed Java/Scala projects. The Editor integration is also flaky e.g. copy and paste between files can cause errors, and you can forget about consistently completing a Rename Refactor. However, even given all that, the ability to mix Scala and Java in one project is what really does it for me. Overall, it's still basic compared to the JDT. I don't yet want to push it for my day job, but for personal projects, where you can absorb the extra time fixing things if you break them, it's fine.</p> <p><em>Scala as a language is really growing on me</em>. As <a href="2009-06-17">previously mentioned</a>, I was working through the <a href="http://www.amazon.co.uk/Programming-Scala-Comprehensive-Step-Step/dp/0981531601">"Programming in Scala"</a> book. Even though Scala fundamentally has a small core, it has the appearance of a much larger language. I really needed to read most of this book to get past quite a few roadblocks, but I did manage it.</p> <p>For example, I'd looked at parser combinators before but found the examples posted at the time and the <a href="http://www.scala-lang.org/docu/files/api/scala/util/parsing/combinator/Parsers.Parser.html">scaladoc</a> impenetrable. This is not too surprising as operators in Scala appear as methods on the class, so class-level docs can't really tell you much about how to use them in context. The JSON example in the book was large enough to give me sufficient transferrable knowledge to write a simple parser for LSystem descriptions:</p> <pre><code>import scala.util.parsing.combinator._ object LSystemLanguage extends RegexParsers { // This parses "B; F -> FF, B -> F[+B]F[-B]+B; FB" into an LSystem def parse(spec: String) : LSystem = { parseAll(lSystem, spec) match { case Success(l, _) => l case Failure(m, _) => throw new IllegalArgumentException(m) case Error(m, _) => throw new IllegalArgumentException(m) } } def lSystem = axioms~";"~rules~";"~visible ^^ { case axioms~";"~rules~";"~visible => LSystem(axioms, rules, Set() ++ visible) } def rules = repsep ( rule, "," ) def rule = variable~"->"~rep( variable | constant ) ^^ { case lhs~"->"~rhs => new Rule(lhs, rhs) } def axioms = rep(element) def visible = rep(element) def element = variable | constant def variable = "[A-Z]".r ^^ ( (s : String) => { Var(s.charAt(0)) } ) def constant = ("[a-z]".r | literal("+") | literal("-") | literal("[") | literal("]") ) ^^ ( (s : String) => Constant(s.charAt(0)) ) } </code></pre> <p>Apologies for the probably non-idiomatic Scala (and lack of syntax-highlighting on this site, I'll upgrade one day, honest), but it has the important property that it works, as opposed to most of my previous attempts. From further reading elsewhere, I get the impression that they are papering over some details (the !RegexParser combines both tokenisation and parsing, which they don't cover separately from what I read of the book). However, who cares, it works!</p> <p>I'm now seriously considering supporting the full <a href="http://fractint.oblivion.cz/snoopy.l">Fractint</a> LSystem syntax, which I wouldn't have considered doing in Java. Obviously, you <em>can</em> do all this with JLex etc, but that means going back and forward between languages and probably, gack, writing an ant script. Seriously, I spent more time during my holiday getting a simple ant task to work than I did writing this parser.</p> <p>Modulo one instance where Eclipse crashed and I had to rebuild my workspace, programming in Scala using Eclipse has been fun. The combination of an object-functional language, a half-decent IDE and rich platform libraries is very powerful. It's important to emphasize what this can give you. For me it means that if I have a spare hour or so in which to add a new feature or tweak an existing one (like extending the parser) I'll consider doing it and expect to complete it, <em>and enjoy it</em>.</p> <p>Technically, I'm capable of getting the same feature implemented in Java, in combination with other tools. However, I'd start out with a big "harumph" as I picture the fields of verbosity laid out before me. It would definitely <em>not</em> be fun.</p> <p><em>This brings me to Android</em>. The Scala compiler spits out JVM bytecodes. The Android platform, though <a href="http://www.betaversion.org/~stefano/linotype/news/110/">not strictly a Java VM</a>, does claim to support Java class files. <em>Theoretically</em>, I should be able to write a library in Scala and use it on Android.</p> <p>I am explictly not trying to write an Android app in Scala. Instead, I created an LSystem library, written in Scala, which exposes itself solely through these interfaces:</p> <pre><code>public interface LSystemViewFactory { public LSystemView evaluate(String spec, double angle, int rounds); } public interface LSystemView { public void renderTo(Renderer renderer); } public interface Renderer { interface Point { double x(); double y(); } public void addPath(Iterable&#x3C;Point> path, int length); } </code></pre> <p>In this way, I was trying to avoid relying on any special help that could come from using one Scala project with another. It does work, in a way. </p> <p><em>Warning: what follows is a history of my stubborn depth-first method of getting something showing on my phone</em>. There may a better method.</p> <p>In Eclipse 3.4, you need only make an Android project depend on a Scala project and everything will compile. However, when you run it on the phone, it will be missing the required Scala class definitions. You can download the scala-library.jar and add it as a required library. The Dex compiler then starts churning away on this file, heating up your lap as a side-effect, and then fails with a compiler error. Schäde.</p> <p>There is some joojoo in "scala-library.jar" that the Dex compiler just doesn't like. I <em>think</em> it is an unsupported annotation of some kind, probably somewhere in scala.xml.transform, but since it takes a minute or so for dex to do its thang to this library, I decided to adopt a <a href="http://www.flickr.com/photos/schnickschnack/3643127325/in/set-72157620457773888/">slash and burn</a> approach, by quickly removing anything I knew I didn't need on the phone. So, goodbye to any of scala.actors, scala.reflect, scala.testing or scala.xml.transform.</p> <p><em>Random Aside</em>: it was at this point I had the <a href="http://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy_(radio_series)">afore-mentioned elbow injury</a>^H^H^H^H...problem with ant. It is <a href="http://twitter.com/mike_moran/status/2252171537">frustratingly hard</a> to get ant to behave in any sort of sensible and consistent manner. In this case, I had the temerity to require more than one exclude pattern (for the multiple packages). The docs claim that you can put them in one string, comma-separated or space-separated; obviously multiple elements are for wimps and no-one will ever need a pattern that contains both a literal space and a comma. I tried this, and it didn't seem to work. There is, of course, no "verbose" option on the "jar" task so I couldn't confirm whether my patterns were getting picked up. I ended up using a separate "excludesfile". A muted "hurrah" and I'm back to work. It's at times like this that I briefly consider moving back to Make. But only briefly.</p> <p>This did the trick and dex now compiled the scala-library.jar. My Android Activities and Views (which depend, indirectly, on Scala classes) successfully resolved all references and I could run my app.</p> <p>All is not satisfactory, however. As previously-mentioned, the dex compilation phase now takes a minute. This compilation happens in the background whenever you make a change to any file, whatsoever. That's right: tappitty-tap, muscle-memory says "auto-save", and bzzt you've got a minute penalty. On top of this, the dex loader on the phone takes about 10 to 15 seconds to parse the app description. I haven't yet packaged the app and used it outside of the debugger, so I can't tell if this 15 second penalty is incurred ever time you launch it.</p> <p>Both the IDE and run-time problems should be solved by running <a href="http://stackoverflow.com/questions/476111/scala-programming-for-android">proguard over it</a>. If I choose the set of interfaces above as the ones to preserve, then I should be left with a much smaller working set of classes. I didn't try this, partly because I ran out of time, but mostly because it would probably involve writing an ant build file. Can you tell I don't like ant?</p> <p>Phew, so after all that I have a <a href="http://www.flickr.com/photos/schnickschnack/3661739930/">(slightly buggy)</a> drawing of an LSystem on my phone:</p> <p><a href="http://www.flickr.com/photos/schnickschnack/3661739930/"><img title="Android Tree 1" src="http://farm4.static.flickr.com/3650/3661739930_8a2dded1a3_m.jpg" alt="Android Tree 1" /></a></p> <p>For reference, here's the same LSystem rendered using the same library, but with a Java2D backend:</p> <p><a href="http://www.flickr.com/photos/schnickschnack/3666644000/"><img title="Java2D on Mac" src="http://farm4.static.flickr.com/3636/3666644000_58ae61193e.jpg" alt="Java2D on Mac" /></a></p><![CDATA[Is Scala mature enough as a main programming language?]]>https://www.houseofmoran.com/post/2009-06-27https://www.houseofmoran.com/post/2009-06-27Sat, 27 Jun 2009 00:00:00 GMT<p>So, another summer holiday is at an end, and another programming interval. This time I was using my <a href="http://www.flickr.com/photos/schnickschnack/sets/72157620457773888/">LSystem Explorations</a> as a way to get more practice with Scala and Android.</p> <p><em>Random aside</em>: I find it hard to get excited about non-JVM languages nowadays. I develop on a Mac and deploy to Linux, Windows (sometimes) and now Android. I really don't want to worry about whether the language or platform I'm using has native components hidden somewhere inside. I've spent enough time doing "./configure" in the past to be seriously bored with non-portability. That was even going between two <a href="http://www.binrev.com/forums/index.php?showtopic=16846&#x26;pid=155481&#x26;mode=threaded&#x26;start=">Unixes</a> (Solaris and Linux)! I know Java is really "write once, debug everywhere" (e.g. <a href="http://twitter.com/mike_moran/status/2325524583">Graphics2D problems on the Mac</a>), but at least these are problems in particular library features, not a total inability to run.</p> <p>Anyway, what have I learned? <em>Scala in Eclipse has become usable enough for me with the latest Eclipse plugin for me to use Scala as my main Programming Language</em>. It's still the case that the Scala builder gets confused too often and you have to do a Project->Clean. This even happens with pure Scala builds, and not just with mixed Java/Scala projects. The Editor integration is also flaky e.g. copy and paste between files can cause errors, and you can forget about consistently completing a Rename Refactor. However, even given all that, the ability to mix Scala and Java in one project is what really does it for me. Overall, it's still basic compared to the JDT. I don't yet want to push it for my day job, but for personal projects, where you can absorb the extra time fixing things if you break them, it's fine.</p> <p><em>Scala as a language is really growing on me</em>. As <a href="2009-06-17">previously mentioned</a>, I was working through the <a href="http://www.amazon.co.uk/Programming-Scala-Comprehensive-Step-Step/dp/0981531601">"Programming in Scala"</a> book. Even though Scala fundamentally has a small core, it has the appearance of a much larger language. I really needed to read most of this book to get past quite a few roadblocks, but I did manage it.</p> <p>For example, I'd looked at parser combinators before but found the examples posted at the time and the <a href="http://www.scala-lang.org/docu/files/api/scala/util/parsing/combinator/Parsers.Parser.html">scaladoc</a> impenetrable. This is not too surprising as operators in Scala appear as methods on the class, so class-level docs can't really tell you much about how to use them in context. The JSON example in the book was large enough to give me sufficient transferrable knowledge to write a simple parser for LSystem descriptions:</p> <pre><code>import scala.util.parsing.combinator._ object LSystemLanguage extends RegexParsers { // This parses "B; F -> FF, B -> F[+B]F[-B]+B; FB" into an LSystem def parse(spec: String) : LSystem = { parseAll(lSystem, spec) match { case Success(l, _) => l case Failure(m, _) => throw new IllegalArgumentException(m) case Error(m, _) => throw new IllegalArgumentException(m) } } def lSystem = axioms~";"~rules~";"~visible ^^ { case axioms~";"~rules~";"~visible => LSystem(axioms, rules, Set() ++ visible) } def rules = repsep ( rule, "," ) def rule = variable~"->"~rep( variable | constant ) ^^ { case lhs~"->"~rhs => new Rule(lhs, rhs) } def axioms = rep(element) def visible = rep(element) def element = variable | constant def variable = "[A-Z]".r ^^ ( (s : String) => { Var(s.charAt(0)) } ) def constant = ("[a-z]".r | literal("+") | literal("-") | literal("[") | literal("]") ) ^^ ( (s : String) => Constant(s.charAt(0)) ) } </code></pre> <p>Apologies for the probably non-idiomatic Scala (and lack of syntax-highlighting on this site, I'll upgrade one day, honest), but it has the important property that it works, as opposed to most of my previous attempts. From further reading elsewhere, I get the impression that they are papering over some details (the !RegexParser combines both tokenisation and parsing, which they don't cover separately from what I read of the book). However, who cares, it works!</p> <p>I'm now seriously considering supporting the full <a href="http://fractint.oblivion.cz/snoopy.l">Fractint</a> LSystem syntax, which I wouldn't have considered doing in Java. Obviously, you <em>can</em> do all this with JLex etc, but that means going back and forward between languages and probably, gack, writing an ant script. Seriously, I spent more time during my holiday getting a simple ant task to work than I did writing this parser.</p> <p>Modulo one instance where Eclipse crashed and I had to rebuild my workspace, programming in Scala using Eclipse has been fun. The combination of an object-functional language, a half-decent IDE and rich platform libraries is very powerful. It's important to emphasize what this can give you. For me it means that if I have a spare hour or so in which to add a new feature or tweak an existing one (like extending the parser) I'll consider doing it and expect to complete it, <em>and enjoy it</em>.</p> <p>Technically, I'm capable of getting the same feature implemented in Java, in combination with other tools. However, I'd start out with a big "harumph" as I picture the fields of verbosity laid out before me. It would definitely <em>not</em> be fun.</p> <p><em>This brings me to Android</em>. The Scala compiler spits out JVM bytecodes. The Android platform, though <a href="http://www.betaversion.org/~stefano/linotype/news/110/">not strictly a Java VM</a>, does claim to support Java class files. <em>Theoretically</em>, I should be able to write a library in Scala and use it on Android.</p> <p>I am explictly not trying to write an Android app in Scala. Instead, I created an LSystem library, written in Scala, which exposes itself solely through these interfaces:</p> <pre><code>public interface LSystemViewFactory { public LSystemView evaluate(String spec, double angle, int rounds); } public interface LSystemView { public void renderTo(Renderer renderer); } public interface Renderer { interface Point { double x(); double y(); } public void addPath(Iterable&#x3C;Point> path, int length); } </code></pre> <p>In this way, I was trying to avoid relying on any special help that could come from using one Scala project with another. It does work, in a way.</p> <p><em>Warning: what follows is a history of my stubborn depth-first method of getting something showing on my phone</em>. There may a better method.</p> <p>In Eclipse 3.4, you need only make an Android project depend on a Scala project and everything will compile. However, when you run it on the phone, it will be missing the required Scala class definitions. You can download the scala-library.jar and add it as a required library. The Dex compiler then starts churning away on this file, heating up your lap as a side-effect, and then fails with a compiler error. Schäde.</p> <p>There is some joojoo in "scala-library.jar" that the Dex compiler just doesn't like. I <em>think</em> it is an unsupported annotation of some kind, probably somewhere in scala.xml.transform, but since it takes a minute or so for dex to do its thang to this library, I decided to adopt a <a href="http://www.flickr.com/photos/schnickschnack/3643127325/in/set-72157620457773888/">slash and burn</a> approach, by quickly removing anything I knew I didn't need on the phone. So, goodbye to any of scala.actors, scala.reflect, scala.testing or scala.xml.transform.</p> <p><em>Random Aside</em>: it was at this point I had the <a href="http://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy_(radio_series)">afore-mentioned elbow injury</a>^H^H^H^H...problem with ant. It is <a href="http://twitter.com/mike_moran/status/2252171537">frustratingly hard</a> to get ant to behave in any sort of sensible and consistent manner. In this case, I had the temerity to require more than one exclude pattern (for the multiple packages). The docs claim that you can put them in one string, comma-separated or space-separated; obviously multiple elements are for wimps and no-one will ever need a pattern that contains both a literal space and a comma. I tried this, and it didn't seem to work. There is, of course, no "verbose" option on the "jar" task so I couldn't confirm whether my patterns were getting picked up. I ended up using a separate "excludesfile". A muted "hurrah" and I'm back to work. It's at times like this that I briefly consider moving back to Make. But only briefly.</p> <p>This did the trick and dex now compiled the scala-library.jar. My Android Activities and Views (which depend, indirectly, on Scala classes) successfully resolved all references and I could run my app.</p> <p>All is not satisfactory, however. As previously-mentioned, the dex compilation phase now takes a minute. This compilation happens in the background whenever you make a change to any file, whatsoever. That's right: tappitty-tap, muscle-memory says "auto-save", and bzzt you've got a minute penalty. On top of this, the dex loader on the phone takes about 10 to 15 seconds to parse the app description. I haven't yet packaged the app and used it outside of the debugger, so I can't tell if this 15 second penalty is incurred ever time you launch it.</p> <p>Both the IDE and run-time problems should be solved by running <a href="http://stackoverflow.com/questions/476111/scala-programming-for-android">proguard over it</a>. If I choose the set of interfaces above as the ones to preserve, then I should be left with a much smaller working set of classes. I didn't try this, partly because I ran out of time, but mostly because it would probably involve writing an ant build file. Can you tell I don't like ant?</p> <p>Phew, so after all that I have a <a href="http://www.flickr.com/photos/schnickschnack/3661739930/">(slightly buggy)</a> drawing of an LSystem on my phone:</p> <p><a href="http://www.flickr.com/photos/schnickschnack/3661739930/"><img title="Android Tree 1" src="http://farm4.static.flickr.com/3650/3661739930_8a2dded1a3_m.jpg" alt="Android Tree 1" /></a></p> <p>For reference, here's the same LSystem rendered using the same library, but with a Java2D backend:</p> <p><a href="http://www.flickr.com/photos/schnickschnack/3666644000/"><img title="Java2D on Mac" src="http://farm4.static.flickr.com/3636/3666644000_58ae61193e.jpg" alt="Java2D on Mac" /></a></p><![CDATA[How the hell do I do this basic thing?]]>https://www.houseofmoran.com/post/2009-06-17https://www.houseofmoran.com/post/2009-06-17Wed, 17 Jun 2009 00:00:00 GMT<p>I've been programming Scala here and there and every so often get stuck in a "how the hell do I do this basic thing?" moment. So, I'm gradually working my way through <a href="http://www.amazon.co.uk/Programming-Scala-Comprehensive-Step-Step/dp/0981531601">"Programming in Scala"</a>, as I thought I should finally get more of an idea of this language works.</p> <p>I definitely like the application of the "everything is a library" strategy for implementation of what would be core features in other languages. However, one example leaves me wary, "::". A List may be constructed (val l = a :: b :: Nil) and deconstructed ((a :: b :: Nil) = l) using the same syntax. However, this is only possible because "::" is both a method on List and a case class. Along with the right-associativity of any operator ending in ":" these conspire to give the illusion of the "::" operator that is seen in other languages, like <a href="http://www.standardml.org/Basis/list.html">ML</a>.</p> <p>This all seems a little too "just-so" for me. It's if they really wanted to use Lists like in ML and engineered the defaults (like right-associativity) to make it easy. This default doesn't really help make other, non-List operators, very obvious, like "/:" and ":" (for foldLeft and foldRight, if I remember correctly).</p> <p>There is quite a lot of pragmatism in the Scala language and libraries, which I like. However, some of it seems a little too skewed towards particular features and may lack generality.</p><![CDATA[Grave of the Fireflies]]>https://www.houseofmoran.com/post/19145793600/grave-of-the-fireflieshttps://www.houseofmoran.com/post/19145793600/grave-of-the-firefliesSat, 22 Mar 2008 00:00:00 GMT<p><a href="http://en.wikipedia.org/wiki/Grave_of_the_Fireflies">Grave of the Fireflies</a> is not a film I'd recommend be seen by anyone with children. </p> <p>After we had Nils, I imagined myself being affected by all the <a href="http://imdb.com/title/tt0181689/">schmaltzy Speilberg movies</a> <a href="http://imdb.com/title/tt0212720/">featuring children in trouble</a>. Thankfully, that never happened. However, <a href="http://www.imdb.com/title/tt0095327/">this one</a> caught me by surprise. It was one of the few movies in a Studio Giblhi collection that we didn't recognise. We put in on, naively expecting another piece of <a href="http://imdb.com/title/tt0096283/">Totoro</a>-style magic. I was instead left devastated.</p> <p>"Star rating: 5, Would you recommend this to anyone: never"</p>