<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
        <title>me.dt.in.th</title>
        <description>me.dt.in.th - Thai Pangsakulyanont</description>
        <link>http://me.dt.in.th</link>
        <link>http://me.dt.in.th</link>
        <lastBuildDate>2020-07-06T15:21:57+00:00</lastBuildDate>
        <pubDate>2020-07-06T15:21:57+00:00</pubDate>
        <ttl>1800</ttl>


        
        <item>
                <title>What’s NOT a functor?</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a sequel to &lt;a href=&quot;https://medium.com/@dtinth/what-is-a-functor-dcf510b098b6&quot;&gt;What is a functor?&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;In this article, I’ll show some cases where something looks like a functor (it has a &lt;strong&gt;.map(&lt;em&gt;f&lt;/em&gt;)&lt;/strong&gt; method), but did not obey every functor law.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/what-s-not-a-functor-57a081131555</link>
                <guid>https://medium.com/@dtinth/what-s-not-a-functor-57a081131555</guid>
                <pubDate>2015-12-16T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>What is a functor?</title>
                <description>&lt;p&gt;This is my attempt at explaining about a functional programming concept called ‘functor’ in an easy-to-understand way. I’ll be explaining it in JavaScript.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/what-is-a-functor-dcf510b098b6</link>
                <guid>https://medium.com/@dtinth/what-is-a-functor-dcf510b098b6</guid>
                <pubDate>2015-12-16T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>simple > complex > complicated</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a response to &lt;a href=&quot;https://medium.com/javascript-scene/the-single-biggest-mistake-programmers-make-every-day-62366b432308&quot;&gt;The Single Biggest Mistake Programmers Make Every Day&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;It reminds me of this from the Zen of Python:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Simple is better than complex.&lt;br /&gt;
Complex is better than complicated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is not until recently — when I got to work with some very complicated code —
that I finally experience the differences between &lt;strong&gt;&lt;em&gt;complex&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;complicated&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/simple-complex-complicated-260bf5359168</link>
                <guid>https://medium.com/@dtinth/simple-complex-complicated-260bf5359168</guid>
                <pubDate>2015-11-12T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Isolating `node_modules` in Vagrant</title>
                <description>&lt;p&gt;I’m playing with &lt;a href=&quot;https://ottoproject.io/&quot;&gt;Otto&lt;/a&gt;
to set up a development environment for my Node.js project.&lt;/p&gt;

&lt;p&gt;The problem comes when I try to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; inside the VM.
Lots of weird errors going on.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/vagrant&lt;/code&gt; folder is shared between my Mac and my virtual machine.
&lt;strong&gt;By extension, this means the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; are shared as well.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; seems to cause a lot of crazy disk I/O on the shared folder,
causing gibberish bytes to be written in some files, causing installation failure.&lt;/p&gt;

&lt;p&gt;The solution is to isolate that folder, so that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; folder
lives in the VM instead of shared between guest and host.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/isolating-node-modules-in-vagrant-9e646067b36</link>
                <guid>https://medium.com/@dtinth/isolating-node-modules-in-vagrant-9e646067b36</guid>
                <pubDate>2015-11-03T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How to organize CSS in multiple files</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a response to &lt;a href=&quot;https://medium.com/@Heydon/things-to-avoid-when-writing-css-1a222c43c28f&quot;&gt;Things To Avoid When Writing CSS&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You shouldn’t organise CSS by splitting it into separate files any more than you should organise a pane of glass by dropping it on a concrete floor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An alternative to not splitting your CSS into multiple files, is to learn how to properly organize your CSS in multiple files. When done properly, this brings many advantages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Your CSS files will be small and easy to navigate. No need to scroll up and down, and your text editor will love you.&lt;/li&gt;
  &lt;li&gt;Your CSS files will be more modular.&lt;/li&gt;
  &lt;li&gt;Your CSS selectors won’t cascade or conflict with other selectors.&lt;/li&gt;
  &lt;li&gt;Your style will be more predictable, even though you can’t predict which file gets included first.&lt;/li&gt;
&lt;/ul&gt;

</description>
                <link>https://medium.com/@dtinth/how-to-organize-css-in-multiple-files-21952654711</link>
                <guid>https://medium.com/@dtinth/how-to-organize-css-in-multiple-files-21952654711</guid>
                <pubDate>2015-10-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Functions in functions</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a response to &lt;a href=&quot;https://medium.com/humans-create-software/straight-line-code-over-functions-funfunfunction-3-7f845cd79af4&quot;&gt;Straight-line code over functions — FunFunFunction #3&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;I sometimes prefer to write a single, straight-line functions
rather than writing a function that calls many small
closely-related functions, especially in imperative code.&lt;/p&gt;

&lt;p&gt;But when a function starts to get longer than 15 lines, I start feeling that the code becomes less readable.&lt;/p&gt;

&lt;p&gt;&lt;mark&gt;One of the pattern I found very useful when writing JavaScript code is to write functions in functions.&lt;/mark&gt;&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/function-in-functions-7a01dbd5390</link>
                <guid>https://medium.com/@dtinth/function-in-functions-7a01dbd5390</guid>
                <pubDate>2015-10-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Classical composition</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a sequel to &lt;a href=&quot;https://medium.com/@dtinth/different-definitions-of-inheritance-360b01a32bdc&quot;&gt;Different definitions of inheritance&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;mark&gt;Learn how you can do composition using classical inheritance and fluent ES6 classes.&lt;/mark&gt;
This article shows you that after all,
it’s not about which technique is used to structure your application (classes, stamps, prototypes, factories);
it’s actually about how one approaches Object-Oriented Analysis and Design.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/classical-composition-528c4483f6e9</link>
                <guid>https://medium.com/@dtinth/classical-composition-528c4483f6e9</guid>
                <pubDate>2015-10-23T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Different definitions of inheritance</title>
                <description>&lt;p&gt;&lt;i&gt;(This is a sequel to &lt;a href=&quot;https://medium.com/@dtinth/es6-class-classical-inheritance-20f4726f4c4&quot;&gt;ES6 class ≠ classical inheritance&lt;/a&gt;)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Get to understand ‘inheritance’ and ‘composition’ from both a technical aspect, and from an OOAD aspect, and learn how these words with ambiguous meaning causes a lot of confusion in the development community.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/different-definitions-of-inheritance-360b01a32bdc</link>
                <guid>https://medium.com/@dtinth/different-definitions-of-inheritance-360b01a32bdc</guid>
                <pubDate>2015-10-22T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>ES6 class ≠ classical inheritance</title>
                <description>&lt;p&gt;I’ve read several articles by &lt;a href=&quot;https://medium.com/u/c359511de780&quot;&gt;Eric Elliott&lt;/a&gt;
on JavaScript, such as &lt;a href=&quot;https://medium.com/javascript-scene/10-interview-questions-every-javascript-developer-should-know-6fa6bdf5ad95&quot;&gt;10 Interview Questions Every JavaScript Developer Should Know&lt;/a&gt; and &lt;a href=&quot;https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3&quot;&gt;The Two Pillars of JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;He emphasizes that classical inheritance is dangerous and should not be used (which I agree),
but somehow, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; syntax also gets the blame.
In fact, it seems to me that the terms &lt;em&gt;classical inheritance&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt;,
and ES6 class were used &lt;em&gt;interchangeably&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And that is totally wrong.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/es6-class-classical-inheritance-20f4726f4c4</link>
                <guid>https://medium.com/@dtinth/es6-class-classical-inheritance-20f4726f4c4</guid>
                <pubDate>2015-10-20T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Some subtle 3D effects for Atom</title>
                <description>&lt;p&gt;&lt;a href=&quot;http://blog.atom.io/2015/06/25/atom-1-0.html&quot;&gt;Atom 1.0&lt;/a&gt; has recently been released.
It is a very nice text editor that is “hackable to the core.”
You can change its look and behavior with CSS (Less) and CoffeeScript.&lt;/p&gt;

&lt;p&gt;So I added some subtle 3D effects to the text editor’s tree view and the minimap to make it look more “cool.”&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/some-subtle-3d-effects-for-atom-d7a624a74fdd</link>
                <guid>https://medium.com/@dtinth/some-subtle-3d-effects-for-atom-d7a624a74fdd</guid>
                <pubDate>2015-06-30T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Frontend Web Development in 2015 (Talk)</title>
                <description>&lt;p&gt;I recently gave a talk at &lt;a href=&quot;http://www.eventbrite.com/e/code-mania-10-tickets-17379863640&quot;&gt;Code Mania 10&lt;/a&gt;,
organized by Thai Programmer Network.&lt;/p&gt;

&lt;p&gt;This talk was about frontend web development in 2015.
I briefly gave an overview of new web technologies from the past four years, and gave an example of a web development workflow using ES6, React and Webpack.&lt;/p&gt;

</description>
                <link>http://spacet.me/codemania2015/</link>
                <guid>http://spacet.me/codemania2015/</guid>
                <pubDate>2015-06-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>“Code, Applied to Life”</title>
                <description>&lt;p&gt;I created a publication on Medium called “Code, Applied to Life” because I want to inspire people to get more excited about code. I want to show how a small piece of code (or shell script) can make your life easier.&lt;/p&gt;

&lt;p&gt;This publication is looking for writers. Let’s tell the world how you use code to solve everyday problems. Please contact me if you want to help contribute to this collection!&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/code-applied-to-life-ccfe2ef9c784</link>
                <guid>https://medium.com/code-applied-to-life/code-applied-to-life-ccfe2ef9c784</guid>
                <pubDate>2015-05-23T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How to set up an alarm on Mac OS X without 3rd party applications</title>
                <description>&lt;p&gt;So I’m sleepy, but want to make sure that I wake up on time.&lt;/p&gt;

&lt;p&gt;For numerous times, my phone’s alarm clocks failed me. Some morning I wake up late with a notification, saying ‘missed alarm.’ My iPad, too. It would play the alarm song once before going completely silent.&lt;/p&gt;

&lt;p&gt;In this episode, I created a simple alarm clock in shell script that tells iTunes to start playing songs after a certain period of time passes.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/how-to-set-up-an-alarm-on-mac-os-x-without-3rd-party-applications-168d12d5cedb</link>
                <guid>https://medium.com/code-applied-to-life/how-to-set-up-an-alarm-on-mac-os-x-without-3rd-party-applications-168d12d5cedb</guid>
                <pubDate>2015-05-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Towards a More Maintainable CSS</title>
                <description>&lt;p&gt;We recently launched the new Oozou website. Having worked on some projects (both mine and others; both inside and outside Oozou) with CSS code that’s not quite easy to maintain, this time I want to find ways to write CSS in a more maintainable and predictable way.&lt;/p&gt;

</description>
                <link>http://blog.oozou.com/maintainable-css/</link>
                <guid>http://blog.oozou.com/maintainable-css/</guid>
                <pubDate>2015-03-03T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Never Skip a Callback in Your Tests</title>
                <description>&lt;p&gt;On SlimWiki code, one failing test took me a whole day to track down. The worst thing is that the spec passes when the example is run in isolation, but fails when run in a test suite.&lt;/p&gt;

</description>
                <link>http://blog.oozou.com/never-skip-a-callback-in-your-tests/</link>
                <guid>http://blog.oozou.com/never-skip-a-callback-in-your-tests/</guid>
                <pubDate>2015-02-11T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How I built synth.spacet.me</title>
                <description>&lt;p&gt;I competed in this year’s &lt;a href=&quot;http://staticshowdown.com/&quot;&gt;Static Showdown&lt;/a&gt;. This year I created &lt;a href=&quot;http://2015.staticshowdown.com/teams/spacetme&quot;&gt;a web-based synthesizer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This year’s grand sponsor is the &lt;a href=&quot;https://www.polymer-project.org/&quot;&gt;Polymer project&lt;/a&gt;, with a special prize for Best Use of Web Components, so this event is the best time to experiment with Polymer.&lt;/p&gt;

&lt;p&gt;(Update: &lt;a href=&quot;http://2015.staticshowdown.com/winners&quot;&gt;I won that prize.&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This article describes the process of building this application using Polymer, Gulp, Jade, Sass and ES6.&lt;/p&gt;

</description>
                <link>https://medium.com/spacet-me-labs-presents/how-i-built-synth-spacet-me-c7cb1ca49a8f</link>
                <guid>https://medium.com/spacet-me-labs-presents/how-i-built-synth-spacet-me-c7cb1ca49a8f</guid>
                <pubDate>2015-01-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Automated GitHub Organization Invites, with Ruby, Sinatra, Slim, Octokit and ngrok</title>
                <description>&lt;p&gt;I’m working as a TA for a university course (Software Specification and Design), and I’m creating a GitHub organization for students to submit assignments.&lt;/p&gt;

&lt;p&gt;The problem is getting all students into this organization.&lt;/p&gt;

&lt;p&gt;In this episode, I created a simple web site where students can enter their GitHub username and have an invite automatically send to them.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/automated-github-organization-invites-3e940aa27040</link>
                <guid>https://medium.com/code-applied-to-life/automated-github-organization-invites-3e940aa27040</guid>
                <pubDate>2015-01-15T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>The Sass REPL, a Hidden Gem</title>
                <description>&lt;p&gt;Happy new year! In this short episode, we’ll look into how we can use the Sass REPL to generate colors for GitHub labels.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/the-sass-repl-b738465fbaae</link>
                <guid>https://medium.com/code-applied-to-life/the-sass-repl-b738465fbaae</guid>
                <pubDate>2015-01-06T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How to Copy GitHub Labels from One Project to Another</title>
                <description>&lt;p&gt;My GitHub project consists of several sub-projects. To make the labels consistent, we can use some tool to copy the label from one project to another. In this instance, I want to copy the labels from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bemusic/bemuse&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bemusic/bms-js&lt;/code&gt;.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/how-to-copy-github-labels-from-one-project-to-another-1857adc73e0f</link>
                <guid>https://medium.com/@dtinth/how-to-copy-github-labels-from-one-project-to-another-1857adc73e0f</guid>
                <pubDate>2015-01-06T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Let’s Sing Christmas Carols in Harmony!</title>
                <description>&lt;p&gt;Just in time for Christmas, the spacet.me Labs is proud to present
a tool to help you learn to sing in four-part harmony. A HTML5, ES6, and Web Audio experiment.&lt;/p&gt;

</description>
                <link>https://medium.com/spacet-me-labs-presents/lets-sing-christmas-carols-in-harmony-b71b809336af</link>
                <guid>https://medium.com/spacet-me-labs-presents/lets-sing-christmas-carols-in-harmony-b71b809336af</guid>
                <pubDate>2014-12-24T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Working with Multiple Values in a Promise Chain using Stateful Context</title>
                <description>&lt;p&gt;When we do asynchronous operations involving multiple values or objects using promises, sometimes our code could become messy. This article proposes an approach that could make the code more clean.&lt;/p&gt;

</description>
                <link>http://blog.oozou.com/stateful-context-working-with-multiple-values-in-a-promise-chain/</link>
                <guid>http://blog.oozou.com/stateful-context-working-with-multiple-values-in-a-promise-chain/</guid>
                <pubDate>2014-11-21T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Changing the System Font on Yosemite</title>
                <description>&lt;p&gt;Mac OS X comes with a new system font, Helvetica Neue.
Maybe it’s just me, but for such a new and modern interface, Helvetica Neue feels… ancient, and Helvetica is already everywhere…&lt;/p&gt;

&lt;p&gt;A more futuristic font such as Avenir Next may be a better choice.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/changing-the-system-font-on-yosemite-5870887e7b45</link>
                <guid>https://medium.com/@dtinth/changing-the-system-font-on-yosemite-5870887e7b45</guid>
                <pubDate>2014-10-17T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Declaring a CSS Animation @keyframes Directly on an Element using Sass</title>
                <description>&lt;p&gt;Usually, when I write CSS (or Sass), making an element animate involves
creating an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@keyframe&lt;/code&gt; declaration and giving it a name,
and referencing it in the CSS ruleset by name.&lt;/p&gt;

&lt;p&gt;More often than not, that particular animation would have been used only once in your whole CSS file.
This article introduces a mixin to help.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/declaring-a-css-animation-keyframes-directly-on-an-element-using-sass-f091a0a15dbd</link>
                <guid>https://medium.com/@dtinth/declaring-a-css-animation-keyframes-directly-on-an-element-using-sass-f091a0a15dbd</guid>
                <pubDate>2014-10-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Please Remind Me Every 15 Minutes! (quick 'n dirty in the irb)</title>
                <description>&lt;p&gt;At where I stay at NAIST, I use the room’s television in place of a speaker. But because there is no video signal, the TV keeps turning off by itself after 15 minutes.&lt;/p&gt;

&lt;p&gt;So I have to set a reminder every 15 minutes, and I quickly did this in the irb.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everyday-please-remind-me-every-15-minutes-e04d0df17ad5</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everyday-please-remind-me-every-15-minutes-e04d0df17ad5</guid>
                <pubDate>2014-08-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Ruby Everywhere: Ruby on Kindle Paperwhite</title>
                <description>&lt;p&gt;In this episode, I’ll get Ruby 2.1 to run on my Kindle Paperwhite.
This involves jailbreaking my Kindle.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everywhere-ruby-on-kindle-paperwhite-5139a661ed76</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everywhere-ruby-on-kindle-paperwhite-5139a661ed76</guid>
                <pubDate>2014-07-24T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>One-Line Countdown Timer</title>
                <description>&lt;p&gt;I don’t have any countdown timer app installed, but I have Ruby…&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everyday-one-line-countdown-timer-52cccc47f922</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everyday-one-line-countdown-timer-52cccc47f922</guid>
                <pubDate>2014-07-14T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Copying Table from Numbers into a Wiki</title>
                <description>&lt;p&gt;I want to convert a table from Numbers into a wiki language, so I wrote some quick-and-dirty Ruby code in the IRB to help me with this.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everyday-copying-table-from-numbers-into-a-wiki-1aba6946de8c</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everyday-copying-table-from-numbers-into-a-wiki-1aba6946de8c</guid>
                <pubDate>2014-07-11T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Growling the Current Song in a Mix, Using AppleScript, Osaka, iTunes, and Growl</title>
                <description>&lt;p&gt;Every week, I listen to Uplifting Only on SoundCloud. It is a two-hour mix of Orchestral Uplifting and Uplifting Trance music.&lt;/p&gt;

&lt;p&gt;Recently, I have been able to get this SoundCloud feed into iTunes. I want to create a script that notifies me when the song changes, so I don’t have to manually check for the playing song in iTunes.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everyday-growling-the-current-song-in-a-mix-f9a658ff51a2?source=your-stories</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everyday-growling-the-current-song-in-a-mix-f9a658ff51a2?source=your-stories</guid>
                <pubDate>2014-07-10T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Generating Text Title Images, Using a Ruby script and PhantomJS</title>
                <description>&lt;p&gt;In my last article, I grouped my Facebook photos during my internship by week: each week has its own photo album.&lt;/p&gt;

&lt;p&gt;Since I might visit several places in a single week, I want to put a “title image” to separate between the photos of different places or different date on the same week.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/ruby-everyday-generating-text-title-images-fbfa997109b8</link>
                <guid>https://medium.com/code-applied-to-life/ruby-everyday-generating-text-title-images-fbfa997109b8</guid>
                <pubDate>2014-07-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Batch Changing Facebook Album Descriptions</title>
                <description>&lt;p&gt;I am doing an internship at Nara Institute of Science and Technology for 2 months. During my time here, I traveled a lot and took many photos, and uploaded them to Facebook.&lt;/p&gt;

&lt;p&gt;The problem is that when there are so many photos in a single album, performance degrades, so I want to split them into many albums, while interlinking them together.&lt;/p&gt;

&lt;p&gt;One approach to do this is by putting links in the description of each album, linking to the other albums.&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/batch-changing-facebook-album-descriptions-35c69100a322</link>
                <guid>https://medium.com/code-applied-to-life/batch-changing-facebook-album-descriptions-35c69100a322</guid>
                <pubDate>2014-06-22T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Who Goes First?</title>
                <description>&lt;p&gt;I was at a software development training camp when, at the day of presentation, I was asked to randomly choose which group to present first…&lt;/p&gt;

</description>
                <link>https://medium.com/code-applied-to-life/who-goes-first-297fab428651</link>
                <guid>https://medium.com/code-applied-to-life/who-goes-first-297fab428651</guid>
                <pubDate>2014-06-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Populate .gitignore Automatically with git-ignore</title>
                <description>&lt;p&gt;Tired of having to create your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; manually?
Like, having to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.DS_Store&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thumbs.db&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.swp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.swo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.swn&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;I stumbled upon this project called &lt;a href=&quot;https://github.com/imwithye/git-ignore&quot;&gt;git-ignore&lt;/a&gt;.&lt;/p&gt;

</description>
                <link>https://medium.com/@dtinth/5b6423ca5c4e</link>
                <guid>https://medium.com/@dtinth/5b6423ca5c4e</guid>
                <pubDate>2014-05-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Quick Note: Setting up NAT service on Mac OS X</title>
                <description>&lt;p&gt;I wanted to share my Mac’s Internet connection from en2 (Bluetooth PAN) to en1 (Wi-Fi),
but didn’t want to run a full-fledged Internet Sharing (DHCP, Wireless Access Point, …).&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://blog.netnerds.net/2012/07/os-x-how-to-setup-nat-on-lion-and-mountain-lion/&quot;&gt;this post&lt;/a&gt;,
here is the relevant part:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Enable IP forwarding:&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; net.inet.ip.forwarding&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1

&lt;span class=&quot;c&quot;&gt;# Kill natd, just in case:&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;killall &lt;span class=&quot;nt&quot;&gt;-9&lt;/span&gt; natd
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;killall &lt;span class=&quot;nt&quot;&gt;-9&lt;/span&gt; natd

&lt;span class=&quot;c&quot;&gt;# Some ipfw rules:&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /sbin/ipfw add 100 divert natd ip from any to any via en2

&lt;span class=&quot;c&quot;&gt;# ...and start the NAT server:&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /usr/sbin/natd &lt;span class=&quot;nt&quot;&gt;-interface&lt;/span&gt; en2 &lt;span class=&quot;nt&quot;&gt;-use_sockets&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-same_ports&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-unregistered_only&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-dynamic&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-clamp_mss&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-enable_natportmap&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-natportmap_interface&lt;/span&gt; en1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now,
the client should be able to set the Default Gateway to Mac’s IP address and use the Internet through it!&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/Mac-NAT/</link>
                <guid>http://me.dt.in.th/page/Mac-NAT/</guid>
                <pubDate>2014-05-19T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Quick and Dirty Real-time Collaborative Coding Development Environment with code.stypi.com</title>
                <description>&lt;p&gt;I have to work on a very small C++ project with my friends,
so I want to edit my code like Google Docs.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://code.stypi.com/&quot;&gt;code.stypi.com&lt;/a&gt; provides a real-time collaborative code editor,
like Etherpad or Google Docs, but it only supports editing a single file.
So some quick and dirty script must be used to enable quick development and testing cycle.&lt;/p&gt;
&lt;h2 id=&quot;the-nature-of-the-project&quot;&gt;The Nature of the Project&lt;/h2&gt;

&lt;p&gt;Of course, this approach does not apply in all projects,
so here’s some background on the project.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s only a small group assignment. We don’t need permanent storage; just a way to collaborate.&lt;/li&gt;
  &lt;li&gt;It consists of only a few C++ source files, no images or binary files.&lt;/li&gt;
  &lt;li&gt;I develop on Linux while my friends use Windows.&lt;/li&gt;
  &lt;li&gt;It’s a group assignment for the real-time systems engineering course.
We have to create simulation using &lt;a href=&quot;http://www.omnetpp.org/&quot;&gt;OMNeT++&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s consider the alternatives first, and why we did not use it&lt;/p&gt;

&lt;h3 id=&quot;dropbox--google-drive&quot;&gt;Dropbox / Google Drive&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;No real-time editing. Must save the file in order for it to synchronize.&lt;/li&gt;
  &lt;li&gt;When we edit the same file, Dropbox just marks it as conflict and adds conflicted versions to the Dropbox.&lt;/li&gt;
  &lt;li&gt;Binaries (for different platforms) gets added to the Dropbox and synchronized all over. No way to ignore certain files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;github&quot;&gt;GitHub&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Not real-time.&lt;/li&gt;
  &lt;li&gt;Too slow cycle: have to save, commit, push, pull, merge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;nitrousio--cloud9--koding&quot;&gt;Nitrous.io / Cloud9 / Koding&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Creating a full-fledged project with a virtual machine and getting my friends to create an account
on sites like &lt;a href=&quot;http://nitrous.io/&quot;&gt;Nitrous.io&lt;/a&gt;, &lt;a href=&quot;http://c9.io/&quot;&gt;Cloud9&lt;/a&gt; or &lt;a href=&quot;https://koding.com/&quot;&gt;Koding&lt;/a&gt;
just for a quick bootstrapping of a project seems to be an overkill.&lt;/li&gt;
  &lt;li&gt;I want something more lightweight.&lt;/li&gt;
  &lt;li&gt;Cloud9’s collaboration feature is too laggy.&lt;/li&gt;
  &lt;li&gt;Koding is too buggy (as of writing).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;etherpad&quot;&gt;Etherpad&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;No syntax highlighting.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;div class=&quot;next-center&quot;&gt;&lt;/div&gt;

&lt;p&gt;(If you know of a better solution, please leave a comment. Thanks!)&lt;/p&gt;

&lt;h2 id=&quot;how-about-stypi&quot;&gt;How about Stypi?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://code.stypi.com/&quot;&gt;code.stypi.com&lt;/a&gt; is a real-time collaboration platform.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It lets you collaborate on writing code. It is usually used for online interviewing.&lt;/li&gt;
  &lt;li&gt;It supports syntax highlighting and has a configurable tab size.&lt;/li&gt;
  &lt;li&gt;You don’t have to sign in; you can work anonymously.&lt;/li&gt;
  &lt;li&gt;It also allows you to access the raw contents. So you can quickly download the code and build them with a quick and dirty script.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-workflow&quot;&gt;The Workflow&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Collaborate the code on Stypi.&lt;/li&gt;
  &lt;li&gt;Run a script to download the code from Stypi, builds, and test it.&lt;/li&gt;
  &lt;li&gt;Repeat.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Seems simple, right?&lt;/p&gt;

&lt;h2 id=&quot;overcoming-single-file-limitation&quot;&gt;Overcoming Single File Limitation&lt;/h2&gt;

&lt;p&gt;Since Stypi does not have tabs or support multiple files,
we decided to work on a single page, and then let the build script split it into multiple files.
The convention used is this:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/*FILE file1.h*/&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/*FILE file1.cc*/&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/*FILE main.cc*/&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &quot;file1.h&quot;
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;getting-the-raw-link&quot;&gt;Getting the Raw Link&lt;/h2&gt;

&lt;p&gt;If your Stypi is here:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://code.stypi.com/lg1ervbj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can access the raw contents using this URL:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://code.stypi.com/raw/lg1ervbj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-download-script&quot;&gt;The Download Script&lt;/h2&gt;

&lt;p&gt;First, I want a script that fetches the code from Stypi and spit out to multiple files.&lt;/p&gt;

&lt;p&gt;So I put this into Stypi:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;sr&quot;&gt;/*FILE download.rb*/&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'open-uri'&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Downloading File:&quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'https://code.stypi.com/raw/lg1ervbj'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\/\*FILE ([a-z0-9]+\.[a-z0-9]+)\*\//i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; ==&amp;gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It simply fetches the code, and uses a regular expression to split it into many files.&lt;/p&gt;

&lt;p&gt;Here’s how it now looks like:&lt;/p&gt;

&lt;div class=&quot;next-image-caption&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/Stypi-Firefox.png&quot; alt=&quot;The current state of the code in my Stypi&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This Stypi page contains the code for many files.
Each file is identified by a special comment.&lt;/p&gt;

&lt;h2 id=&quot;bootstrapping&quot;&gt;Bootstrapping&lt;/h2&gt;

&lt;p&gt;Next thing, I have to tell my friends to download and install Ruby, MingW and MSYS.
Then, I tell them to manually copy the code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;download.rb&lt;/code&gt; into a new file in a new directory,
and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby download.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If all goes well, all files should be downloaded:&lt;/p&gt;

&lt;div class=&quot;next-image-caption next-image-caption-up&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/Stypi-Result.png&quot; alt=&quot;After running ruby download.rb&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby download.rb&lt;/code&gt;, all files (including download.rb itself) have been download.&lt;/p&gt;

&lt;h2 id=&quot;building&quot;&gt;Building&lt;/h2&gt;

&lt;p&gt;Since the download script is finished, we can now make a build script!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;FILE build.sh&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;
g++ file1.cc main.cc

/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;FILE test.sh&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; a.out &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  ./a.out
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  ./a.exe
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;FILE run.sh&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;
ruby download.rb
bash build.sh
bash test.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Three files:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sh&lt;/code&gt; compiles the source code.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.sh&lt;/code&gt; runs the compiled code.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run.sh&lt;/code&gt; re-downloads the code, compiles, and runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then told my friends to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby download.sh&lt;/code&gt; again.
It now downloads the required build script.&lt;/p&gt;

&lt;p&gt;They can now type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash run.sh&lt;/code&gt; to re-download the code, compile, and run it.&lt;/p&gt;

&lt;h2 id=&quot;enjoy-the-collaboration&quot;&gt;Enjoy the Collaboration&lt;/h2&gt;

&lt;p&gt;Now we can enjoy collaborating on this small project.
When we make a change, we can just type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash run.sh&lt;/code&gt; to test it.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/stypi/</link>
                <guid>http://me.dt.in.th/page/stypi/</guid>
                <pubDate>2014-05-07T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Creating Music with Algorithms and Mathematics</title>
                <description>&lt;p&gt;Just playing with &lt;a href=&quot;http://studio.substack.net/&quot;&gt;http://studio.substack.net/&lt;/a&gt;, a &lt;a href=&quot;http://dailyjs.com/2014/04/17/code-studio/&quot;&gt;Browser Synths with Code Studio&lt;/a&gt;.
It is a website where you enter JavaScript code and it generates sound from it.&lt;/p&gt;

&lt;p&gt;Here’s what I came up with.&lt;/p&gt;
&lt;h2 id=&quot;do-you-hear-the-people-sing-uplifting-mix&quot;&gt;Do You Hear the People Sing? (Uplifting Mix)&lt;/h2&gt;

&lt;p&gt;Inspired by another code, &lt;a href=&quot;http://studio.substack.net/DUHearThePeopleSing%28v1.1%29?time=1397899959659&quot;&gt;DUHearThePeopleSing&lt;/a&gt;,
which comes from the song &lt;a href=&quot;http://www.youtube.com/watch?v=QngGvHTOKh4&quot;&gt;Do You Heart the People Sing from Les Miserables&lt;/a&gt;
I created a version with sawtooth synth arpeggios and beats.&lt;/p&gt;

&lt;div class=&quot;music-link-next&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://studio.substack.net/Do%20You%20Hear%20the%20People%20Sing%20%28Uplifting%20Mix,%20v1.3%29?time=1397997049050&quot;&gt;&lt;strong&gt;Do You Hear the People Sing (Uplifting Mix, v1.3)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created this song in a declarative, functional approach.
Each synthesizer is simply a function (such as sine, sawtooth)
that takes the time and returns the sample.
These synthesizers are filtered and mixed through a higher-order function.
Finally, I ended up with a function that represents the music itself.&lt;/p&gt;

&lt;p&gt;Since writing a lot of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function() {}&lt;/code&gt; things are so cumbersome,
I decided to develop it using CoffeeScript instead.
&lt;a href=&quot;https://gist.github.com/dtinth/11080149&quot;&gt;Here is the source code in CoffeeScript&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;interactive-version&quot;&gt;Interactive Version&lt;/h3&gt;

&lt;p&gt;I added some hack to it to allow mouse position to be captured.
I used the mouse position to control the highpass/lowpass filter and some
stuttering beat effect.&lt;/p&gt;

&lt;div class=&quot;music-link-next&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://studio.substack.net/Do%20You%20Hear%20the%20People%20Sing%20%28Uplifting%20Mix,%20v1.31%29%20%28Interactive%20Version%29?time=1398869551019&quot;&gt;&lt;strong&gt;Do You Hear the People Sing (Uplifting Mix, v1.31)&lt;br /&gt;(Interactive Version)&lt;/strong&gt;&lt;/a&gt; (move your mouse around!)&lt;/p&gt;

&lt;h2 id=&quot;rising-arp&quot;&gt;Rising Arp&lt;/h2&gt;

&lt;p&gt;A fat sawtooth arpeggio that keeps rising in frequency.
After one minute, it somehow turned into some kind of non-melodic sound.&lt;/p&gt;

&lt;div class=&quot;music-link-next&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://studio.substack.net/Rising%20Arp?time=1398097833196&quot;&gt;&lt;strong&gt;Rising Arp&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;infinitely-descending-chord-progression&quot;&gt;Infinitely Descending Chord Progression&lt;/h2&gt;

&lt;p&gt;This music features a chord progression that keeps descending.&lt;/p&gt;

&lt;p&gt;It goes like this: C/E, Cm/Eb, A#/D, A#m/Db, G#/C, G#m/B, …&lt;/p&gt;

&lt;p&gt;However, the chord progression seems to keep descending without ending.
This is possible by an auditory illusion known as &lt;a href=&quot;http://en.wikipedia.org/wiki/Shepard_tone&quot;&gt;Shepard tone&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;music-link-next&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://studio.substack.net/Infinitely%20Descending%20Chord%20Progression%20%28v1.1%29?time=1398867258045&quot;&gt;&lt;strong&gt;Infinitely Descending Chord Progression (v1.1)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There are a lot of other nice sound, which you can find in &lt;a href=&quot;http://studio.substack.net/-/recent&quot;&gt;/-/recent&lt;/a&gt;.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/code-and-music/</link>
                <guid>http://me.dt.in.th/page/code-and-music/</guid>
                <pubDate>2014-05-05T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>One Liner: Brick</title>
                <description>&lt;p&gt;A sophomore student asked me
if I can write a solution to a programming problem “Brick” in one line.
So I tried it and decided to write a walkthrough.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;This problem comes from &lt;a href=&quot;http://www.programming.in.th/task/rev2_problem.php?pid=1001&quot;&gt;Programming.in.th&lt;/a&gt;.
Given the size of the board (rows and column),
the board, and number of bricks to drop on each column,
print the resulting board.&lt;/p&gt;

&lt;h2 id=&quot;example-input&quot;&gt;Example Input&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;8 5
.....
.....
.OO..
.....
.O...
...O.
.....
.....
1 1 3 2 0 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;example-output&quot;&gt;Example Output&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;..#..
.##..
.OO..
...#.
.O.#.
...O.
.....
#....
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;Within 7 minutes, I came up with this solution in Ruby:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-walkthrough&quot;&gt;The Walkthrough&lt;/h2&gt;
&lt;p&gt;Let’s walk through the code and how I can come up with this solution.&lt;/p&gt;

&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;p&gt;This problem can be broken into many smaller subproblems.&lt;/p&gt;

&lt;h3 id=&quot;getting-the-size-of-the-board&quot;&gt;Getting the size of the board&lt;/h3&gt;

&lt;p&gt;The first line of input is the number of rows and column.
We can get it in one go:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [8, 5]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can put them into a variable and use them later by using Ruby’s lambdas.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;reading-the-board-and-the-number-of-bricks&quot;&gt;Reading the board and the number of bricks&lt;/h3&gt;

&lt;p&gt;Given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;, we can read the board using:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [[&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We transpose the board to make it easier to process.&lt;/p&gt;

&lt;p&gt;Then we can read the number of bricks to drop for each column using:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [1, 1, 3, 2, 0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Put them in variables!&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can zip the column and question like this:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [[[&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], 1],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [[&quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], 1],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [[&quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], 3],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [[&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;], 2],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [[&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], 0]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We get an array where each element represents a problem.
The first sub-element is the column (we name it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;col&lt;/code&gt;), and the second sub-element the number of blocks to drop on that column (we name it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;dropping-blocks&quot;&gt;Dropping blocks&lt;/h3&gt;

&lt;p&gt;Now, we can solve the problem for each column separately.
Consider the fourth column:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;O&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, we have to calculate where to drop blocks…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If there is an “O” in that column, we put blocks above it.&lt;/li&gt;
  &lt;li&gt;Otherwise, we put blocks on the bottom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above can be summarized by this expression:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; 5  --------------------------+&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#                                ↓&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, if we want to drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt; blocks above the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;th index, we can use this code:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;#&quot;, &quot;#&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Putting them together, we get:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Putting all of them together, we get:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; [[&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;#&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;#&quot;, &quot;O&quot;, &quot;.&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;#&quot;, &quot;#&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;#&quot;, &quot;#&quot;, &quot;O&quot;, &quot;.&quot;, &quot;.&quot;],&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;formatting-the-output&quot;&gt;Formatting the output&lt;/h3&gt;

&lt;p&gt;Now that we have the answer, we just transpose it back, and print them!&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chars&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# STDOUT:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    ..#..&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    .##..&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    .OO..&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    ...#.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    .O.#.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    ...O.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    .....&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#    #....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/OneLiner-Brick/</link>
                <guid>http://me.dt.in.th/page/OneLiner-Brick/</guid>
                <pubDate>2014-02-01T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>please — repeat last command as root.</title>
                <description>&lt;p&gt;Today I’d like to introduce you to this recipe you can put in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;please&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sudo bash -c &quot;$(history -p !!)&quot;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr /&gt;

&lt;p&gt;You probably have had these moments when you are trying to run a command
only to find out that you are not root:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;▹ &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;127.0.0.1 dev.my.test.app.com &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts
&lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;: /etc/hosts: Permission denied
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;With this alias, you can just re-run the command using&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;▹ please
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and it will re-run the command as root.
Note that &lt;em&gt;it also works with redirections!&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;handles-arguments-correctly&quot;&gt;Handles Arguments Correctly&lt;/h2&gt;

&lt;p&gt;To see if this recipe works well with complex commands,
consider this example:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;▹ ruby &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'p [ARGV, `whoami`.strip]'&lt;/span&gt; a &lt;span class=&quot;s1&quot;&gt;'b c'&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;d e&quot;&lt;/span&gt; f &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;whoami&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;b c&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;d e&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;f&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;dttvb&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;dttvb&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

▹ please
&lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;b c&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;d e&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;f&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the whole command is run
as if it’s being typed again, but in the root shell.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/please/</link>
                <guid>http://me.dt.in.th/page/please/</guid>
                <pubDate>2014-01-03T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>pushnot — A Personal Push Notification Server</title>
                <description>&lt;p&gt;&lt;a href=&quot;https://github.com/dtinth/pushnot&quot;&gt;&lt;strong&gt;pushnot&lt;/strong&gt;&lt;/a&gt; is an open source push notification server written in Node.js.
You can use it to push notifications to your Mac.&lt;/p&gt;
&lt;p class=&quot;image with-border&quot;&gt;&lt;img src=&quot;/images/pushnot-Screenshot2.png&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;When I push my code, the post-receive hook deploys it,
and pushes the notification back to my screen.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;When I push code to my &lt;a href=&quot;https://github.com/dtinth/dark-facebook&quot;&gt;GitHub repository&lt;/a&gt;,
GitHub triggers a &lt;a href=&quot;https://help.github.com/articles/post-receive-hooks&quot;&gt;Post-Receive WebHook&lt;/a&gt; that I set up to compile the code and deploy it.&lt;/p&gt;

&lt;p&gt;I want to be notified when the code is successfully deployed.&lt;/p&gt;

&lt;p&gt;Apple already has &lt;a href=&quot;https://developer.apple.com/notifications/safari-push-notifications/&quot;&gt;Safari Push Notifications&lt;/a&gt;,
but &lt;a href=&quot;https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW1&quot;&gt;to use it&lt;/a&gt;,
I need to be in their Mac Developer or iOS Developer program.&lt;/p&gt;

&lt;p&gt;So I decided to roll my own.&lt;/p&gt;

&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Send push notifications from your shell scripts, PHP scripts, or whatever.&lt;/li&gt;
  &lt;li&gt;Notifications are encrypted using public key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/pushnot.png&quot; alt=&quot;Overview Diagram&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;The client sends a notification to the server.
The server pushes it to the subscriber.&lt;br /&gt;
The subscriber displays the notification on screen.&lt;/p&gt;

&lt;p&gt;Pushnot consists of three major components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The server&lt;/strong&gt; that clients can send a notification to, and subscribers can subscribe to these notifications.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The client&lt;/strong&gt; is any application that wants to send a notification to the user.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The subscriber&lt;/strong&gt; waits for the server to push the notification and notifys the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;First, you need to have a private server to run your personal notification server.
I’m using &lt;a href=&quot;https://www.digitalocean.com/&quot;&gt;DigitalOcean’s VPS&lt;/a&gt;
which costs only $5 a month. Installing &lt;a href=&quot;https://www.digitalocean.com/community/articles/how-to-install-node-js-with-nvm-node-version-manager-on-a-vps&quot;&gt;Node.js on it is straightforward&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On both your personal computer and the server, install:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://zeromq.org/&quot;&gt;zeromq&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;On Ubuntu, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get install libzmq-dev&lt;/code&gt; should do it.&lt;/li&gt;
      &lt;li&gt;On Mac OS X, perhaps using Homebrew.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On your personal computer, install and run:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://growl.info/&quot;&gt;Growl&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://growl.info/downloads&quot;&gt;GrowlNotify&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sdegutis/zephyros&quot;&gt;zephyros&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;public-and-private-key-generation&quot;&gt;Public and Private Key Generation&lt;/h2&gt;
&lt;p&gt;All notifications are encrypted using a public key,
and only the user (with the private key) can see that notification.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pushnot&lt;/code&gt; requires an RSA key of at least 2048 bit:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openssl genrsa &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; ~/.pushnot.pem 2048
openssl rsa &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; ~/.pushnot.pem &lt;span class=&quot;nt&quot;&gt;-pubout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/.pushnot.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;You need a configuration file to locate the server.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;~/.pushnot.conf.json&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;your.vps.host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;http&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;zmq&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;some random string&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;server&lt;/strong&gt;: This is the IP address or host name of your server.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;http&lt;/strong&gt;: The port of the HTTP server. You can use 60001.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;zmq&lt;/strong&gt;: The port of the ZeroMQ server. You can use 60002.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;key&lt;/strong&gt;: Enter some random string here, which is a shared key to communicate between the client and server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;server-installation&quot;&gt;Server Installation&lt;/h2&gt;

&lt;p&gt;On server, install &lt;a href=&quot;http://pm2.io/&quot;&gt;pm2&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; pm2 &lt;span class=&quot;nt&quot;&gt;--unsafe-perm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Copy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.pushnot.conf.json&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.pushnot.pub&lt;/code&gt; to your server.&lt;/p&gt;

&lt;p&gt;Clone the project and install dependencies:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/dtinth/pushnot.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;pushnot
npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Link so that you can use the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pushnot&lt;/code&gt; anywhere.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start the server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pm2 start pushnot-server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;client-installation&quot;&gt;Client Installation&lt;/h2&gt;

&lt;p&gt;Also clone the project, and install dependencies.
You can link so that you can send push notifications from your computer too.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/dtinth/pushnot.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;pushnot
npm &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure both Zephyros and Growl is running,
start the subscriber!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node pushnot-subscriber.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s send a push notification!
From the server,
run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pushnot hello Hello World
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should now see the notification on your computer.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/pushnot-Screenshot.png&quot; alt=&quot;The Notification&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;caption move-caption-up&quot;&gt;Here comes the notification.&lt;/p&gt;

&lt;h2 id=&quot;turn-off-growl-display&quot;&gt;Turn off Growl Display&lt;/h2&gt;

&lt;p&gt;You should probably see that the notification is displayed both by Zephyros and Growl.&lt;/p&gt;

&lt;p&gt;The reason for that is because I like Zephyros’ alert boxes better (you can click through it), but I also want Growl to put the notification in “Growl Notification Rollup” when I am idle.&lt;/p&gt;

&lt;p&gt;But displaying two notifications at once seems like a silly idea. That’s why I tell Growl not to display a notification by setting the display style to “No Default Display”&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/pushnot-NoDefaultDisplay.png&quot; alt=&quot;Growl Settings&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;caption move-caption-up&quot;&gt;Set the Application's Display Style for pushnot to &quot;No Default Display.&quot;&lt;/p&gt;

&lt;h2 id=&quot;zephyros-configuration&quot;&gt;Zephyros Configuration&lt;/h2&gt;

&lt;p&gt;You’ll see that you need to keep this script running to receive push notifications,
but you can configure Zephyros to keep it running!&lt;/p&gt;

&lt;p&gt;Go to Zephyros preferences, and set the script to pushnot subscriber:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/pushnot-ZephyrosConfiguration.png&quot; alt=&quot;Zephyros Settings&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Depending on how you installed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt;, your command may vary. Here’s mine:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/Users/dttvb/.nvm/v0.10.5/bin/node /Users/dttvb/Projects/pushnot/pushnot-subscriber.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To determine which command you want to use, make sure you’re in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pushnot&lt;/code&gt; folder:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;which node&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/pushnot-subscriber.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;use-pushnot-in-your-hooks&quot;&gt;Use pushnot in Your Hooks&lt;/h2&gt;

&lt;p&gt;Now you are free to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pushnot&lt;/code&gt; in your post-commit hooks.
For example,
if you just want to notify when someone pushes a commit to your repository,
you can use this hook (written in PHP):&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;truncate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'~\n.*$~s'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'...'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;json_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'payload'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$payload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;repository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' / '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$payload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;repository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'New commit:'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$commits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;array_reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$payload&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$commits&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$commit_message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;truncate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'+ ('&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;') '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$commit_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;implode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'pushnot '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;escapeshellarg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;escapeshellarg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;a-wrapper-script&quot;&gt;A Wrapper Script&lt;/h2&gt;

&lt;p&gt;Since I install node inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvm&lt;/code&gt;. It can’t be run by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nobody&lt;/code&gt; (web server’s PHP process). To make it work I need to use some dirty hack:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/usr/bin/pushnot&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/root/.nvm/v0.10.22/bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/root
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sending noti&quot;&lt;/span&gt;
/root/.nvm/v0.10.22/bin/pushnot &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And make sure to give appropriate permissions to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/root&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/root/.nvm&lt;/code&gt;.
I know it’s dirty, but it works for me.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/pushnot/</link>
                <guid>http://me.dt.in.th/page/pushnot/</guid>
                <pubDate>2013-11-29T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>The "itself" Recipe</title>
                <description>&lt;p&gt;I’m tired of having to write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function(x) { return x.something }&lt;/code&gt; again
and again and again and again and again,
and I’m working on a very small standalone script,
so using &lt;a href=&quot;https://github.com/dtinth/it.js&quot;&gt;it.js&lt;/a&gt; seems to be an overkill for me.&lt;/p&gt;

&lt;p&gt;So I came up with a simple recipe:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itself&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;its&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;return its&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;its&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itself&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Let’s see some use cases…&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;itself&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.trim()&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// =&amp;gt; [ 'hello', 'world', 'test' ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;An &lt;a href=&quot;https://github.com/dtinth/itself&quot;&gt;npm module&lt;/a&gt; is available!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;itself
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That version also has function caching, so it should be extremely fast.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/itself/</link>
                <guid>http://me.dt.in.th/page/itself/</guid>
                <pubDate>2013-11-22T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Monkey-Patching, Overriding, and Decorating Methods in JavaScript</title>
                <description>&lt;p&gt;While working on a &lt;a href=&quot;http://casperjs.org/&quot;&gt;CasperJS&lt;/a&gt; &lt;a href=&quot;http://docs.casperjs.org/en/latest/modules/tester.html&quot;&gt;test suite&lt;/a&gt;,
I wanted to make it generate another file after the test result file was generated,
so I had to monkey-patch their test framework
(see the section after this article for why I had to do it).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Monkey_patch&quot;&gt;Monkey-patching&lt;/a&gt; is a way to override or extend the behaviour of a method without changing its original source code.
This article shows you how you can do it in a beautiful way in JavaScript.&lt;/p&gt;

&lt;h2 id=&quot;original-code&quot;&gt;Original Code&lt;/h2&gt;
&lt;p&gt;Let’s take this class as an example.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tester&lt;/code&gt; class has a method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;saveResults&lt;/code&gt; that saves the test result to a file specified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filepath&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test result to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Running tests...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;test.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And it’d be used like this…&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tester&lt;/code&gt; class is written by a third-party,
so I don’t want to modify its source code.&lt;/p&gt;

&lt;p&gt;However, I wanted my Tester to also generate and save a test plan file after the test result is saved.
This is where monkey-patching comes in.&lt;/p&gt;

&lt;h2 id=&quot;stupid-monkey-patching&quot;&gt;Stupid Monkey Patching&lt;/h2&gt;
&lt;p&gt;This is the simplest way to do monkey patching.
Just copy the source code and modify it to your needs,
replacing the original function.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test result to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// old code&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_plan.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// new code&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test plan to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// new code&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works but you have to duplicate some code from the source code.&lt;/p&gt;

&lt;p&gt;There has to be a better way…&lt;/p&gt;

&lt;h2 id=&quot;store-a-reference-to-the-original-function&quot;&gt;Store a Reference to the Original Function&lt;/h2&gt;
&lt;p&gt;We can store a reference to the original function,
and call it in our new function.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalSaveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;originalSaveResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_plan.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test plan to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But how could you be sure that the function that calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;saveResults&lt;/code&gt; doesn’t use its return value?
We can save the return value from the original function and return it to preserve its return value, whatever it might be:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalSaveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;saveResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalSaveResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_plan.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test plan to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Having to do this every time we monkey-patch a function seems to me like a lot of work.&lt;/p&gt;

&lt;p&gt;There has to be a better way…&lt;/p&gt;

&lt;h2 id=&quot;meet-the-override-function&quot;&gt;Meet the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;override&lt;/code&gt; function&lt;/h2&gt;
&lt;p&gt;When we override a method, we&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;save the original function in a variable, and&lt;/li&gt;
  &lt;li&gt;replace that method with the function we desire to use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I factored it out. Here’s our override function:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;methodName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;methodName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;methodName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What it does is this:
it sends the original function into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; function,
and whatever that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; function returns,
we replace the object’s method with it.&lt;/p&gt;

&lt;p&gt;Here’s how we can use it:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;saveResults&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_plan.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test plan to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now it’s very clear that we are overriding a function,
and no more do we have save the original function in a variable—it gets passed into the callback function.
Also,
instead of having to write the name of the method to monkey-patch twice,
we only have to write it once.&lt;/p&gt;

&lt;p&gt;However,
having to call the original function,
and save its return value,
and return it myself does not look ideal…&lt;/p&gt;

&lt;p&gt;There has to be a better way…&lt;/p&gt;

&lt;h2 id=&quot;meet-the-after-decorator&quot;&gt;Meet the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after&lt;/code&gt; decorator&lt;/h2&gt;
&lt;p&gt;You see the pattern:
in the function we want to replace,
we&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;call the original function,&lt;/li&gt;
  &lt;li&gt;save its return value,&lt;/li&gt;
  &lt;li&gt;do our work, and&lt;/li&gt;
  &lt;li&gt;return the saved return value.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can factor that out too. Meet the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a &lt;a href=&quot;http://javascript.info/tutorial/decorators&quot;&gt;decorator&lt;/a&gt;.
It takes a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extraBehavior&lt;/code&gt;,
and return a function suitable for passing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;override&lt;/code&gt;—a function that takes the original function and return the altered behavior.
We can use it like this.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;saveResults&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_plan.xml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Save test plan to &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;planpath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;meet-the-other-decorators&quot;&gt;Meet the Other Decorators&lt;/h2&gt;
&lt;p&gt;Here are some other decorators,
just to give you some idea how far you can go with it.&lt;/p&gt;

&lt;h3 id=&quot;before&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;compose&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compose&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;extraBehavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say you want to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getName&lt;/code&gt; always return the name uppercased:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;benchmark&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;benchmark&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;startTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;finishTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Took&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;finishTime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;startTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ms.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returnValue&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;memoize&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memoize&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// XXX: Work only with functions with 1 argument.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memoize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;original&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, maybe we might want to memoize a recursive function.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memoize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ~6111ms without memoize,&lt;/span&gt;
                               &lt;span class=&quot;c1&quot;&gt;//     0ms with memoize.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;using-these-decorators-on-their-own&quot;&gt;Using These Decorators on Their Own&lt;/h2&gt;
&lt;p&gt;Of course, it’s possible to use these decorators on their own.
Here’s how I measured the speed of the above benchmark of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memoize&lt;/code&gt; decorator:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;memoize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;afterthoughts&quot;&gt;Afterthoughts&lt;/h2&gt;
&lt;p&gt;Monkey-patching is extremely useful when you want to modify the behavior of some methods,
but you don’t want to alter its source code.
For example,
when attaching some extra behavior or when working around an issue in a third-party library.&lt;/p&gt;

&lt;p&gt;However,
I don’t recommend using it in your own code
because when you read the original function,
it will be hard to predict if some extra behavior will run
because it’s been monkey-patched somewhere else in your application or not.&lt;/p&gt;

&lt;p&gt;Here’s a case study:&lt;/p&gt;

&lt;p&gt;My Twitter client, thaiWitter,
has a lot of base functionalities hard-coded.
Additional functionalities are added by monkey-patching these classes on top of one another.&lt;/p&gt;

&lt;p&gt;Soon the code became a big mess.
It’s hard to test and debug.&lt;/p&gt;

&lt;p&gt;The lessons I learned is this:
it’s better to make an object extensible explicitly
(using hooks, events, or whatever)
than implicitly (monkey patches on top of monkey patches).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-i-had-to-do-monkey-patch-casperjs&quot;&gt;Why I had to do monkey-patch CasperJS&lt;/h2&gt;

&lt;h3 id=&quot;capturing-screenshot-when-test-failed&quot;&gt;Capturing Screenshot when Test Failed&lt;/h3&gt;

&lt;p&gt;CasperJS’s &lt;a href=&quot;http://docs.casperjs.org/en/latest/modules/tester.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tester&lt;/code&gt;&lt;/a&gt; module fires the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fail&lt;/code&gt; event when an assertion failure occurs. We could have used that instead.&lt;/p&gt;

&lt;p&gt;However, when we tell CasperJS to abort the test suite on first failure (don’t keep going on) with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--fail-fast&lt;/code&gt; flag turned on,
CasperJS doesn’t call the registered event handler!&lt;/p&gt;

&lt;p&gt;So we had to work around by monkey-patching the function that gets called when an error or an assertion failure occurs:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentSuite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;addFailure&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleFailure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentSuite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;addError&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;nx&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleFailure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;generating-test-plans&quot;&gt;Generating Test Plans&lt;/h3&gt;

&lt;p&gt;Furthermore, we want to be able to generate a test plan document in addition to the test result,
and that’s just what we did in the article:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;saveResults&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;savePlan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/JavaScript-override/</link>
                <guid>http://me.dt.in.th/page/JavaScript-override/</guid>
                <pubDate>2013-11-19T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How I sent my friend to sleep</title>
                <description>&lt;p&gt;Or, how I explained the expected value of a Geometric Random Variable to a friend.&lt;/p&gt;

</description>
                <link>https://medium.com/this-happened-to-me/4dca7b28b4d4</link>
                <guid>https://medium.com/this-happened-to-me/4dca7b28b4d4</guid>
                <pubDate>2013-10-10T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>With Angular.js I Created a Teaching Material in 15 minutes</title>
                <description>&lt;blockquote&gt;
  &lt;p&gt;Just as iron sharpens iron, friends sharpen the minds of each other. —Proverbs 27:17 (CEV)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I like to teach my friends about coding stuff, usually about the web, JavaScript, Ruby, and sometimes other things.
When I do, I like to find new ways to help people see what actually happened. Anyway, this post isn’t about me; it’s about Angular.js. I used it to create an &lt;a href=&quot;http://plnkr.co/edit/gist:6743484?p=preview&quot;&gt;array visualizer&lt;/a&gt; to help visualize how sorting algorithms work, within 15 minutes.&lt;/p&gt;

</description>
                <link>https://medium.com/teaching-learning/868b68128da0</link>
                <guid>https://medium.com/teaching-learning/868b68128da0</guid>
                <pubDate>2013-09-29T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Cool things you can do with it.js</title>
                <description>&lt;p&gt;I just released a new small JavaScript library called &lt;a href=&quot;https://github.com/dtinth/it.js&quot;&gt;&lt;strong&gt;it.js&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve ever used any of these: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array.map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array.filter&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_.sortBy&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_.all&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_.any&lt;/code&gt;, you’ll know
that these “higher-order” functions wants you to to pass in some kind of function.
Usually this function just takes an object, looks up a property or call a method, and return the result.&lt;/p&gt;

&lt;p&gt;This library, &lt;strong&gt;it.js&lt;/strong&gt;, helps you create that function, so you can write:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead of&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This library is a byproduct of me building another AngularJS app,
the new version of &lt;a href=&quot;http://dtinth.github.io/friendlist/&quot;&gt;Friendlist&lt;/a&gt;, friend list manager for Facebook.&lt;/p&gt;

&lt;p&gt;This article will show you what you can do with &lt;strong&gt;it.js&lt;/strong&gt;.
For more detailed documentation, please see the &lt;a href=&quot;https://github.com/dtinth/it.js&quot;&gt;project page on GitHub!&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;itjs-generates-functions&quot;&gt;it.js generates functions&lt;/h2&gt;

&lt;p&gt;Generating functions is a main duty of it.js.&lt;/p&gt;

&lt;p&gt;Let’s see some analogies. The first line is how you can do it without it.js,
and the second line shows how you can use it.js instead of writing these functions by hand.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;charCodeAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;charCodeAt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pluck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;splat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;screen_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;screen_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;screen_name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;here-are-the-things&quot;&gt;Here are the things&lt;/h2&gt;

&lt;p&gt;Here we have an array of “things”.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;          &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;CoffeeScript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;            &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;            &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Guava&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;          &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;JavaScript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Mountain Lion&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;animal&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Pineapple&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;      &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Ruby&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s see what we can do with it…&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The first line shows how you can do it without using it.js.&lt;br /&gt;
Subsequent lines shows how it.js can help simplify your code.&lt;/p&gt;

&lt;p&gt;Get all the names!&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How about having them lowercased?&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;What if we only want the fruits?&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And if we only want the name of these fruits?&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;fruit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;here-are-the-strings&quot;&gt;Here are the strings&lt;/h2&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;strings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Piece&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;life&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;still&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;still&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Wall&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;my&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;heart&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What if we want to get a case-insensitive sorted copy?
Using &lt;a href=&quot;http://lodash.com/&quot;&gt;Lo-Dash&lt;/a&gt; or &lt;a href=&quot;http://documentcloud.github.com/underscore/&quot;&gt;underscore&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As you can see, where we could create a simple function manually, we can use &lt;a href=&quot;https://github.com/dtinth/it.js&quot;&gt;it.js&lt;/a&gt; to help.&lt;/p&gt;

&lt;p&gt;As a note about performance, it takes a lot of operation to generate a function, so
you should not generate these functions inside a loop.&lt;/p&gt;

&lt;p&gt;You can, and should, generate these functions somewhere else. They can be used later.&lt;/p&gt;

&lt;p&gt;For example, you could write this:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;caseInsensitive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And use them like this:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sortBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;caseInsensitive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/it</link>
                <guid>http://me.dt.in.th/page/it</guid>
                <pubDate>2013-07-06T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Vim: Running Custom Shell Commands Quickly</title>
                <description>&lt;p&gt;When I use Vim, sometimes when I make an edit, I want to test if it works by running some command.
(Something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc % &amp;amp;&amp;amp; ./a.out&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So I made a simple Vim script to help:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/dtinth/5727151.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;To use it, first, press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Leader&amp;gt;s&lt;/code&gt;. It will ask for a command, in which you type the command you wish to run.&lt;/p&gt;

&lt;p&gt;Then, when you want to run the configured command, just press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Leader&amp;gt;r&lt;/code&gt;.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/VimCustomShellCommand</link>
                <guid>http://me.dt.in.th/page/VimCustomShellCommand</guid>
                <pubDate>2013-06-07T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Building an AngularJS App that Synchronizes Across Clients in Realtime with Synchroscope</title>
                <description>&lt;p&gt;&lt;i&gt;This article tells story about my first AngularJS web app, and development of my first AngularJS
library called &lt;a href=&quot;https://github.com/dtinth/synchroscope&quot;&gt;&lt;strong&gt;synchroscope&lt;/strong&gt;&lt;/a&gt; that lets multiple web clients to synchronize
AngularJS scope variables in realtime. If you just want to see the library, please see the &lt;a href=&quot;https://github.com/dtinth/synchroscope&quot;&gt;GitHub project&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;My Computer Engineering department has an activity to welcome first-year students every year,
the &lt;strong&gt;Freshy Camp&lt;/strong&gt;. I work on the registration part, so I made a web app to make the registration process
quicker and more accurate.&lt;/p&gt;

&lt;p&gt;I think I’d go with AngularJS because I’ve never used it, and I’m wondering why everyone loves it.&lt;/p&gt;

&lt;h2 id=&quot;the-freshy-camp-registration-app&quot;&gt;The Freshy Camp Registration App&lt;/h2&gt;

&lt;p&gt;Let’s first see how the web application I made looked like…
There are two interfaces, one facing the freshmen on an iPad, and another one facing me on my laptop.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/Synchroscope-Freshy-Step0.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;nudge caption&quot;&gt;The welcome screen: freshmen just touch the screen!&lt;/p&gt;
&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/Synchroscope-Freshy-Step1.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;nudge caption&quot;&gt;Then, the freshmen &lt;strong&gt;writes&lt;/strong&gt; part of his/her real name.
&lt;br /&gt;The handwriting appears on my screen, and I type his/her name accordingly.
&lt;br /&gt;The app searches for matching names and displays it in a table, making it look
like the app magically recognizes their handwriting, where actually, I was the recognizer.
&lt;br /&gt;The freshmen chooses the correct record and proceed to the next step.&lt;/p&gt;
&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/Synchroscope-Freshy-Step2.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;nudge caption&quot;&gt;The freshmen writes in his/her nickname.
I see it written, and type accordingly.&lt;/p&gt;
&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/Synchroscope-Freshy-Step4.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;nudge caption&quot;&gt;The freshmen enters his/her mobile phone number.&lt;/p&gt;
&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/Synchroscope-Freshy-Step5.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;nudge caption&quot;&gt;The app informs the freshmen's assigned group, called &quot;mung.&quot;
&lt;br /&gt;To this day I still don't know why they use the word &quot;mung.&quot;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Thanks to AngularJS’ design, the model (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$scope&lt;/code&gt; data) and the controller can be totally
separated from the view. So I can write different views for same model.&lt;/p&gt;

&lt;p&gt;The model (scope) contains:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The current step (welcome, entering name, phone number, or finished)&lt;/li&gt;
  &lt;li&gt;The handwriting that the freshmen is writing&lt;/li&gt;
  &lt;li&gt;A flag whether the handwriting pad is visible&lt;/li&gt;
  &lt;li&gt;Selected student ID, name, phone number, and assigned group, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now, when it comes to view, I just display stuff based on the model.
On the iPad, showing different components for different steps is as easy as:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ng-show=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;step==1&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On my desktop page, it’s something like:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ng-class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{active: step==1}&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;but&quot;&gt;But…&lt;/h2&gt;

&lt;p&gt;Well, but the iPad’s view and desktop’s view aren’t on the same page.
In fact, they’re on entirely different devices! So how can they access the same model?
Well, they can’t!&lt;/p&gt;

&lt;p&gt;Therefore, it’s clear that there must be something that syncs the models between two devices.&lt;/p&gt;

&lt;p&gt;And that’s where my new library, &lt;a href=&quot;https://github.com/dtinth/synchroscope&quot;&gt;synchroscope&lt;/a&gt; kicks in.&lt;br /&gt;Actually, this library is extracted from this Freshy Camp webapp.&lt;/p&gt;

&lt;h2 id=&quot;how&quot;&gt;How?&lt;/h2&gt;

&lt;p&gt;Using synchroscope is easy. You just include several JS files, declare a dependency, and then add one line of JavaScript to your controller:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$ync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;keep&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;roomName&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After this, synchroscope will keep these properties in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$scope&lt;/code&gt; in sync with all clients in the same server and room.&lt;/p&gt;

&lt;p&gt;With the rooms feature, I can have multiple iPad+Computer+Human to register multiple people at the same time.&lt;/p&gt;

&lt;h2 id=&quot;the-server&quot;&gt;The Server&lt;/h2&gt;

&lt;p&gt;Synchroscope uses Socket.IO for realtime communication.
It also requires only one line of code to add Synchroscope server to your Node.js server.
It’s also possible to run a server on its own. Just see &lt;a href=&quot;https://github.com/dtinth/synchroscope&quot;&gt;the project page for instructions&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;limitations&quot;&gt;Limitations&lt;/h2&gt;

&lt;p&gt;Because it’s designed to be use in a small registration place, the server kept all data in memory, and they won’t survive restarts.
It also doesn’t scale beyond one process.&lt;/p&gt;

&lt;p&gt;Although this library doesn’t cover all realtime collaborative app use cases,
I think that being able to synchronize data across clients
using very few lines of code—both on the client and server—makes it very easy to get started.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This is my first AngularJS web project and library.
After I tried AngularJS, &lt;strong&gt;I completely fell in love with it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I now see no reasons not to use AngularJS anymore, even for very small projects,
because it’s so simple. Just include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;angular.min.js&lt;/code&gt; and add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ng-app&lt;/code&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;html&amp;gt;&lt;/code&gt;,
your HTML becomes much more powerful with data binding and directives!&lt;/p&gt;

&lt;h2 id=&quot;application&quot;&gt;Application&lt;/h2&gt;

&lt;p&gt;So after I wrote &lt;a href=&quot;https://github.com/dtinth/synchroscope&quot;&gt;synchroscope&lt;/a&gt;, I recalled having written a similar project that synchronizes data between
iPad and computer, called &lt;a href=&quot;https://github.com/dtinth/shoutpraises&quot;&gt;shoutpraises&lt;/a&gt;. I use it to display onscreen lyrics during worship at church.&lt;/p&gt;

&lt;p&gt;So I went ahead and turned it into my second AngularJS webapp, and that took me less than an hour.
The codebase is much more cleaner and I don’t have to worry about synchronizing between the clients anymore.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/Synchroscope</link>
                <guid>http://me.dt.in.th/page/Synchroscope</guid>
                <pubDate>2013-06-07T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>ttycast v0.2 Released</title>
                <description>&lt;p&gt;&lt;a href=&quot;https://github.com/dtinth/ttycast&quot;&gt;ttycast&lt;/a&gt; v0.2.0 is just released.
This new version is easier to use, includes server-side terminal emulation (instead of client-side),
configurable terminal size, and recording support to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tty&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&quot;ui-refinements&quot;&gt;UI refinements&lt;/h2&gt;

&lt;p&gt;The terminal window is moved to the center of browser window, and is accompanied with
a little glow around the border.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;http://i.imgur.com/YBobVKm.png&quot; alt=&quot;ttycast&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;server-side-terminal-emulation&quot;&gt;Server-side terminal emulation&lt;/h2&gt;

&lt;p&gt;In old version (v0.0.x) raw terminal data is sent directly to each client, and each client runs its own
terminal emulator.&lt;/p&gt;

&lt;p&gt;In this version the terminal emulation is done in server-side. The rendered content is then sent to the browser.
This ensures that all viewers see the same thing. The client side code to download is a lot smaller too.&lt;/p&gt;

&lt;h2 id=&quot;easier-to-use&quot;&gt;Easier to use&lt;/h2&gt;

&lt;p&gt;You don’t have to type long commands (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkfifo /tmp/......&lt;/code&gt;) to start ttycast anymore.&lt;/p&gt;

&lt;p&gt;In this new version, just type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ttyreccast&lt;/code&gt; in one terminal and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ttyrec /tmp/ttycast&lt;/code&gt; in another.&lt;/p&gt;

&lt;h2 id=&quot;recording&quot;&gt;Recording&lt;/h2&gt;

&lt;p&gt;The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ttyreccast&lt;/code&gt; command also support recording to &lt;strong&gt;.tty&lt;/strong&gt; file as you broadcast.&lt;/p&gt;

&lt;p&gt;You may play the recorded file normally using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ttyplay&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;adjustable-terminal-size&quot;&gt;Adjustable Terminal Size&lt;/h2&gt;

&lt;p&gt;This version of ttycast doesn’t require you to use 80x25 terminal anymore.&lt;/p&gt;

&lt;p&gt;You can use any terminal size you want.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;You can read more about ttycast and how to install it at &lt;a href=&quot;https://github.com/dtinth/ttycast&quot;&gt;GitHub Project&lt;/a&gt;. Enjoy!&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/ttycast-0.2</link>
                <guid>http://me.dt.in.th/page/ttycast-0.2</guid>
                <pubDate>2013-02-02T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Node.js: When to use a StringDecoder?</title>
                <description>&lt;p&gt;In Node.js, &lt;a href=&quot;http://nodejs.org/api/buffer.html&quot;&gt;Buffers&lt;/a&gt; has &lt;a href=&quot;http://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end&quot;&gt;toString()&lt;/a&gt; that can convert a buffer into a String with a specified encoding,
and &lt;a href=&quot;http://nodejs.org/api/string_decoder.html&quot;&gt;StringDecoder&lt;/a&gt; does the same. So, &lt;strong&gt;when to use StringDecoder?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The docs says that the StringDecoder is better at UTF-8. Let’s see some practical use. Here I have few buffers:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x81&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xa3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x97&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x94&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xaa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xe0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xb8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x9a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say that we received these buffers one at a time.&lt;/p&gt;

&lt;p&gt;When we receive each of these buffers, we want to pass it &lt;strong&gt;immediately&lt;/strong&gt; to the client &lt;strong&gt;as a string&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So for each received buffer, we decoded it and sent it right away.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;utf-8&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;utf-8&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;utf-8&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, what did the client get? Some gibberish along with the text…&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;กา��
�ทด�
��อบ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;How about a StringDecoder?&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;string_decoder&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;StringDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;utf-8&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s the output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;กา
รทด
สอบ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So from what we see, instead of converting incomplete UTF-8 character sequence into gibberish,
a StringDecoder &lt;strong&gt;does buffer&lt;/strong&gt; incomplete UTF-8 multibyte character sequence and waits until the
character sequence is completed.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/StringDecoder</link>
                <guid>http://me.dt.in.th/page/StringDecoder</guid>
                <pubDate>2013-02-02T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Understanding Quicksort (with interactive demo)</title>
                <description>&lt;p&gt;At the college, we’re learning about abstract data types and few sorting algorithms,
and so in this article I try to explain about the quicksort algorithm using some kind of an interactive demo.&lt;/p&gt;
&lt;p&gt;Quicksort is a sorting algorithm, which takes an array like this:&lt;/p&gt;

&lt;div id=&quot;ex1&quot;&gt;&lt;/div&gt;

&lt;p&gt;and turns it into this:&lt;/p&gt;

&lt;div id=&quot;ex2&quot;&gt;&lt;/div&gt;

&lt;p&gt;This blog post will just explain the concepts of quicksort in a very high level.&lt;/p&gt;

&lt;p&gt;I won’t go down into the code, or the analysis of running time, because that’s boring.&lt;/p&gt;

&lt;div id=&quot;nojs&quot;&gt;&lt;b&gt;This blog post requires JavaScript to function properly.&lt;/b&gt; Please read this post directly
on the blog, and turn on JavaScript.&lt;/div&gt;

&lt;h2 id=&quot;overview-of-quicksort&quot;&gt;Overview of Quicksort&lt;/h2&gt;

&lt;p&gt;Now, the principle of the quicksort algorithm is this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pick a “pivot” element.&lt;/li&gt;
  &lt;li&gt;“Partition” the array into 3 parts:
    &lt;ul&gt;
      &lt;li&gt;First part: all elements in this part is less than the pivot.&lt;/li&gt;
      &lt;li&gt;Second part: the pivot itself (only one element!)&lt;/li&gt;
      &lt;li&gt;Third part: all elements in this part is greater than or equal to the pivot.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Then, apply the quicksort algorithm to the first and the third part. (recursively)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;instructions&quot;&gt;&lt;i&gt;(drag the slider to see each step of the demonstration)&lt;/i&gt;&lt;/div&gt;

&lt;div id=&quot;ex3&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;partitioning&quot;&gt;Partitioning&lt;/h2&gt;

&lt;p&gt;An important part of this algorithm is the partitioning — how it partitions an array into 3 parts in-place, that is,
without creating extra arrays (like in mergesort). You can do it with some clever algorithm.&lt;/p&gt;

&lt;p&gt;Here is one algorithm to partition the array, which I try to present in a way that’s as easy to understand as possible.
We’ll try to partition the array like a card game.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First, assume that the pivot is the leftmost element.&lt;/li&gt;
  &lt;li&gt;Flip all the other cards down.&lt;/li&gt;
  &lt;li&gt;Then, open each card from left to right.
    &lt;ul&gt;
      &lt;li&gt;If you find a card that is &lt;i&gt;less than&lt;/i&gt; the pivot:
        &lt;ul&gt;
          &lt;li&gt;Swap that card with the card that was first opened (the leftmost open card), and close that leftmost card.&lt;/li&gt;
          &lt;li&gt;Also take note of the last closed card.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Otherwise, continue opening the next card.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Swap the last closed card with the pivot (if any).&lt;/li&gt;
  &lt;li&gt;Open all cards… You will see that the array is already partitioned!&lt;/li&gt;
&lt;/ul&gt;

&lt;div id=&quot;ex4&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;picking-the-pivot&quot;&gt;Picking the Pivot&lt;/h2&gt;

&lt;p&gt;For simplicity, we picked the leftmost element as the pivot, but this isn’t always good. Let’s consider this case where the
array is reverse-sorted:&lt;/p&gt;

&lt;div id=&quot;ex5&quot; style=&quot;min-height:360px&quot;&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the size of the problem is only reduced by 1 in each recursive call.&lt;/p&gt;

&lt;p&gt;Note that the steps it take to partition is proportional to the number of elements to partition,
therefore the more we can reduce the problem size, the lesser the number of steps.&lt;/p&gt;

&lt;p&gt;The best pivot would split the array into 2 equal parts, so the problem size would be reduced by half.
That is, the best pivot would be the median of the elements,
but to find the median you first need to sort the array (which is what we’re doing), so that wouldn’t work*.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;One approach that some people use is: just pick a random pivot!&lt;/p&gt;

&lt;p&gt;… “but the partitioning algorithm assumes that the pivot is at the leftmost element!”&lt;/p&gt;

&lt;p&gt;Easy, just swap the pivot we picked with the leftmost element,
then the leftmost element becomes the pivot.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Here’s what happens if we were able to choose the best pivot.&lt;/p&gt;

&lt;div id=&quot;ex6&quot; style=&quot;min-height:300px&quot;&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;* I remembered that one friend asked me when he tries to implement the heapsort, the conversation goes like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;” Do I need to sort the array first? “&lt;/p&gt;

  &lt;p&gt;” Wait wait wait, what are you trying to implement? “&lt;/p&gt;

  &lt;p&gt;” Heapsort. “&lt;/p&gt;

  &lt;p&gt;” Then what’s the point of doing the heap sort if we have to sort the array before we can sort the array using heapsort?! “&lt;/p&gt;
&lt;/blockquote&gt;

&lt;script src=&quot;//code.jquery.com/ui/1.10.3/jquery-ui.js&quot;&gt;&lt;/script&gt;

&lt;script&gt;$(function() {

  $('#nojs').hide()

  function render(id, frames) {
    var el = $('#' + id)
      , data = $('&lt;div&gt;&lt;/div&gt;').appendTo(el)
    el.addClass('example')
    function display(index) {
      var html = ''
        , frame = frames[index]
      for (var i = 0; i &lt; frame.array.length; i ++) {
        var classes = ['number']
        if (frame.sorted &amp;&amp; frame.sorted[i]) classes.push('sorted')
        if (frame.classes &amp;&amp; frame.classes[i] != null) {
          classes.push(frame.classes[i])
        } else if (frame.active) {
          var active = frame.active
          if (active.pivot != null) {
            var pivot = active.pivot
            if (i == pivot) classes.push('pivot')
            else if (active.partitioned) {
              if (i &lt; pivot) classes.push('before-pivot')
              if (i &gt; pivot) classes.push('after-pivot')
            } else {
              if (frame.opened) {
                if (i &lt; frame.opened[0] || i &gt;= frame.opened[1]) {
                  classes.push('closed')
                } else {
                  classes.push('after-pivot')
                }
              }
            }
          }
        }
        if (frame.stack &amp;&amp; frame.stack.length &gt; 0) {
          var top = frame.stack[frame.stack.length - 1]
          if (i &lt; top[0] || i &gt;= top[1]) classes.push('offstack')
        }
        html += '&lt;span class=&quot;' + classes.join(' ') + '&quot;&gt;' + frame.array[i] + '&lt;/span&gt;'
      }
      function size(z) {
        return 46 * z + 'px'
      }
      var addendum = false
      if (frame.stack || frame.description) addendum = true
      if (addendum) html += '&lt;div class=&quot;addendum&quot;&gt;'
      if (frame.stack) {
        html += '&lt;div class=&quot;stacks&quot;&gt;'
        for (var j = frame.stack.length - 1; j &gt;= 0; j --) {
          var sf = frame.stack[j]
            , style = 'width: ' + size(sf[1] - sf[0]) + '; margin-left: ' + size(sf[0]) + '; margin-right: ' + size(frame.array.length - sf[1])
          html += '&lt;div class=&quot;stack-frame' + (j &lt; frame.stack.length - 1 ? ' inactive' : '') + '&quot;&gt;&lt;div class=&quot;stack-bound&quot; style=&quot;' + style + '&quot;&gt;&lt;/div&gt;&lt;/div&gt;'
        }
        html += '&lt;/div&gt;'
      }
      if (frame.description) {
        html += '&lt;p class=&quot;description&quot;&gt;' + '&lt;b&gt; ( ' + (index + 1) + ' / ' + frames.length + ' ) &lt;/b&gt;&lt;br&gt;' + frame.description + '&lt;/p&gt;'
      }
      if (addendum) html += '&lt;/div&gt;'
      data.html(html)
    }
    display(0)
    var frameManager = {
          frame: 0
        , next: function() {
            this.go(this.frame + 1)
          }
        , go: function(frame) {
            this.frame = frame
            display(this.frame)
          }
        }
    if (frames.length &gt; 1) {
      $('&lt;div class=&quot;slider&quot;&gt;&lt;/div&gt;').prependTo(el).slider({ min: 0, max: frames.length - 1 }).on('slide', function(event, ui) {
        frameManager.go(ui.value)
      })
    }
  }

  var array = [ 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 ]

  render('ex1', [ { array: array.slice() } ])

  ;(function() {
    var a = array.slice()
      , all = {}
    a.sort(function(x, y) { return x - y; })
    for (var i = 0; i &lt; a.length; i ++) all[i] = true
    render('ex2', [ { array: a.slice(), sorted: all } ])
  })()

  function doQuickSort(array, id, randomPivot, showPartition) {
    var a = array.slice()
      , o = []
      , stack = []
      , sorted = []
      , partitioning
    function show(description, active) {
      var all = {}
        , classes = {}
      if (partitioning != null) classes[partitioning] = 'partitioning'
      for (var i = 0; i &lt; sorted.length; i ++) all[sorted[i]] = true
      o.push({ array: a.slice(), description: description, active: active, stack: stack.slice(), sorted: all, classes: classes })
    }
    show('This is the array to sort')
    function swap(x, y) {
      var c = a[x]
      a[x] = a[y]
      a[y] = c
    }
    function partition(lower, upper, pivot) {
      var left = lower
        , right = lower
      function report() {
        if (showPartition) {
          partitioning = right - 1
          show('[Partitioning steps...]', { pivot: pivot })
          partitioning = null
        }
      }
      while (right &lt; upper) {
        right++
        if (a[right - 1] &lt; a[pivot]) {
          swap(right - 1, left)
          left++
        }
        report()
      }
      return left
    }
    function quicksort(lower, upper, cb) {
      if (lower &gt;= upper) return
      stack.push([lower, upper])
      var noun = stack.length &gt; 1 ? 'sub-array' : 'array'
      if (cb) cb()
      if (lower + 1 == upper) {
        sorted.push(lower)
        show('Since there is only one element in this ' + noun + ',&lt;br&gt;we consider that only element &quot;sorted.&quot;')
        stack.pop()
        return
      }
      if (randomPivot) {
        var rand = (function() {
          // we will cheat and just pick the median
          var b = a.slice(lower, upper)
          b.sort(function(x, y) { return x - y; })
          var d = b[Math.floor(b.length / 2)]
          for (var k = lower; k &lt; upper; k ++) if (a[k] == d) return k
        })()
        var pivot = a[rand]
        show('Pick a pivot. The pivot (' + pivot + ') is highlighted in green.', { pivot: rand })
        swap(rand, lower)
        show('The pivot is swapped with the leftmost element.', { pivot: lower })
      } else {
        var pivot = a[lower]
        show('Pick a pivot. The pivot (' + pivot + ') is highlighted in green.', { pivot: lower })
      }
      var right = partition(lower + 1, upper, lower)
      swap(lower, right - 1)
      if (showPartition &amp;&amp; lower != right - 1) show('[Partitioning steps...]', { pivot: right - 1 })

      var descs = []
      descs.push(lower == right - 1 ? 'There are no more elements less than the pivot.' :
        'All elements less than the pivot are in the left part.')
      descs.push(right - 1 == upper - 1 ? 'There are no more elements greater than or equal to than the pivot.' :
        'All elements greater than or equal to the pivot are in the right part.')
      
      show('Partition the ' + noun + '. ' + descs.join('&lt;br&gt;'), { pivot: right - 1, partitioned: true })
      sorted.push(right - 1)
      show('The pivot is now considered &quot;sorted&quot;.')
      quicksort(lower, right - 1, function() { show('We now do quicksort on the left sub-array.') })
      quicksort(right, upper, function() { show('We now do quicksort on the right sub-array') })
      show('Coming back, we see that this ' + noun + ' is sorted.' + (stack.length == 1 ? '&lt;br&gt;Done.' : ''))
      stack.pop()
    }
    quicksort(0, a.length)
    render(id, o)
  }

  doQuickSort(array, 'ex3')
  var down = [15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
  doQuickSort(down, 'ex5', false, true)
  doQuickSort(down, 'ex6', true, true)

  ;(function() {
    var a = array.slice()
      , o = []
      , pivot
      , opened
      , beforePivot
      , normalCard
      , justClosed
    function show(description) {
      var classes = {}
      if (justClosed != null) classes[justClosed] = 'just-closed'
      if (beforePivot != null) classes[beforePivot] = 'before-pivot'
      if (normalCard != null) classes[normalCard] = 'number'
      o.push({ array: a.slice(), description: description, active: { pivot: pivot }, opened: opened ? opened.slice() : null, classes: classes })
    }
    show('This is the array to partition.')

    pivot = 0
    show('Assume that the pivot is the leftmost element (' + a[0] + ').')

    opened = [1, 1]
    show('Flip all the other cards down.')

    function swap(x, y) {
      var c = a[x]
      a[x] = a[y]
      a[y] = c
    }

    function partition(lower, upper) {
      var left = lower + 1
        , right = lower + 1
      pivot = lower
      while (right &lt; upper) {
        right++
        opened = [left, right]
        normalCard = right - 1
        show('Open the next card...')
        normalCard = null
        if (a[right - 1] &lt; a[pivot]) {
          var old = a[right - 1], neu = a[left]
            , selfSwap = right - 1 == left
          beforePivot = right - 1
          show('...but ' + old + ' is less than the pivot (' + a[pivot] + ').')
          swap(right - 1, left)
          beforePivot = left
          show('So we swap it with the first opened card (' + (selfSwap ? 'itself' : neu) + ').')
          left++
          opened = [left, right]
          justClosed = beforePivot
          beforePivot = null
          show('Then we close that card.')
        } else {
          show('...' + a[right - 1] + ' is greater than or equals to the pivot (' + a[pivot] + ').&lt;br&gt;Everything is good.')
        }
      }
      swap(pivot, left - 1)
      pivot = left - 1
      justClosed = 0
      if (pivot == 0) justClosed = null
      show('Now that we\'ve opened all cards, &lt;br&gt;swap the last closed card with the pivot.')
      var description = 'Re-open the closed card, you\'ll see that the array is partitioned!'
      o.push({ array: a.slice(), description: description, active: { pivot: pivot, partitioned: true } })
    }

    partition(0, a.length)

    render('ex4', o)
  })()

})


























&lt;/script&gt;

</description>
                <link>http://me.dt.in.th/page/Quicksort/</link>
                <guid>http://me.dt.in.th/page/Quicksort/</guid>
                <pubDate>2012-11-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Pagist — Turn a Gist Into a Web Page</title>
                <description>&lt;p&gt;Tomorrow I’m going to have a discrete maths test,
and so there are few friends asking me several questions.&lt;/p&gt;

&lt;p&gt;So I think, &lt;em&gt;wouldn’t it be nice if there is a way to send them
these mathematical equations (or few paragraph of text) in a way that is
as easy as posting a &lt;a href=&quot;https://gist.github.com/&quot;&gt;Gist&lt;/a&gt;?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s why I created &lt;a href=&quot;http://pagist.github.com/&quot;&gt;&lt;strong&gt;Pagist&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;Basically, pagist lets you write some text documents in Markdown format,
submit it to Gist, and alter the URL from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://gist.github.com&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://pagist.github.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then Pagist will fetch the Gist, format the contents with Markdown, and apply Mathjax. Here’s how it looks like:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;http://i.imgur.com/1xKwJ.png&quot; alt=&quot;Pagist Example&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The good thing is that Gists are editble, so I can just edit the Gist and when I refresh
the page, I can see new content. &lt;a href=&quot;http://pagist.github.com/?3899155&quot;&gt;Here’s an example of a Pagist&lt;/a&gt;,
which is generated from &lt;a href=&quot;https://gist.github.com/3899155&quot;&gt;this Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pagist also allows raw HTML, CSS and JavaScript. So you can make dynamic pages quickly from Pagist.
&lt;a href=&quot;http://pagist.github.com/?3899782&quot;&gt;See the Pagist Kitchen Sink&lt;/a&gt;.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/Pagist</link>
                <guid>http://me.dt.in.th/page/Pagist</guid>
                <pubDate>2012-10-17T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Poor, Poor Return Key!</title>
                <description>&lt;p&gt;Just a diary for myself. Yesterday, while I was using my MacBook Pro normally,
&lt;strong&gt;a soft touch on the return key broke it apart into two pieces.&lt;/strong&gt;&lt;/p&gt;
&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/PoorPoorReturnKey-1.jpg&quot; alt=&quot;it broke :(&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Right then I panicked. The Return key is one of the key I use
constantly, for 278 days, and not being able to press it in a comfortable way
could greatly impact my productivity.&lt;/p&gt;

&lt;p&gt;Lucky for me that I still have my old MacBook with me
(Early 2008 Model), so I think
&lt;em&gt;maybe I should try replace the Return key with my old MacBook’s&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I researched on YouTube about how to replace MacBook keys,
and I found a video on
&lt;a href=&quot;http://www.youtube.com/watch?v=XItAVpHt3GU&quot;&gt;removing the Return key&lt;/a&gt;.
So I practiced with some other keys in my old MacBook first.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The video recommended that we use some kind flat screwdriver
because that’s a lot easier, but I don’t have it with me at that time,
and that was late at night.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;The best alternative is, well, a &lt;strong&gt;Lancer Spiral&lt;/strong&gt;.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/PoorPoorReturnKey-LancerSpiral.jpg&quot; alt=&quot;lancer spiral&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;After tens of minutes of fiddling,
I managed to pop the Return key out, but then underneath the key,
the two models have different layout. Forcing it into my MacBook Pro’s
keyboard made the key stuck and made it even harder to press return.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/PoorPoorReturnKey-ReturnVS.jpg&quot; alt=&quot;different mechanics&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now I’m totally out of luck.
But thank God I suddenly feel like there’s nothing better to do, then
let’s just pop the Caps Lock key out for brevity.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;And looking below, &lt;em&gt;the layout underneath the key matches exactly!&lt;/em&gt;&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;So I just push it back in place of the broken Return key and voila:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/PoorPoorReturnKey-2.jpg&quot; alt=&quot;yay&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p class=&quot;center&quot;&gt;Oh and finally, where did my old Return key go?&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;Well,&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/PoorPoorReturnKey-Where.jpg&quot; alt=&quot;yay&quot; /&gt;&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/PoorPoorReturnKey</link>
                <guid>http://me.dt.in.th/page/PoorPoorReturnKey</guid>
                <pubDate>2012-09-12T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Serve Google Spreadsheet as JSONP (JavaScript)</title>
                <description>&lt;p&gt;While creating a Live Scoreboard for this year’s
&lt;a href=&quot;http://www.miniarcadethailand.com/technikachampionship.php&quot;&gt;DJMAX Technika Thailand Championship&lt;/a&gt;,
some of the data (list of participants, offline judge results) are stored on Google Spreadsheets.&lt;/p&gt;

&lt;p&gt;I need to find a way to incorporate these data into the web app,
and I find a &lt;strong&gt;purely client-side&lt;/strong&gt; way to do it.&lt;/p&gt;
&lt;h2 id=&quot;preparing-the-spreadsheet&quot;&gt;Preparing the Spreadsheet&lt;/h2&gt;

&lt;p&gt;Create a new sheet in the spreadsheet, call it “JS”. And fill in the sheet like this:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/SpreadsheetToJSONP-before.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;create-a-google-apps-script&quot;&gt;Create a Google Apps Script&lt;/h2&gt;

&lt;p&gt;Go to &lt;em&gt;Tools&lt;/em&gt; -&amp;gt; &lt;em&gt;Script Editor&lt;/em&gt; to create a script, paste in this code, and save:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SpreadsheetApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getActiveSpreadsheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getSheets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;JS&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                 &lt;span class=&quot;na&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getDataRange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;SpreadsheetApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getActiveSpreadsheet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getSheetByName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;JS&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getRange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;B1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Basically, what is does is this: when the spreadsheet is edited,
the script gets all the sheets, filter out the one named JS,
and create an object representing the sheet and all its values for each sheet.&lt;/p&gt;

&lt;p&gt;Finally, these objects are stringified into JSON, and are put on the B1 cell
of the JS sheet.&lt;/p&gt;

&lt;h2 id=&quot;make-some-change-and-behold&quot;&gt;Make some change, and behold&lt;/h2&gt;

&lt;p&gt;After you make changes in other sheets, and then switch to the JS sheet,
you will see that the B1 cell we first intentionally left blank at first now contains
the JSON representation of the other sheets.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/SpreadsheetToJSONP-after.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, what does it look like? A JavaScript code!&lt;/p&gt;

&lt;h2 id=&quot;publish-the-js-sheet&quot;&gt;Publish the JS sheet&lt;/h2&gt;

&lt;p&gt;Now, we can publish the JS sheet.
Tell it to auto publish so that the data is always fresh.&lt;/p&gt;

&lt;p&gt;Then, get the link to the publish data as &lt;strong&gt;TXT (Plain Text)&lt;/strong&gt;&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/SpreadsheetToJSONP-publish.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;include-it-in-your-web-page&quot;&gt;Include it in your web page!&lt;/h2&gt;

&lt;p&gt;Since the exported text is a valid JavaScript code, you can now include them
inside your page!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
function loadData(sheets) {
  alert(JSON.stringify(sheets));
}
&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://docs.google.com/spreadsheet/pub?key=...output=txt&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/SpreadsheetToJSONP</link>
                <guid>http://me.dt.in.th/page/SpreadsheetToJSONP</guid>
                <pubDate>2012-09-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>What I learned during refactoring JavaScript</title>
                <description>&lt;p&gt;I just refactored &lt;a href=&quot;/page/dtinthstagram&quot;&gt;dtinthstagram&lt;/a&gt; a bit, to make the code more concise,
also making use of &lt;a href=&quot;http://backbonejs.org/&quot;&gt;Backbone.js&lt;/a&gt;.
Here’s the experience of it.&lt;/p&gt;
&lt;p&gt;The current version, as of writing, has a lot of memory leaks.
When the view wants to update itself according to the change in the model,
it adds an observer to the model. That’s normal.&lt;/p&gt;

&lt;p&gt;But when the view is not used anymore, it does not remove the observer from the model.
The observer also references the view, obviously, because it needs to update the view.
So the view hangs around unused forever! Memory leak!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now the problems are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;My implementation of EventEmitter does not provide a way to remove event listeners.&lt;/em&gt;
That’s ridiculous. The solution is just &lt;strong&gt;use Backbone.Events instead&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;The view doesn’t know when it is not going to be used anymore.&lt;/em&gt;
Because the event listener is still around, it keeps a reference to the
view, thus to the DOM, so the memory leaks.
The solution is just to &lt;strong&gt;explicitly tell the view to GTFO&lt;/strong&gt;.
Then so view can go remove the DOM and clear any references to it,
and also unbind its observers from the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now for even more problems:&lt;/p&gt;

&lt;h2 id=&quot;the-code-is-already-ugly-enough&quot;&gt;The Code Is Already Ugly Enough!&lt;/h2&gt;

&lt;p&gt;Here is the code that enables and disables the refresh button,
the loading indicator, and the load more button.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When refreshing, the button should dim and should light back up when finished.&lt;/li&gt;
  &lt;li&gt;When loading more photos, the button should switch to a loading indicator, and switch back when finished.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty strightforward:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;that.feed.on('startLoading', function() {
	that.view.loading.show();
	that.view.loadMore.hide();
});
that.feed.on('finishLoading', function() {
	that.view.loading.hide();
	if (that.feed.hasNext()) {
		that.view.loadMore.show();
	}
});
that.view.loadMore.hide();

// ...

var refreshing = false;
that.feed.on('startRefreshing', function() {
	refreshing = true;
	that.view.refresh.addClass('dim');
});
that.feed.on('finishRefreshing', function() {
	refreshing = false;
	that.view.refresh.removeClass('dim');
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although it’s long, it doesn’t look bad. Just that the same logic is used over again.&lt;/p&gt;

&lt;p&gt;Here’s another piece of code that updates the like button, as well as the like indicator.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function updateLike() {
	view.likeIcon.data('icon').attr('fill', media.liked ? '#ffff99' : '#8b8685');
}
media.on('likeChanged', updateLike);
updateLike();

media.on('startLike', function() { view.likeIcon.addClass('dim'); });
media.on('finishLike', function() { view.likeIcon.removeClass('dim'); });
media.on('startReload', function() { view.right.addClass('dim'); });
media.on('finishReload', function() { view.right.removeClass('dim'); });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I think, when the view is no longer used, then I have to go and remove
each of the listeners that I just added, &lt;strong&gt;TO CLEAN UP ALL THE MESS THAT WAS
CAUSED TO THE MODEL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And if I forget to remove only one of the event listeners,
then the view would stay around forever, FOREVER!! Until the web page is unloaded.
Now we know how easy it is to cause a memory leak in JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There must be a better way!&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-i-learned-write-it-the-way-i-want-to-write-it-first&quot;&gt;What I learned: Write it the way I want to write it first!&lt;/h2&gt;

&lt;p&gt;Yes, forget all the APIs. Don’t forget the syntaxes.&lt;/p&gt;

&lt;p&gt;Then refine and implement the missing parts later. So I replaced those code with this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;binds(that.feed.status, that)
	.showWhile('loading', that.dom.loading)
	.hideWhile('loading', that.dom.loadMore)
	.toggleClass('refreshing', that.dom.refresh, 'dim')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function updateLike() {
	dom.likeIcon.data('icon').attr('fill',
		media.get('liked') ? '#ffff99' : '#8b8685');
}

binds(media, that)
	.toggleClass('liking', dom.likeIcon, 'dim')
	.toggleClass('reloading', dom.right, 'dim')
	.bind('liked', updateLike)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In my head is a design of a model-view binder that binds itself
to both the model and the view, and then:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When the model is changed, or when the binding is initially created,
the binder updates various elements &lt;strong&gt;inside&lt;/strong&gt; the view.&lt;/li&gt;
  &lt;li&gt;When the view is destroyed, the binder unbinds itself from the model and the view.
As of writing, I didn’t implement this yet, but it should be much easier than
binding and unbinding manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I go &lt;a href=&quot;https://github.com/dtinth/dtinthstagram/blob/backbone/binder.sjs&quot;&gt;implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;binds&lt;/code&gt; function&lt;/a&gt;,
the model-view binder, and problem solved.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to Chris Headley of WhoIsHostingThis.com for reporting the broken links. You might find &lt;a href=&quot;http://wiht.link/backbonejs-intro&quot;&gt;Backbone.js Introduction and Resources&lt;/a&gt; on WhoIsHostingThis.com useful.&lt;/em&gt;&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/ImplementLater</link>
                <guid>http://me.dt.in.th/page/ImplementLater</guid>
                <pubDate>2012-08-17T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Playing with mplayer and caca</title>
                <description>&lt;p&gt;I’m giving my friend a JavaScript and Node.js crash course through Skype, using &lt;a href=&quot;/page/ttycast&quot;&gt;ttycast&lt;/a&gt;
to stream my live terminal session through to friend. Then I talked to him about what command-line apps can do:
browsing the web, installing software, chatting, and watching movies right inside a Terminal!&lt;/p&gt;
&lt;p&gt;I’m giving my friend a JavaScript and Node.js crash course through Skype, using &lt;a href=&quot;/page/ttycast&quot;&gt;ttycast&lt;/a&gt;
to stream my live terminal session through to friend.&lt;/p&gt;

&lt;p&gt;After teaching, I talked to him about what Terminal apps can do, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; to convert all .wav files in current and subdirectory to .ogg file and delete the original wav files.&lt;/li&gt;
  &lt;li&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew&lt;/code&gt; to quickly install software.&lt;/li&gt;
  &lt;li&gt;Browsing the web with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elinks&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Chatting on Facebook using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finch&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Playing music using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mplayer&lt;/code&gt; (he hears it through Skype)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, playing movies on a Terminal!&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/caca-sintel.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p class=&quot;caption move-caption-up&quot;&gt;
&lt;b&gt;Sintel&lt;/b&gt;
  © copyright Blender Foundation | &lt;a href=&quot;http://www.sintel.org&quot;&gt;www.sintel.org&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;First, rebuild mplayer with libcaca.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew unlink mplayer
brew uninstall mplayer
brew install libcaca
brew install mplayer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then, stream the movie (&lt;a href=&quot;http://oreilly.com/pub/h/4441&quot;&gt;thanks to this post&lt;/a&gt;)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CACA_DRIVER=ncurses mplayer \
    -vf framestep=10 -vo caca -quiet \
    sintel-2048-surround.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-vf framestep=10&lt;/code&gt; tells mplayer to update every 10 frames so the movie doesn’t flicker too much.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-vo caca&lt;/code&gt; tells mplayer to output as a colored ASCII art.
Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-quiet&lt;/code&gt; tells mplayer not to display the current playing stats every frame, which interferes with the
terminal output.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Last but not least, I opened up VLC and streamed from iSight through network, and then told mplayer to stream from it:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/caca-isight.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/caca</link>
                <guid>http://me.dt.in.th/page/caca</guid>
                <pubDate>2012-08-16T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>dtinthstagram: Instagram Viewer for Web and Desktop</title>
                <description>&lt;p&gt;An Ajax app I made some time ago. It is an open-source super-smooth web-based Instagram viewer.
If you are an Instagram user, try it out! :D&lt;/p&gt;
&lt;ul class=&quot;features&quot;&gt;
&lt;li&gt;View your Instagram feed, like and comments on photos,&lt;br /&gt;in your &lt;b&gt;big computer screen&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Auto-refreshes and works minimized:&lt;br /&gt;come back some time later and view all new photos.&lt;/li&gt;
&lt;li&gt;Dark, slick and simple user interface with super-smooth animations.&lt;/li&gt;
&lt;li&gt;Free and open source! &lt;a href=&quot;https://github.com/dtinth/dtinthstagram/&quot;&gt;on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;try&quot;&gt;&lt;a href=&quot;http://dtinth.github.com/dtinthstagram/&quot;&gt;try it now&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;caption&quot;&gt;tested on Firefox, Safari and Chrome&lt;/p&gt;

&lt;h2 id=&quot;desktop-version-installation-instructions&quot;&gt;Desktop Version &lt;small&gt;(installation instructions)&lt;/small&gt;&lt;/h2&gt;

&lt;div&gt;&lt;div class=&quot;platform-box&quot;&gt;

&lt;/div&gt;

### Windows and Linux &lt;small&gt;(Chrome)&lt;/small&gt;

* Install &lt;a href=&quot;https://www.google.com/chrome&quot;&gt;&lt;b&gt;Google Chrome&lt;/b&gt;&lt;/a&gt;
* Open &lt;a href=&quot;http://dtinth.github.com/dtinthstagram/&quot;&gt;dtinthstagram&lt;/a&gt; with Google Chrome
* Click the Wrench Icon, &lt;b&gt;Tools&lt;/b&gt; and then &lt;b&gt;Create Application Shortcuts&lt;/b&gt;
* Click &lt;b&gt;Create&lt;/b&gt; to finish. Next time, run dtinthstagram from your desktop.



&lt;div&gt;&lt;/div&gt;&lt;div class=&quot;platform-box&quot;&gt;

&lt;/div&gt;

### Mac OS X &lt;small&gt;(Fluid)&lt;/small&gt;

* Install &lt;a href=&quot;http://fluidapp.com/&quot;&gt;&lt;b&gt;Fluid&lt;/b&gt;&lt;/a&gt;
* Run the Fluid app.
* In the URL field, type in:&lt;br /&gt;http://dtinth.github.com/dtinthstagram/
* In the Name field, type in:&lt;br /&gt;&lt;b&gt;dtinthstagram&lt;/b&gt;
* Click &lt;b&gt;Create&lt;/b&gt; to finish. Next time, run the newly-created dtinthstagram app.



&lt;div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;/div&gt;

&lt;div&gt;&lt;p class=&quot;center image&quot;&gt;&lt;img src=&quot;/images/dtinthstagram.png&quot; /&gt;&lt;/p&gt;

&lt;/div&gt;
</description>
                <link>http://me.dt.in.th/page/dtinthstagram</link>
                <guid>http://me.dt.in.th/page/dtinthstagram</guid>
                <pubDate>2012-08-14T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Remote Camera Shutter for a Jailbroken iPad Powered by Node.js</title>
                <description>&lt;p&gt;Yesterday, I went to &lt;strong&gt;&lt;em&gt;Chocolate Ville&lt;/em&gt;&lt;/strong&gt;, a very beautiful restaurant,
planning to take bunch of photos.
I went with many friends, my MacBook Pro and my New iPad.&lt;/p&gt;

&lt;p&gt;After the food is ordered, my friends went to look around and take more photos,
while I and another friend were waiting for the food &lt;i&gt;(someone has to look for
our belongings)&lt;/i&gt;, I then felt like oh it’s a nice idea to take photos of
everyone.&lt;/p&gt;

&lt;p&gt;…but instead of asking the waitress to take a photo for us, I think
&lt;em&gt;I’d make my MacBook press the shutter button on my iPad for me.&lt;/em&gt;
So while waiting for the food, I quickly created a remote shutter in Node.js.&lt;/p&gt;
&lt;hr /&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img alt=&quot;iPad Remote Shutter&quot; src=&quot;/images/iPad-RemoteShutter.jpg&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;caption&quot;&gt;A Node.js server sending tap events to the iPad through Veency.&lt;/p&gt;

&lt;h2 id=&quot;on-the-ipad&quot;&gt;On the iPad&lt;/h2&gt;

&lt;p&gt;On the iPad, I installed “&lt;strong&gt;Veency&lt;/strong&gt;”, which is a VNC server for the iPad,
from Cydia. That’s all.&lt;/p&gt;

&lt;p&gt;Make sure you enabled the server and set the password to something.&lt;/p&gt;

&lt;p&gt;Then I used the normal camera app to take photos.&lt;/p&gt;

&lt;h2 id=&quot;on-my-laptop&quot;&gt;On My Laptop&lt;/h2&gt;

&lt;p&gt;First, I tried connecting my iPad to my MacBook through Bluetooth PAN,
but the remote shutter works for like 2–3 meters and is so delayed.
So I recommend you to &lt;em&gt;set up an ad-hoc wireless network&lt;/em&gt;.
Static IP is recommended because that makes these 2 devices see each other
more quickly.&lt;/p&gt;

&lt;h2 id=&quot;the-nodejs-server&quot;&gt;The Node.js Server&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/substack&quot;&gt;substack&lt;/a&gt; has made the excellent
&lt;a href=&quot;https://github.com/substack/node-rfb&quot;&gt;rfb&lt;/a&gt; module that lets Node connect
to a VNC server. I also used &lt;a href=&quot;http://www.senchalabs.org/connect/&quot;&gt;connect&lt;/a&gt;
so that I build the web server more quickly. So,&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rfb connect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the app code (this code is refined to work better):&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RFB&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;rfb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RFB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;securityType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;vnc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;connecting&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dimensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;connected&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/click&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\/([\d\.]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)\/([\d\.]&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;text/plain&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nextTick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2271&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;Basically, what this code does is connecting to the VNC server, which is my
iPad, and then starts a web server. If I go to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;http://&lt;b&gt;&lt;/b&gt;localhost:2271/click/0.95/0.5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will tap on the iPad at the point (0.95, 0.5) in the screen.
The point in the screen is defined in range 0–1, where 0 is left/top and
1 is right/bottom.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Note that the &lt;strong&gt;coordinates are independent of the orientation of the device.&lt;/strong&gt;
The left side of the iPad screen is always
&lt;em&gt;the side that the home button resides.&lt;/em&gt; If you rotate your iPad, you have to
rotate the numbers too if you want it to click on the same button.&lt;/p&gt;

&lt;h2 id=&quot;using-it&quot;&gt;Using It&lt;/h2&gt;

&lt;p&gt;Now, after the iPad and the laptop is in the same wireless network, run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node app.js 192.168.43.42 vncpass1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Change the IP and your VNC password accordingly, then if it works, it
should say “connected” along with the dimensions of the screen.&lt;/p&gt;

&lt;p&gt;Then on the iPad, fire up the Camera app, and rotate your screen so that
the lens are at the top, and the on-screen shutter button is on the same
side as the home button.&lt;/p&gt;

&lt;p&gt;Then fire the web browser to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;http://&lt;b&gt;&lt;/b&gt;localhost:2271/click/0.05/0.5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;The shutter button should act like it is actually tapped by a finger,
and a photo should be taken, and the browser should say “ok”.&lt;/p&gt;

&lt;p&gt;Now to take more photos, you just press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd+R&lt;/code&gt; on your keyboard and
the shutter will be pressed again.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In closing, I think it is pretty amazing that with Node.js and the
right module, it’s possible to make a working remote camera shutter
in less than 30 lines of code and within 10 minutes while waiting for the
food to be served.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/iPad-RemoteShutter</link>
                <guid>http://me.dt.in.th/page/iPad-RemoteShutter</guid>
                <pubDate>2012-07-20T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>XULRunner App Development Experience</title>
                <description>&lt;p&gt;#thaiWitter has been using the engine in Firefox 3.6 since 2011,
and I attempt to roll my own #thaiWitter app in XULRunner.&lt;/p&gt;

&lt;p&gt;This blog post describes its experience.&lt;/p&gt;
&lt;p&gt;This blog post doesn’t cover how to write XUL applications, you better read about it on the MDN.&lt;/p&gt;

&lt;p&gt;This blog post covers about how to run a XUL application on various platform,
because XULRunner sometimes like to act very strangely in some platform.&lt;/p&gt;

&lt;p&gt;At the time of writing, it’s XULRunner 13.0.2. And the XUL articles on MDN is very outdated.&lt;/p&gt;

&lt;h2 id=&quot;on-the-mac&quot;&gt;On The Mac&lt;/h2&gt;

&lt;p&gt;I started with the Mac platform. I followed the tutorial to create a XUL application.
I got all the chrome stuff ready and ready to run the application.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xulrunner `pwd`/application.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Didn’t work. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--install-app&lt;/code&gt; also doesn’t work.&lt;/p&gt;

&lt;p&gt;So I think I will have to package an application bundle first to be able
to try it out, &lt;strong&gt;and that worked.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I followed the steps described in
&lt;a href=&quot;https://developer.mozilla.org/en/XULRunner/Deploying_XULRunner_1.8&quot;&gt;Deploying XULRunner&lt;/a&gt;
article, to the point of running the app:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./thaiWitter-DEV.app/Contents/MacOS/xulrunner
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It complains about library not found and stuff. It turns out that I have to copy (or symlink)
all the .dylib files from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frameworks/XUL.Framework/&lt;/code&gt; into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt; folder too.&lt;/p&gt;

&lt;p&gt;…and finally, it runs, it runs!&lt;/p&gt;

&lt;p&gt;So therefore I assembled a build script that packages the application, available here:
&lt;a href=&quot;https://github.com/dtinth/xulrunner-twclient/tree/master/osx&quot;&gt;dtinth/xulrunner-twclient/osx&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;windows&quot;&gt;Windows&lt;/h2&gt;

&lt;p&gt;On Windows, however, it’s much more straightforward. Just follow the
&lt;a href=&quot;https://developer.mozilla.org/en/XULRunner/Deploying_XULRunner_1.8&quot;&gt;deploying XULRunner&lt;/a&gt;
article and everything should work just fine.&lt;/p&gt;

&lt;p&gt;To change the icon of the window (by default windows will show the blue globe icon),
just add an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ico&lt;/code&gt; file with the name matching the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; property of the window to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chrome/icons/default&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;So if I have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;window id=&quot;tw-main-window&quot;&amp;gt;&lt;/code&gt;, I’d put my app icon on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chrome/icons/default/tw-main-window.ico&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On Windows, I like to distribute my app as a “portable app,” so I also made a
batch script that copies stuff to make a runnable app, available here:
&lt;a href=&quot;https://github.com/dtinth/xulrunner-twclient/tree/master/win&quot;&gt;dtinth/xulrunner-twclient/win&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;/h2&gt;

&lt;p&gt;Not yet lol&lt;/p&gt;

&lt;p&gt;When the linux version is out, I’ll update this post.
But I guess that it’s straightforward, just follow the deploy guide and things should work well.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/xulapp</link>
                <guid>http://me.dt.in.th/page/xulapp</guid>
                <pubDate>2012-07-12T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>ttycast: Broadcast your tty to the world!</title>
                <description>&lt;p&gt;&lt;a href=&quot;https://github.com/dtinth/ttycast&quot;&gt;&lt;strong&gt;ttycast&lt;/strong&gt;&lt;/a&gt; is a Node.js app that allows you to
broadcast your tty online, in really real time!&lt;/p&gt;
&lt;p&gt;Sometimes I teach my friends some programming over Skype, and to show them code,
I have to share my screen or paste my code in the chat box and let him try out himself.&lt;/p&gt;

&lt;p&gt;Sharing screen is usually slow, and has very low frame rate.
And I can’t figure out how to share part of my screen.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now I really like &lt;a href=&quot;https://www.destroyallsoftware.com/&quot;&gt;Destroy All Software&lt;/a&gt;’s screencasts,
where almost everything in his screencasts is &lt;em&gt;done inside a terminal&lt;/em&gt;. I am really inspired by it
and think:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wouldn’t it be great if I can share what I’m seeing inside a terminal easily?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think it’d be very fast, because only text needs to be sent, I think it’ll be very smooth like
when I use SSH. I also see that there’s already a terminal emulator written in JavaScript out there
and there’s already a tool to record my terminal screen, &lt;a href=&quot;http://0xcc.net/ttyrec/index.html.en&quot;&gt;ttyrec&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;introducing-ttycast&quot;&gt;Introducing ttycast&lt;/h2&gt;

&lt;p&gt;This app is a result of putting together several libraries:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.senchalabs.org/connect/&quot;&gt;Connect&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/chjj/tty.js&quot;&gt;tty.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://socket.io/&quot;&gt;socket.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and there’s less than 80 lines of my code.&lt;/p&gt;

&lt;p&gt;So, to get started, just &lt;a href=&quot;https://github.com/dtinth/ttycast#readme&quot;&gt;read the README!&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;/images/ttycast-1.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/ttycast</link>
                <guid>http://me.dt.in.th/page/ttycast</guid>
                <pubDate>2012-07-07T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Divide Money - My first app written using Knockout.js</title>
                <description>&lt;p&gt;I just came from an HTML5 training.
The instructors taught us some basic jQuery and
told us to make an app about lifestyle.&lt;/p&gt;

&lt;p&gt;So I think I’d try something new, so instead I play with Knockout.js&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here is the result&lt;/strong&gt;: &lt;a href=&quot;http://thai.org.org/money/&quot;&gt;Divide Money App&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is an app to help you to figure out how much one needs to pay when
eating at a restaurant. It is designed to be flexible so that it works
with almost any situation.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;After the experience, I found out that it’s extremely easy to build
very rich app with this. You can add, change, and remove people
and food, and the UI and results updates itself automatically.&lt;/p&gt;

&lt;p&gt;And all of that is done with Knockout in less than 300 lines of code,
which for me is really amazing.&lt;/p&gt;

&lt;p&gt;So I definitely recommend playing with it: &lt;a href=&quot;http://knockoutjs.com/&quot;&gt;&lt;strong&gt;Knockout&lt;/strong&gt;&lt;/a&gt;!&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/DivideMoney</link>
                <guid>http://me.dt.in.th/page/DivideMoney</guid>
                <pubDate>2012-07-07T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>pmd: A Command-Line Pomodoro Timer for Mac</title>
                <description>&lt;p&gt;Today, I started applying &lt;a href=&quot;http://www.pomodorotechnique.com/&quot;&gt;The Pomodoro Technique&lt;/a&gt;, so I
made for myself a simple countdown timer.&lt;/p&gt;

&lt;p&gt;This blog post also covers how to make a NSStatusItem that lives at the far right of the items.&lt;/p&gt;
&lt;p&gt;As I usually work with the Terminal, this app must be easily usable from the Terminal.
But I also want to always see the time remaining.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href=&quot;https://github.com/dtinth/pmd&quot;&gt;pmd&lt;/a&gt;. It is invoked from the command-line, and
displays the remaining time at the status bar, finally, it sends a Growl notification.&lt;/p&gt;

&lt;p&gt;The command is written in Shell Script, with the countdown timer written in MacRuby.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;To use, just invoke from the terminal:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pmd start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then the countdown will show.&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img alt=&quot;pmd screenshot&quot; src=&quot;/images/pmd.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;making-a-status-bar-item-go-far-right&quot;&gt;Making a Status Bar Item Go Far Right&lt;/h2&gt;

&lt;p&gt;Originally, I wrote the countdown in Objective-C and working with it feels like an overkill.
There is an Xcode project file, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.m&lt;/code&gt;, the app delegate stuff (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.m&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.h&lt;/code&gt;), a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xib&lt;/code&gt; file,
and finally an .app file.
So I rewrote it in &lt;a href=&quot;https://github.com/dtinth/pmd/blob/master/pmd-counter&quot;&gt;42 lines of MacRuby&lt;/a&gt;.
The code shown here will be from the Objective-C version though.&lt;/p&gt;

&lt;p&gt;Usually, when running a status bar application, the new status bar item gets added
&lt;strong&gt;to the left&lt;/strong&gt; of the status bar.&lt;/p&gt;

&lt;p&gt;To make it go to far right, we must use &lt;a href=&quot;http://cocoadev.com/wiki/NSStatusItem&quot;&gt;Cocoa’s private API&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;statusItem = [[NSStatusBar systemStatusBar] _statusItemWithLength:0.0 withPriority:INT_MAX];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But the length parameter is not used when doing it this way, so after creating the item, we
need to set its length.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[statusItem setLength:NSVariableStatusItemLength];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/pmd</link>
                <guid>http://me.dt.in.th/page/pmd</guid>
                <pubDate>2012-06-29T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>tos3: An extremely simple tool to sync local files to Amazon S3.</title>
                <description>&lt;p&gt;For some time blog has been running on a Ruby on Rails webapp hosted on Heroku, which makes it feels somewhat “slow”. So I decided to make my website totally static and host them somewhere.&lt;/p&gt;

&lt;p&gt;I got the blog engine done and then wondered where and how to put these static files. I chose Amazon S3 and tried to find a nice way to put the files up. I ended up writing &lt;a href=&quot;https://github.com/dtinth/tos3&quot;&gt;my own syncer in Java&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-java&quot;&gt;Why Java?&lt;/h2&gt;
&lt;p&gt;Well, because I love its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt; class and how it abstracts the file system, so I can use them consistently on all platform. I don’t have to worry about slashes and backslashes.&lt;/p&gt;

&lt;p&gt;Then, because Amazon AWS has a Java SDK.&lt;/p&gt;

&lt;p&gt;Another nice thing is that I can compile it to a single .jar file and then run it on all platforms.&lt;/p&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;p&gt;After compiling, you can run it like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;java -jar tos3.jar &amp;lt;directory&amp;gt; &amp;lt;bucket&amp;gt; &amp;lt;path-to-s3credentials.properties&amp;gt; preview
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;directory&amp;gt;&lt;/code&gt; and list of files in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;bucket&amp;gt;&lt;/code&gt;, and compares them to show what file needs to be added or removed.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;path-to-s3credentials.properties&amp;gt;&lt;/code&gt; is path to your credentials file, which should look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;accessKey=YOUR_ACCESS_KEY
secretKey=YOUR_SECRET_KEY
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After you’re sure about what you’re going to upload, you can remove the “preview” part, and then tos3 will actually upload and remove files on s3.&lt;/p&gt;

&lt;h2 id=&quot;noexhtml&quot;&gt;.noex.html&lt;/h2&gt;
&lt;p&gt;For pretty URLs, I prefer that many URLs don’t have file extension, but served like an HTML file. For instance, this blog post URL doesn’t have the file extension.&lt;/p&gt;

&lt;p&gt;For dynamic sites this can be achieved easily, and for static sites this app handles it for you: &lt;em&gt;any file whose name ends with .noex.(whatever) will have that part removed when uploading&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So actually on my local computer this blog post resides at “page/tos3.noex.html”, but when uploaded it will go to “page/tos3” instead.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/tos3</link>
                <guid>http://me.dt.in.th/page/tos3</guid>
                <pubDate>2012-06-25T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>sgvc</title>
                <description>&lt;p&gt;This is my new static site generator system,
inspired by &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;, but is written in Node.js.
The name stands for 
Static &lt;em&gt;S&lt;/em&gt;ite &lt;em&gt;G&lt;/em&gt;enerator using &lt;em&gt;V&lt;/em&gt;iews and &lt;em&gt;C&lt;/em&gt;ontents.
It aims to be extremely flexible.&lt;/p&gt;
&lt;p&gt;Before that, this website is running on a Ruby on Rails application,
but I think that Ruby on Rails is too complex for this kind of simple blog,
so I think writing a static site generator is better.&lt;/p&gt;

&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Each post is a single text file, which corresponds to a single file.&lt;/li&gt;
  &lt;li&gt;Write posts using a combination of Markdown and HTML. You can switch back and forth between Markdown and HTML using a special syntax.&lt;/li&gt;
  &lt;li&gt;Each post can define its own CSS and JavaScript, so each blog post can be different.&lt;/li&gt;
  &lt;li&gt;Each post can define parameters, which then can be understood by the layout.
    &lt;ul&gt;
      &lt;li&gt;For example, each post has to define a title, which the blog engine will then use to display on the list.&lt;/li&gt;
      &lt;li&gt;Each post can also define custom parameters, such as the “comments” parameter, and the layout can decide by this parameter whether to
display the Disqus comment box or whatever.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The index page is a single page which displays all of the posts.&lt;/li&gt;
  &lt;li&gt;Each post can also have a preamble (Markdown only), which will be displayed on the index page.&lt;/li&gt;
&lt;/ul&gt;

</description>
                <link>http://me.dt.in.th/page/sgvc</link>
                <guid>http://me.dt.in.th/page/sgvc</guid>
                <pubDate>2012-06-17T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Quick Note about Jailcoder</title>
                <description>&lt;p&gt;Just tried using &lt;a href=&quot;http://jailcoder.com/&quot;&gt;Jailcoder&lt;/a&gt; to build and run iOS apps on my iPad.
So here is a quick how to.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Jailbreak the iDevice.&lt;/li&gt;
  &lt;li&gt;Install AppSync from cydia.hackulo.us repo.&lt;/li&gt;
  &lt;li&gt;Install &lt;a href=&quot;http://jailcoder.com/&quot;&gt;Jailcoder&lt;/a&gt; and patch your Xcode.&lt;/li&gt;
  &lt;li&gt;After creating, patch your Project.&lt;/li&gt;
  &lt;li&gt;Build the app for the iDevice.&lt;/li&gt;
  &lt;li&gt;Click run and your app should run.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;But when app doesn’t run:&lt;/p&gt;

&lt;h3 id=&quot;xcode-cannot-run-using-the-selected-device-no-provisioned-ios-devices-are-available-with-a-compatible-ios-version&quot;&gt;&lt;em&gt;Xcode cannot run using the selected device.&lt;/em&gt; No provisioned iOS devices are available with a compatible iOS version.&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Make sure the deployment target is set to the right version on your device.&lt;/li&gt;
  &lt;li&gt;Go to the organizer and click “use for development” on your device. There is no need to sign in.&lt;/li&gt;
  &lt;li&gt;Try disconnecting and reconnecting your iDevice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;build-failed-with-something-about-no-certificate&quot;&gt;Build failed with something about no certificate.&lt;/h3&gt;

&lt;p&gt;Make sure the project is patched.&lt;/p&gt;

&lt;h3 id=&quot;app-doesnt-install-and-complains-something-about-installd&quot;&gt;App doesn’t install and complains something about installd.&lt;/h3&gt;

&lt;p&gt;Make sure AppSync is installed.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/Jailcoder</link>
                <guid>http://me.dt.in.th/page/Jailcoder</guid>
                <pubDate>2012-05-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Fluid (Mac): Fix Back Button Breaking the JavaScript API</title>
                <description>&lt;p&gt;While I was making &lt;a href=&quot;http://dtinth.github.com/dtinthstagram/&quot;&gt;dtinthstagram&lt;/a&gt;, I thought that it would be a good idea to make it work in &lt;a href=&quot;http://fluidapp.com/&quot;&gt;Fluid&lt;/a&gt;, as well as a support for dock badges.&lt;/p&gt;

&lt;p&gt;So I implemented it in a straightforward way. Then I found that going to other page and back to the old page breaks the Fluid JavaScript API.&lt;/p&gt;
&lt;p&gt;When navigating to another page, the API gets destroyed. When the user return back to the old page, calls to the API generates an error:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ReferenceError: Trying to access object from destroyed plug-in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I contacted the developer of Fluid, but for now, I came up with a workaround that works pretty well.&lt;/p&gt;

&lt;p&gt;I fixed the problem by checking, if invoking the Fluid API generates an error, then create a hidden iframe (which Fluid will initialize another JavaScript API instance inside it), and then use the API of the iframe instead.&lt;/p&gt;

&lt;p&gt;The code goes like this (comments added):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// holds the reference to the window
// that holds the Fluid JavaScript API.
var fluidHoster = window;

// the iframe instance, if any.
var fluidIframe = null;

// the text queued to show on the dock badge.
var fluidQueuedText = null;

function setDockBadge(text) {
	if ('fluid' in window) {
		try {
			if (fluidHoster == null) {
				// the iframe did not finish loading, queue the text
				fluidQueuedText = text;
			} else {
				// try calling the API
				fluidHoster.fluid.dockBadge = text;
			}
		} catch (e) {

			// in case of error, queue the text,
			fluidHoster = null;
			fluidQueuedText = text;

			// trash the old iframe,
			if (fluidIframe != null &amp;amp;&amp;amp; fluidIframe.parentNode) {
				fluidIframe.parentNode.removeChild(fluidIframe);
			}

			// create a new iframe,
			var iframe = fluidIframe = document.createElement('iframe');

			// make it display the queued text on the dock
			// when the API is ready
			iframe.onload = function() {
				fluidHoster = iframe.contentWindow;
				fluidHoster.fluid.dockBadge = fluidQueuedText;
			};

			// add to document.body
			iframe.src = 'about:blank';
			iframe.style.display = 'none';
			document.body.appendChild(iframe);

		}
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
                <link>http://me.dt.in.th/page/FluidBackButton</link>
                <guid>http://me.dt.in.th/page/FluidBackButton</guid>
                <pubDate>2012-04-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>About ActionListeners</title>
                <description>&lt;p&gt;I’ve been chatting some OOP with a friend, who went to an army camp during the Object-Oriented Programming class. So I explained to him a bit on how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionListener&lt;/code&gt;s work. And here’s how the conversation went:&lt;/p&gt;
&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;I’ll have to introduce you to a concept of what we call “Listener”.&lt;/p&gt;

  &lt;p&gt;Normally, when we add buttons, we want something to happen when user clicks it.&lt;/p&gt;

  &lt;p&gt;And in Java Swing, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionListener&lt;/code&gt;s.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;actionlistener-basics&quot;&gt;ActionListener Basics&lt;/h2&gt;

&lt;p&gt;What are action listeners? They are classes that implements the interface ActionListener.&lt;/p&gt;

&lt;p&gt;And they have one required method: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void actionPerformed(ActionEvent event)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, when you create a button, and you want something to happen, you create an action listener, and add it to the button.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ActionListener listener = new MyButtonListener();
 button.addActionListener(listener);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above code basically says to the button, “if someone presses you, call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actionPerformed&lt;/code&gt; method of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listener&lt;/code&gt;”&lt;/p&gt;

&lt;h2 id=&quot;actionlisteners-are-flexible&quot;&gt;ActionListeners are flexible&lt;/h2&gt;

&lt;p&gt;[…] a button can have many action listeners. And one action listener can be added to multiple buttons, or other components that can perform action, or even a swing timer.&lt;/p&gt;

&lt;p&gt;When a button is clicked, in Swing, we say that “an action is performed on the button”. That’s why we use the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actionPerformed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, when a menu item is clicked, we also say, “an action is performed on the menu item”. For a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JTextField&lt;/code&gt;, when use enters a text and then press ENTER, then an action is performed on that text field.&lt;/p&gt;

&lt;p&gt;For Swing timers, when it’s the specified time, the timer will perform some action.&lt;/p&gt;

&lt;h2 id=&quot;other-kinds-of-listeners&quot;&gt;Other kinds of Listeners&lt;/h2&gt;

&lt;p&gt;For many components, actions can be performed on them. But it’s different for each component on how can the user perform action on it.&lt;/p&gt;

&lt;p&gt;So that’s why sometimes, ActionListener is not enough. For example, for a JTextField, we may want to know when a key is pressed, not just when the user press Enter.&lt;/p&gt;

&lt;p&gt;So on JTextField, we also have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addKeyListener(KeyListener)&lt;/code&gt;, and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeyListener&lt;/code&gt; interface, that has 3 methods, each receiving a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeyEvent&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyTyped&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyPressed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyReleased&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And also, sometimes, maybe we want to detect when the user moves mouse over the button (or maybe another component), we can use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MouseListener&lt;/code&gt; and/or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MouseMotionListener&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hope that kinds of explained it.&lt;/p&gt;
</description>
                <link>http://me.dt.in.th/page/OOP-ActionListeners</link>
                <guid>http://me.dt.in.th/page/OOP-ActionListeners</guid>
                <pubDate>2012-03-05T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Stylus Snippet - Deopacify</title>
                <description>&lt;p&gt;What it does, given a &lt;em&gt;background color&lt;/em&gt;, an &lt;em&gt;opacity&lt;/em&gt;, and a &lt;em&gt;target color&lt;/em&gt;: It finds a color which when drawn on the &lt;em&gt;background color&lt;/em&gt; with the given &lt;em&gt;opacity&lt;/em&gt;, results in the &lt;em&gt;target color&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When I was making &lt;a href=&quot;http://userstyles.org/styles/56731/facebook-dark-facebook&quot;&gt;dark-facebook&lt;/a&gt;, I noticed a performance drop because lots of opacity use in images.&lt;/p&gt;

&lt;p&gt;For example, I darkened the icons by applying opacity on the icon. And for text I just use gray (but the gray that I use everywhere).&lt;/p&gt;

&lt;ul class=&quot;example ex-1&quot;&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Though it doesn’t look laggy here, it does on Facebook because of its page complexity.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I tried another experiment, by changing the opacity of the whole list.&lt;/p&gt;

&lt;ul class=&quot;example ex-2&quot;&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that did make it faster, but the text is also dimmed, but I still want it to be &lt;em&gt;that&lt;/em&gt; gray.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;That’s where this function comes in handy. I call it &lt;strong&gt;deopacify&lt;/strong&gt;, and it goes like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;deopacify($background, $alpha, $target)
	dv($fn, $bg-v, $target-v)
		$v = $bg-v + ($target-v - $bg-v) / $alpha
		if $v &amp;gt; 255
			warn('IMPOSSIBRU!! TOO BRIGHT! Would result in ' + $fn + ' = ' + $v)
			return 255
		else if $v &amp;lt; 0
			warn('IMPOSSIBRU!! TOO DARK! Would result in ' + $fn + ' = ' + $v)
			return 0
		else
			return $v
	rgb(dv('red', red($background), red($target)), dv('green', green($background), green($target)), dv('blue', blue($background), blue($target)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;So, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deopacify(#353433, 0.6, #8b8685)&lt;/code&gt; results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#c4bdbc&lt;/code&gt;, which is the color that is drawn on #353433 with 60% opacity and results in #8b8685.&lt;/p&gt;

&lt;p&gt;So let’s compare, the old method, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opacity&lt;/code&gt; in each image:&lt;/p&gt;

&lt;ul class=&quot;example ex-1&quot;&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and the new method with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opacity&lt;/code&gt; on the container.&lt;/p&gt;

&lt;ul class=&quot;example ex-2 ex-3&quot;&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;.&lt;/i&gt; text &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt; &lt;i&gt;.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looks the same, but if you select the text you’ll notice that the opacity is different.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;And it will warn you when you try to do impossible things, for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deopacify(#353433, 0.6, #fff)&lt;/code&gt; will generate the following warnings:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Warning: IMPOSSIBRU!! TOO BRIGHT! Would result in red = 389.6666666666667
Warning: IMPOSSIBRU!! TOO BRIGHT! Would result in green = 390.33333333333337
Warning: IMPOSSIBRU!! TOO BRIGHT! Would result in blue = 391
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Because there’s no way to draw white on dark gray with opacity less than 100% and still results in white.&lt;/p&gt;

&lt;p&gt;It will return the closest color it can find though, which in this case is #fff.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/stylDeopacify</link>
                <guid>http://me.dt.in.th/page/stylDeopacify</guid>
                <pubDate>2011-11-29T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>PhantomJS - Passing Variables to page.evaluate</title>
                <description>&lt;p&gt;When I was making an auto form submission script, I tried to find out how to pass data from outside script to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page.evaluate&lt;/code&gt; script. In all form submission examples that I’ve seen, they all use fixed data. As of 1.3.0, &lt;a href=&quot;http://code.google.com/p/phantomjs/issues/detail?id=132&quot;&gt;it’s still unsupported&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I thought I would pass it as a global variable instead.&lt;/p&gt;
&lt;p&gt;And here’s how I did it.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function setGlobal(page, name, data) {
	var json = JSON.stringify(data);
	var fn = 'return window[' + JSON.stringify(name) + ']=' + json + ';';
	return page.evaluate(new Function(fn));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(note: I tried adding it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebPage.prototype&lt;/code&gt; but it didn’t work)&lt;/p&gt;

&lt;p&gt;And then in the page handler:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;setGlobal(page, '__dt_credentials', credentials);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and finally the code inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page.evaluate&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;			un.value = __dt_credentials.username;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
                <link>http://me.dt.in.th/page/phantomjsPageEvaluate</link>
                <guid>http://me.dt.in.th/page/phantomjsPageEvaluate</guid>
                <pubDate>2011-11-23T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Generating a Tone on Internal PC Speaker (Linux C, C++)</title>
                <description>&lt;p&gt;So I played a bit with the PC Speaker like I like to do before in an AX-11.
I tried using Beep() on Windows 7, but it didn’t work, so I had to use Linux.
I searched a lot on the Internet for how to make it generate a tone so I’ll post it here for
future reference.&lt;/p&gt;
&lt;p&gt;By the way here’s the result:&lt;/p&gt;

&lt;div&gt;&lt;p class=&quot;youtube&quot;&gt;&lt;iframe width=&quot;640&quot; height=&quot;480&quot; src=&quot;http://www.youtube.com/embed/Dfudl0KNM-o&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;/div&gt;

&lt;h2 id=&quot;enabling-the-pc-speaker&quot;&gt;Enabling the PC Speaker&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo modprobe pcspkr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;linux/kd.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;

// ...
ioctl(STDOUT_FILENO, KIOCSOUND, 1193180 / freq);
usleep(wait);
ioctl(STDOUT_FILENO, KIOCSOUND, 0);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/4447166/how-to-use-pc-speaker-in-linux&quot;&gt;http://stackoverflow.com/questions/4447166/how-to-use-pc-speaker-in-linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ubuntuforums.org/showthread.php?t=873679&quot;&gt;http://ubuntuforums.org/showthread.php?t=873679&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
                <link>http://me.dt.in.th/page/pcspkrTone</link>
                <guid>http://me.dt.in.th/page/pcspkrTone</guid>
                <pubDate>2011-11-23T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>My Eclipse Color Theme</title>
                <description>&lt;p&gt;I just finished tweaking my Eclipse color theme.&lt;/p&gt;

&lt;p&gt;On code with good balance of code and documentation, it will have a mix of cool colors and warm colors. Without the comments and stuff, it will look reddish.&lt;/p&gt;
&lt;p&gt;Here’s how it looks like:&lt;/p&gt;

&lt;p class=&quot;image&quot;&gt;&lt;img src=&quot;http://dl.dropbox.com/u/25097375/me.dt.in.th/MyEclipseColorTheme.png&quot; alt=&quot;My Eclipse Color Theme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;http://www.eclipsecolorthemes.org/?view=theme&amp;amp;id=4552&quot;&gt;get it at Eclipse Color Themes!&lt;/a&gt;&lt;/p&gt;
</description>
                <link>http://me.dt.in.th/page/MyEclipseColorTheme</link>
                <guid>http://me.dt.in.th/page/MyEclipseColorTheme</guid>
                <pubDate>2011-11-18T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Gzipping Responses in Node.js + Express App (Obsoleted)</title>
                <description>&lt;p&gt;Not long ago while developing the #thaiWitter 3 server (Node.js + Express App), I realized that &lt;a href=&quot;http://stackoverflow.com/questions/7680947/how-to-enable-gzip-compression-on-heroku-cedar-python-flask-gunicorn&quot;&gt;Heroku/Cedar doesn’t gzip the output&lt;/a&gt;, so I need to gzip them myself. I go with &lt;a href=&quot;https://github.com/waveto/node-compress&quot;&gt;node-compress&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2012-06-25&lt;/strong&gt;: Since node 0.6 we now have &lt;a href=&quot;http://nodejs.org/api/zlib.html&quot;&gt;Zlib&lt;/a&gt; built-in, so
this post is no longer valid. Just &lt;a href=&quot;http://www.senchalabs.org/connect/compress.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use(connect.compress())&lt;/code&gt;&lt;/a&gt; hell yeah!&lt;/p&gt;

&lt;h2 id=&quot;gzipping-static-content&quot;&gt;Gzipping Static Content&lt;/h2&gt;

&lt;p&gt;My app has a lot of client side data, and they are served using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;express.static&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tomgallacher/gzippo&quot;&gt;gzippo&lt;/a&gt; is a drop-in replacement for it, so just install gzippo and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gzippo.staticGzip&lt;/code&gt; in place of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;express.static&lt;/code&gt;. It gzips the static data on-the-fly and cache them in memory.&lt;/p&gt;

&lt;h2 id=&quot;my-gzip-middleware&quot;&gt;My Gzip Middleware&lt;/h2&gt;

&lt;p&gt;I also need to Gzip the API output too, so I made my own middleware &lt;a href=&quot;https://github.com/dtinth/express-gzip&quot;&gt;express-gzip&lt;/a&gt;. And the &lt;a href=&quot;https://github.com/dtinth/express-gzip/blob/master/lib/express-gzip.js&quot;&gt;code that does the action here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It doesn’t get in your way, that means, you have to tell it to output Gzip yourself, but that’s easier for me. It adds 3 functions. 1 to the request object, and 2 to the response object.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;req.supportsGzip()&lt;/code&gt; - returns true if the browser supports Gzip&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;res.setGzipHeader()&lt;/code&gt; - sets the gzip headers for the response&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;res.sendGzipped(text, headers)&lt;/code&gt; - sends text data to the browser, gzipped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;res.sendGzipped()&lt;/code&gt; only allow UTF-8 encoded strings.&lt;/p&gt;

&lt;p&gt;I’m going to use it in the rest of this post.&lt;/p&gt;

&lt;h2 id=&quot;gzipping-api-responses&quot;&gt;Gzipping API Responses&lt;/h2&gt;

&lt;p&gt;As a web-based Twitter client, most of my API calls returns data from Twitter API as JSON. And JSON gzips very well!&lt;/p&gt;

&lt;p&gt;For that, at the final stage when sending output, I just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;res.sendGzipped&lt;/code&gt; from my middleware.&lt;/p&gt;

&lt;h2 id=&quot;gzipping-pre-gzipped-assets&quot;&gt;Gzipping Pre-gzipped Assets&lt;/h2&gt;

&lt;p&gt;The client-side JavaScript file is big, nearly 190k.&lt;/p&gt;

&lt;p&gt;I have a build script to Gzip them, and I use a separate request handler to load both the non-gzipped version and gzipped version into memory at startup time.&lt;/p&gt;

&lt;p&gt;I need to do that because when I compile assets, it goes to, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thaiWitterAsset1.js&lt;/code&gt;. But I also need a way to make the browser get the latest version. So I reference in the HTML file as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thaiWitterAsset1_[hash of the file].js&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;express.static&lt;/code&gt; couldn’t do that, so I need to make a new request handler. Surely I could just append a query string, but I heard from somewhere that it will not be cached as good as having the hash in the file name.&lt;/p&gt;

&lt;p&gt;The handler code looks something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	if (req.supportsGzip()) {
		res.setGzipHeader();
		return res.send(gzipped, headers);
	} else {
		return res.send(nonGzipped, headers);
	}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;performances&quot;&gt;Performances&lt;/h2&gt;

&lt;p&gt;So people at Connect and Express said that it is more of a loss to Gzip. It takes lot of power to serve Gzipped content and removed it in newer versions.&lt;/p&gt;

&lt;p&gt;But for me, my connection to Heroku wasn’t fast. So before I use Gzip, the home timeline loads in about 2.3s, but after I enable Gzip, it loads in about 1.5s. I didn’t remember the number, but it’s significantly faster.&lt;/p&gt;

&lt;p&gt;The size of the JSON output from the server reduced from 45k to around 8k and that makes it load faster.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/NodeJS-express-gzip</link>
                <guid>http://me.dt.in.th/page/NodeJS-express-gzip</guid>
                <pubDate>2011-11-10T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Checking for SSL in Node.js App on Heroku/Cedar</title>
                <description>&lt;p&gt;So in the preview of #thaiWitter 3 I’ve added Piggyback SSL to my Heroku app, and I couldn’t find a way for the app to check if it’s requested via SSL or not…&lt;/p&gt;
&lt;p&gt;…and for 3 days or so I have been checking on the client side and passing parameters to the API to indicate that the API call was secure, like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location.protocol == 'https:'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve tried looking at the environment variables and stuff (like in PHP or CGI applications, we like to look at environment variables to find out about the user) to find out nothing. It’s nothing like that anymore.&lt;/p&gt;

&lt;p&gt;Well, I forgot to look at the request headers. :(&lt;/p&gt;

&lt;p&gt;So I added a handler that shows all the request headers and found out. So now here’s how to check:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;req.headers['x-forwarded-proto'] == 'https'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
                <link>http://me.dt.in.th/page/HerokuNodeSSLCheck</link>
                <guid>http://me.dt.in.th/page/HerokuNodeSSLCheck</guid>
                <pubDate>2011-11-02T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>thaiWitter 3 RC</title>
                <description>&lt;p&gt;The newer version of thaiWitter (known as thaiWitter 3) is almost out&lt;/p&gt;
&lt;h2 id=&quot;downloads&quot;&gt;Downloads&lt;/h2&gt;

&lt;p&gt;You can download the latest builds at the main Downloads page: &lt;a href=&quot;http://docs.dt.in.th/thaiWitter/Download&quot;&gt;http://docs.dt.in.th/thaiWitter/Download&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;enable-user-stream--direct-api-call-in-firefox&quot;&gt;Enable User Stream / Direct API Call in Firefox&lt;/h2&gt;

&lt;p&gt;Please install the latest &lt;a href=&quot;https://github.com/dtinth/twclient2&quot;&gt;thaiWitter Client Extension&lt;/a&gt; which now works in thaiWitter beta.&lt;/p&gt;

&lt;h2 id=&quot;changelog&quot;&gt;Changelog&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;A bit refactored code. Now written in its own language thaiJS (compiles to JavaScript) ;p&lt;/li&gt;
  &lt;li&gt;Fixed many small bugs and lot of stuff.&lt;/li&gt;
  &lt;li&gt;Server rewritten in &lt;strong&gt;Node.js + Express&lt;/strong&gt; so very lightweight.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Live conversation view&lt;/strong&gt;: new tweets that are relevant to the conversation will now slide into the conversation view.&lt;/li&gt;
  &lt;li&gt;Has &lt;strong&gt;Logout / Change Account&lt;/strong&gt; button for re-authentication.&lt;/li&gt;
  &lt;li&gt;Has HTTPS thanks to Heroku.&lt;/li&gt;
  &lt;li&gt;Can &lt;a href=&quot;http://docs.dt.in.th/thaiWitter/Usage/FacebookIntegration&quot;&gt;&lt;strong&gt;post status updates to Facebook&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;New &lt;strong&gt;image upload system&lt;/strong&gt;. Can now post images to pic.twitter.com. Just drag and drop the images into the text box and send. User interface inspired from @manatsawin’s &lt;a href=&quot;http://t.whsgroup.ath.cx/&quot;&gt;Twitica Desktop&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Has the image preview feature, as suggested by @tannce and @icez. (Disabled by default).&lt;/li&gt;
  &lt;li&gt;Allows retweeting a retweet when the retweeter is protected, as reported by @PalmZenith.&lt;/li&gt;
  &lt;li&gt;When counting tweet text, all URLs will count as 20-21 characters because they will be shortened by t.co. Also each image upload will also count as 21 characters. And URL shorteners are now deprecated and gone.&lt;/li&gt;
  &lt;li&gt;Search feature is a more reliable, it now uses OAuth.&lt;/li&gt;
  &lt;li&gt;Displays “Twitter is over capacity” when Twitter is over capacity.&lt;/li&gt;
  &lt;li&gt;Lists timeline will now include retweets.&lt;/li&gt;
  &lt;li&gt;Can now follow/unfollow people/lists in-app.&lt;/li&gt;
  &lt;li&gt;Portable version: some common dialog UI adjustments :)&lt;/li&gt;
  &lt;li&gt;Portable version: now uses no-remote so you can run multiple instances of #thaiWitter at the same time. Just extract the package somewhere else.&lt;/li&gt;
  &lt;li&gt;When opening a new window, the new window’s size will match the size of the old window.&lt;/li&gt;
  &lt;li&gt;Too long words will be broken into lines using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;word-wrap: break-word&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;More (or less :P) mobile compatibility. Better touch handling in iOS.&lt;/li&gt;
  &lt;li&gt;Username auto-completion using Tab key.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.dt.in.th/thaiWitter/Usage/NewNotification&quot;&gt;&lt;strong&gt;New notification options&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
                <link>http://me.dt.in.th/page/thaiWitter3Preview</link>
                <guid>http://me.dt.in.th/page/thaiWitter3Preview</guid>
                <pubDate>2011-10-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>JavaScript - Asynchronous Loops</title>
                <description>&lt;p&gt;I’m been working on a little experiment that I need to process a set of images (loading it, and putting it in canvas, and then process it) sequentially.&lt;/p&gt;

&lt;p&gt;In JavaScript, image loading is asynchronous, so I made these utility functions that makes processing things sequentially a lot easier.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var asyncWhile = function(cond, body, fin) {
	function cont() { if (cond()) body(cont, brk); else brk(); }
	function brk() { if (fin) fin(); }
	cont();
};

var asyncFor = function(init, cond, next, body, fin) {
	init();
	asyncWhile(cond, function(cont, brk) {
		body(function() { next(); cont(); }, brk);
	}, fin);
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;asyncwhile&quot;&gt;asyncWhile&lt;/h2&gt;

&lt;p&gt;This function, &lt;strong&gt;asyncWhile&lt;/strong&gt; works like a while loop. It receives 3 arguments.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The first one is the condition function. It should return true if the loop should run.&lt;/li&gt;
  &lt;li&gt;The second argument is the body of the loop, and it can be asynchronous function.
    &lt;ul&gt;
      &lt;li&gt;It receives 2 arguments: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cont&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brk&lt;/code&gt;. Just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return cont();&lt;/code&gt; in place of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue;&lt;/code&gt; and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return brk();&lt;/code&gt; in place of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break;&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;So in asynchronous nature, this utility function doesn’t know when to continue, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return cont();&lt;/code&gt; must be explicitly called so that the loop can continue.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The third argument is the finishing function. It is called when the loop is over.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;asyncfor&quot;&gt;asyncFor&lt;/h2&gt;

&lt;p&gt;Another function, &lt;strong&gt;asyncFor&lt;/strong&gt;, well, works like the for loop. It just receives 2 more arguments. The initializer and the runner. Its implementation is rather simple, it just calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init()&lt;/code&gt; at the start and injects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next()&lt;/code&gt; into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; function passed to the body of the function.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So back to the sequential image loading problem, I can use these functions to do this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var i;
asyncFor(
	function() { i = 0; },
	function() { return i &amp;lt; images.length; },
	function() { i ++ },
	function(cont, brk) {
		console.log('loading image #' + i);
		var img = new Image();
		img.onload = function() {
			console.log('image #' + i + ' loaded');
			return cont();
		};
		img.src = images[i];
	},
	function() {
		console.log('all images loaded!');
	}
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;asyncseq&quot;&gt;asyncSeq&lt;/h2&gt;

&lt;p&gt;I also made this function, which makes it easy to run lots of asynchronous functions sequentially, without having to nest them:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var asyncSeq = function() {
	var i, args = arguments;
	asyncLoop(
		function() { i = 0; },
		function() { return i &amp;lt; args.length; },
		function() { i ++; },
		function(cont, brk) {
			args[i](cont, brk);
		}
	);
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The usage is like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asyncSeq(
	function(cont, brk) {
		console.log('function 1 called');
		return cont();
	},
	function(cont, brk) {
		console.log('function 2 called');
		setTimeout(function() { return cont(); }, 300);
	},
	function(cont, brk) {
		console.log('function 3 called');
		setTimeout(function() { return cont(); }, 1000);
	},
	function(cont, brk) {
		console.log('function 4 called');
		return cont();
	}
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;So I hope that these utility functions can be useful for you and feel free to use them in your code!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;And I made a simple game for you.&lt;/p&gt;

&lt;p&gt;Here I have ten buttons. Click from left to right and you win!&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;button class=&quot;bt&quot; id=&quot;b1&quot;&gt;1&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b2&quot;&gt;2&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b3&quot;&gt;3&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b4&quot;&gt;4&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b5&quot;&gt;5&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b6&quot;&gt;6&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b7&quot;&gt;7&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b8&quot;&gt;8&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b9&quot;&gt;9&lt;/button&gt;
&lt;button class=&quot;bt&quot; id=&quot;b10&quot;&gt;10&lt;/button&gt;&lt;/p&gt;

&lt;script&gt;
	var asyncWhile = function(cond, body, fin) {
		function cont() { if (cond()) body(cont, brk); else brk(); }
		function brk() { if (fin) fin(); }
		cont();
	};

	var asyncFor = function(init, cond, next, body, fin) {
		init();
		asyncWhile(cond, function(cont, brk) {
			body(function() { next(); cont(); }, brk);
		}, fin);
	};

(function() {
	function win() { for (var i = 0; i &lt; 10; i ++) alert('You win!!'); }
	var i;
	asyncFor(
		function() { i = 1; },
		function() { return i &lt;= 10; },
		function() { i ++; },
		function(cont, brk) {
			var b = document.getElementById('b' + i);
			b.className = 'bt bt-click';
			b.onclick = function() {
				b.className = 'bt';
				b.onclick = undefined;
				return cont();
			};
		},
		win
	);
})();

&lt;/script&gt;

&lt;p&gt;The relevant code looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asyncFor(
	function() { i = 1; },
	function() { return i &amp;lt;= 10; },
	function() { i ++; },
	function(cont, brk) {
		var b = document.getElementById('b' + i);
		b.className = 'bt bt-click';
		b.onclick = function() {
			b.className = 'bt';
			b.onclick = undefined;
			return cont();
		};
	},
	win
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So as you see. You need to be careful not to let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cont()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brk()&lt;/code&gt; be called more than one time, or you will encounter unexpected results.&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/AsynchronousLoops</link>
                <guid>http://me.dt.in.th/page/AsynchronousLoops</guid>
                <pubDate>2011-10-23T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How Facebook Ranks Your Friends</title>
                <description>&lt;p&gt;I’m a bit tired of all those applications that tries to determine your top friends based on some factor, knowing that Facebook &lt;strong&gt;knows&lt;/strong&gt; the ranking of your friend more than any other applications could know. So I created this little experiment.&lt;/p&gt;
&lt;hr /&gt;

&lt;p class=&quot;center&quot;&gt;Please use Firefox or Chrome for this experiment.&lt;/p&gt;

&lt;p&gt;The results from this application is considered private. No data will be sent to my server in this experiment.&lt;/p&gt;

&lt;h2 id=&quot;get-the-user-id&quot;&gt;Get the User ID&lt;/h2&gt;

&lt;div&gt;&lt;p&gt;&lt;a href=&quot;https://www.facebook.com/dialog/oauth?client_id=301081103251083&amp;amp;redirect_uri=http://me.dt.in.th/page/FacebookCallback&amp;amp;response_type=token&quot; onclick=&quot;window.open(this.href, '_blank', 'width=800,height=480'); return false;&quot;&gt;Click here to get the user ID&lt;/a&gt;

(or enter your ID manually:)

&lt;input id=&quot;paste-id&quot; /&gt;&lt;/p&gt;

&lt;p&gt;(if the text above says &quot;undefined&quot;, please click the above link again)&lt;/p&gt;

&lt;!--
Sign in to Facebook and go there: &lt;https://developers.facebook.com/tools/explorer/&gt;

This is the graph API explorer, which normally when you enter, will show info about you, including your ID.

Copy the ID and paste it in the box below.
--&gt;

&lt;/div&gt;

&lt;h2 id=&quot;get-the-raw-list&quot;&gt;Get the Raw List&lt;/h2&gt;

&lt;p&gt;Sign in to Facebook and go to the URL below.&lt;/p&gt;

&lt;p&gt;&lt;input id=&quot;copy-id&quot; readonly=&quot;readonly&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You should see a very long text. Copy all of them and paste it in the box below.&lt;/p&gt;

&lt;h2 id=&quot;paste-the-content&quot;&gt;Paste The Content&lt;/h2&gt;

&lt;div&gt;&lt;p&gt;&lt;textarea id=&quot;paste-data&quot;&gt;&lt;/textarea&gt;&lt;/p&gt;

&lt;/div&gt;

&lt;p&gt;Finally, click the button to see the ordered list of your friends, in some particular order that I don’t know, but this is the order that you’ll see when you tag your friends in posts/comments/photos.&lt;/p&gt;

&lt;p&gt;&lt;input type=&quot;button&quot; id=&quot;get-data&quot; value=&quot;Click here to see the list.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;output&quot;&gt;Output&lt;/h2&gt;

&lt;ol id=&quot;result&quot;&gt;&lt;li&gt;your results will display here&lt;/li&gt;&lt;/ol&gt;

&lt;script&gt;window.obtainID = function(id) {
    document.getElementById('paste-id').value = id;
    idChanged();
};
document.getElementById('paste-id').onchange = 
document.getElementById('paste-id').onkeyup =
document.getElementById('paste-id').onmouseup =
window.idChanged = function() {
    var v = document.getElementById('paste-id').value.match(/\d+/);
    if (v &amp;&amp; v[0] != '') {
        //v = 'https://www.facebook.com/ajax/typeahead/first_degree.php?__a=1&amp;filter[0]=user&amp;viewer=' + v[0];
        //v = 'https://www.facebook.com/ajax/typeahead/search/first_degree.php?__a=1&amp;filter[0]=user&amp;viewer=' + v[0] + '&amp;token=v7&amp;stale_ok=1&amp;__user=' + v[0] + '';
        v = 'https://www.facebook.com/ajax/typeahead/search/bootstrap.php?__a=1&amp;filter[0]=user&amp;viewer=' + v[0] + '&amp;token=v7&amp;lazy=1&amp;__user=' + v[0];
    } else v = '';
    document.getElementById('copy-id').value = v;
};

document.getElementById('get-data').onclick = function() {
    var json = document.getElementById('paste-data').value.replace(/^\s+/, '').substr(9);
    try {
        var data = JSON.parse(json);
        if (!data.payload) throw new Error('Payload not found!');
        if (!data.payload.entries) throw new Error('Entries not found!');
        var res = document.getElementById('result'), ent = data.payload.entries;
        while (res.firstChild) res.removeChild(res.firstChild);
        for (var i = 0; i &lt; ent.length; i ++) {
            var li = document.createElement('li'), a = document.createElement('a'),
                text = document.createTextNode(ent[i].text);
            a.href = 'https://www.facebook.com' + ent[i].path;
            li.appendChild(a); a.appendChild(text); li.appendChild(document.createTextNode(' (' + ent[i].index + ')')); res.appendChild(li);
        }
    } catch (e) {
        alert('JSON parsing error!: ' + e.toString());
    }
};

&lt;/script&gt;

</description>
                <link>http://me.dt.in.th/page/FacebookFirstDegree</link>
                <guid>http://me.dt.in.th/page/FacebookFirstDegree</guid>
                <pubDate>2011-10-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Hello, Rails!</title>
                <description>&lt;p&gt;Hello! I am new to Ruby on Rails!&lt;/p&gt;

&lt;p&gt;And I’m liking it! &amp;lt;3&lt;/p&gt;

</description>
                <link>http://me.dt.in.th/page/HelloRails</link>
                <guid>http://me.dt.in.th/page/HelloRails</guid>
                <pubDate>2011-10-12T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>#thaiWitter Scrolling Equation</title>
                <description>&lt;p&gt;Since the beginning, thaiWitter has a characteristic about the way it scrolls from one place to another place.
This article discusses, in mathematics style, about how it scrolls from one position to another.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;In acceleration phase, the acceleration is constant, so the animation is quadratic.&lt;/li&gt;
  &lt;li&gt;In deceleration phase, the acceleration is not constant. The velocity is proportional to the distance to the target, so the animation is exponential.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;new-algorithm&quot;&gt;New Algorithm&lt;/h2&gt;

&lt;p&gt;This algorithm is almost identical to the original algorithm, but the time is used in calculation, so the scrolling speed will be the same everywhere.&lt;/p&gt;

&lt;p&gt;In acceleration phase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The speed is $v_0 + kt_1$.
&lt;li&gt;So the displacement is $x_0 + v_0t_1 + {1 \over 2}kt_1^2$.
&amp;lt;/ul&amp;gt;


In deceleration phase:

&lt;ul&gt;
&lt;li&gt;The speed is $-\mu x$.&lt;/li&gt;
&lt;li&gt;Solve the differential equation, you get $c_0 e^{-\mu t_2}$.&lt;/li&gt;
&lt;li&gt;Substitute it in the speed (or differentiate it!) to get $-\mu c_0 e^{-\mu t_2}$.&lt;/li&gt;
&lt;/ul&gt;


Put the 2 phase one after another:

Let $x_0$ be initial distance to target (always positive).

Let $v_0$ be initial velocity (always negative).

Let $\mu$ be the friction coefficient (0.27 in #thaiWitter).

Let $k$ be the acceleration coefficient (5 in #thaiWitter).


Let $t$ be the number of frames in current animation.

Find the time $t_c$ which the animation changes from acceleration to deceleration:

$$ a = {1 \over 2} \mu k $$

$$ b = -\mu v_0 + k $$

$$ c = -\mu x\_0 - v\_0 $$

$$ t_c = { -b + \sqrt{ b^2 - 4ac } \over 2a } $$

Let $x$ be the distance to target after $t$ frames, $x$ is defined as:

&lt;p&gt;$$ x = \begin{cases}
  (x_0 + v_0 t_c - {1 \over 2} k {t_c}^2) e^{-\mu (t - t_c)} &amp;amp; t \ge t_c \\[1em]
  x_0 + v_0 t - {1 \over 2} k t^2 &amp;amp; t &amp;lt; t_c
\end{cases} $$&lt;/p&gt;

Let $v$ be the current scrolling speed after $t$ frames, $v$ is defined as:

&lt;p&gt;$$ v = \begin{cases}
  -\mu(x_0 + v_0 t_c - {1 \over 2} k {t_c}^2 ) e^{-\mu (t - t_c)} &amp;amp; t \ge t_c \\[1em]
  v_0 - k t &amp;amp; t &amp;lt; t_c
\end{cases} $$&lt;/p&gt;



Original Algorithm in JavaScript
----

This speed of the scrolling varies with the performance of the computer, because the next scrolling position is computed based on last frame without difference in time being used.

    var direction = this.scrollPos &amp;lt; this.curScrollPos ? -1 : 1;
    var distance  = Math.abs(this.scrollPos - this.curScrollPos);
    var speed     = Math.min(Math.max(1, Math.ceil(distance * 0.27)), this.lastAmount + 5);
    var amount    = direction * speed;
    this.lastAmount = speed;
    this.curScrollPos += amount;
    this.scrollTo (0, this.curScrollPos);

&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
</description>
                <link>http://me.dt.in.th/page/thaiWitterScrollingEquation</link>
                <guid>http://me.dt.in.th/page/thaiWitterScrollingEquation</guid>
                <pubDate>2011-08-28T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>A Simple GPS Tracker is Too Simple. My GPS Tracking Webapp.</title>
                <description>&lt;p&gt;I was looking for a free GPS tracker to record trips from my school to my university on my iPad.&lt;/p&gt;

&lt;p&gt;One that does the simplest things that a GPS tracker can do: record the coordinates and let me get these data out to do stuff with it.&lt;/p&gt;

&lt;h2&gt;I Haven't Found Any Which Works for Me&lt;/h2&gt;

&lt;p&gt;Many GPS trackers are not free (and has a lot of features I don't really want), or relies heavily on their own server.&lt;/p&gt;

&lt;p&gt;I prefer to have full control over my data. I would like to only send them when I want, and have full access to them.&lt;/p&gt;

&lt;h2&gt;My Simplest GPS Tracking Webapp&lt;/h2&gt;

&lt;p&gt;This is the simplest GPS tracking webapp that works for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt; It logs your location and time in localStorage and submits them to any URL when you click &quot;Submit&quot;. That's it.&lt;/p&gt;

&lt;p&gt;Without much talking, let's &lt;a href=&quot;https://github.com/dtinth/gps/blob/gh-pages/index.html&quot;&gt;see the code&lt;/a&gt; (or &lt;a href=&quot;http://dtinth.github.com/gps/&quot;&gt;the live version&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It has got no map display, speedometer, or whatever. It just logs your coordinates locally into the textarea and localStorage and submits to the URL specified at the top.&lt;/p&gt;

&lt;p&gt;This app won't communicate with the server (the URL specified at the top) unless you click the submit button.&lt;/p&gt;

&lt;h2&gt;Usage (for GPS-equipped iDevices)&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Turn off &quot;Auto-Lock&quot; in the Settings app (set it to Never). This app won't track your location when your device is off or locked.&lt;/li&gt;
&lt;li&gt;Open Safari and navigate to the web app's URL.&lt;/li&gt;
&lt;li&gt;Specify the server's URL.&lt;/li&gt;
&lt;li&gt;Tap the &quot;Start Tracking&quot; button.&lt;/li&gt;
&lt;li&gt;When tracking, no connection to the Internet is needed.&lt;/li&gt;
&lt;li&gt;Once finished, tap the &quot;Submit&quot; button to submit them to the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Receiving The Log&lt;/h2&gt;

&lt;p&gt;My GPS tracker sends the log (contents of the textarea) to the URL specified at the top by using the &lt;code&gt;coords&lt;/code&gt; POST variable.&lt;/p&gt;

&lt;p&gt;Your script should be able to handle it easily. Here is the script that runs on my server:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php file_put_contents('/path/to/gps.log', $_POST['coords']);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Parsing The Log Format&lt;/h2&gt;

&lt;p&gt;There are 4 kinds of line. A comment line, a start line, a coordinate line, or the failing line.&lt;/p&gt;

&lt;p&gt;A comment line starts with &lt;code&gt;--&lt;/code&gt;. Your log parser should ignore these lines. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-- this is a comment
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A start line indicates the time that the user pressed the &quot;Start Tracking&quot; button. The format is &lt;code&gt;[time] // start&lt;/code&gt;. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1302263615830 // start
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A coordinate line looks like &lt;code&gt;[time] // [lat] // [lng]&lt;/code&gt;. A example of this line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1302263698765 // 13.797455945576084 // 100.61361547747381
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, a failure line indicates that the tracker wasn't able to track the position at a specified time. For example,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1302263678901 // fail
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Have Fun With Your Data&lt;/h2&gt;

&lt;p&gt;Use it with Google Maps API or whatever. Have fun!&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2011/04/gps/</link>
                <guid>http://me.dt.in.th/2011/04/gps/</guid>
                <pubDate>2011-04-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>I Put Stuff On GitHub</title>
                <description>&lt;p&gt;I put some stuff on my GitHub profile, but did not mention it on this blog.&lt;/p&gt;

&lt;p&gt;You can take a look: &lt;a href=&quot;https://github.com/dtinth&quot;&gt;https://github.com/dtinth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also moved several old projects to GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dtinth/oauthdamnit&quot;&gt;oauthdamnit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dtinth/DtBMS&quot;&gt;DtBMS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This month, I'm staying at a computer camp, so I might not blog much.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2011/03/github-stuff/</link>
                <guid>http://me.dt.in.th/2011/03/github-stuff/</guid>
                <pubDate>2011-03-16T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Shell Script: Testing Gzip</title>
                <description>&lt;p&gt;I found this old shell script I have written long time ago. I called it &lt;code&gt;httpgztest&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/bash
NOGZ=`wget &quot;$1&quot; -q -O- | wc -c`
echo &quot;Without gzip:       $NOGZ&quot;
YESGZ=`wget --header=&quot;Accept-Encoding: gzip, deflate&quot; &quot;$1&quot; -q -O- | wc -c`
echo &quot;With gzip:          $YESGZ&quot;
RATIO=`echo &quot;scale=3;$YESGZ/$NOGZ&quot; | bc`
echo &quot;Compression ratio:  $RATIO&quot;
if [ $YESGZ -ge $NOGZ ]; then
    echo &quot;Gzip is not enabled for this URL. Go check.&quot;
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To use it, run it, passing URL as the argument&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;httpgztest http://dev.tw.dt.in.th/thaiWitter/js.js
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and it shows the compression ratio.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Without gzip:       79851
With gzip:          20839
Compression ratio:  .260
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And if the first and the second number are the same, i.e., the compression ratio is 1, then your gzip is not working.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Without gzip:       1820
With gzip:          1820
Compression ratio:  1.000
&lt;/code&gt;&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2011/02/httpgztest/</link>
                <guid>http://me.dt.in.th/2011/02/httpgztest/</guid>
                <pubDate>2011-02-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Serving Mercurial Over SSH, with Passwords</title>
                <description>&lt;p&gt;I'm doing a website project and I want to put them in a central repository on my server. I prefer to use password authentication on the server. The trick is to tell SSH to always execute hg instead of the shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; These command are to be executed as &lt;strong&gt;root&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Preparing for the environment&lt;/h2&gt;

&lt;p&gt;I created a &lt;code&gt;/hg&lt;/code&gt; directory to hold the repositories.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir /hg
cd /hg
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Setting up a skeleton&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;mkdir skel
mkdir skel/.ssh
mkdir skel/repo
echo &amp;gt; skel/.ssh/authorized_keys
chmod 600 skel/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates a skeleton directory.&lt;/p&gt;

&lt;h2&gt;Creating A New User&lt;/h2&gt;

&lt;p&gt;I do this by copying the skeleton, well, actually, I like doing this manually:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cp -Rp skel hg-rwb
chown -R hg-username:hg hg-username/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add the new user to &lt;code&gt;/etc/passwd&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;hg-username:x:3001:3000::/hg/hg-username:/bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Take note of the group ID &lt;code&gt;3000&lt;/code&gt;, we'll add it in &lt;code&gt;/etc/group&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;hg:x:3000:hg-username
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add the password:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;passwd hg-username
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Tell the SSH server to allow only Mercurial&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and add these lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Match Group hg
    ForceCommand hg -R ~/repo serve --stdio
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Initialize the repository&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;su hg-username
cd ~/repo
exec hg init
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Use it!&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;hg init
hg add
hg commit
echo '[paths]' &amp;gt;&amp;gt; .hg/hgrc
echo 'default-push=ssh://hg-username@my.secret.server/' &amp;gt;&amp;gt; .hg/hgrc
hg push
&lt;/code&gt;&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2011/02/serving-mercurial-over-ssh-with-passwords/</link>
                <guid>http://me.dt.in.th/2011/02/serving-mercurial-over-ssh-with-passwords/</guid>
                <pubDate>2011-02-25T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>jQuery: Checkboxes Toggling Plugin</title>
                <description>&lt;p&gt;In hurry, I made this simple plugin to jQuery:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $.fn.toggleCheckboxes = function() {
        var state = false;
        $('input:checkbox', this).each(function() {
            if (!this.checked) {
                state = true;
                return false;
            }
        }).each(function() {
            this.checked = state;
        })
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It toggles all the checkboxes &lt;strong&gt;inside&lt;/strong&gt; the matched elements all at once.&lt;/p&gt;

&lt;p&gt;This allows you to do something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$('.toggle').click(function() {
    $(this).closest('tr').toggleCheckboxes();
});
&lt;/code&gt;&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2011/02/jquery-togglecheckboxes/</link>
                <guid>http://me.dt.in.th/2011/02/jquery-togglecheckboxes/</guid>
                <pubDate>2011-02-21T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Converting StepMania Stepcharts to Tap Studio</title>
                <description>&lt;p&gt;&lt;a href=&quot;http://itunes.apple.com/us/app/tap-studio-3/id393451834?mt=8&quot;&gt;&lt;strong&gt;Tap Studio 3&lt;/strong&gt;&lt;/a&gt; is a nice game, but is full of off-synced tapcharts.&lt;/p&gt;

&lt;p&gt;This is mainly because of the way the tapcharts are made: It plays the song, the user records the tapchart as the song plays. When the song finishes, you get a tapchart ready to play. In Tap Studio 3, it has a basic UI for editing taps, but you can't be sure that it syncs well with the song, and it fells unresponsive too.&lt;/p&gt;

&lt;p&gt;Few days ago, I tried making my own taps, but each song took me a lot of time, because when I record, there will be an error in some point in the song (missing taps, extra taps, offbeat taps).&lt;/p&gt;

&lt;h2&gt;StepMania is Much Better At Making Notecharts!&lt;/h2&gt;

&lt;p&gt;Making stepcharts in StepMania is much more fun. You can record notes into your stepchart, or you can choose to add notes one by one. It has a lot of tools that you can use to fine-tune and sync your stepchart.&lt;/p&gt;

&lt;p&gt;Also, most of the already available simfiles on the Internet are pretty time-accurate.&lt;/p&gt;

&lt;p&gt;So I made a small Python script to convert my &lt;code&gt;.sm&lt;/code&gt; files to be playable on Tap Studio, so I can play them anywhere.&lt;/p&gt;

&lt;h2&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;To be able to convert &lt;code&gt;.sm&lt;/code&gt; files for playing in Tap Studio, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Mac.&lt;/li&gt;
&lt;li&gt;A jailbroken iDevice, with an SSH server installed.&lt;/li&gt;
&lt;li&gt;Tap Studio (either version 2 or version 3 will do).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dtinth/sm2tap&quot;&gt;sm2tap&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Converting Stepcharts&lt;/h2&gt;

&lt;h3&gt;Song Initialization&lt;/h3&gt;

&lt;p&gt;First, you need to have the song you want to convert in your device.&lt;/p&gt;

&lt;p&gt;Then, you need to initialize a song. Open Tap Studio, then go to your song library and pick a song you want. After that, press &lt;strong&gt;Record&lt;/strong&gt;. After the song starts, record &lt;strong&gt;only one note&lt;/strong&gt; and &lt;strong&gt;save it&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;Copying the Song to Your Mac&lt;/h3&gt;

&lt;p&gt;Then, SSH to your device, or run a terminal on your device &lt;strong&gt;as &lt;code&gt;mobile&lt;/code&gt; user&lt;/strong&gt;, and then issue this command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;find Applications -name '*.tapd'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should list all the tapfiles you have and the locations where they reside in. Copy the tap file you just created (the one with the song name) to your Mac.&lt;/p&gt;

&lt;h3&gt;Converting StepMania Notes to Tap Studio Notes&lt;/h3&gt;

&lt;p&gt;On your Mac, you need to convert the &lt;code&gt;.tapd&lt;/code&gt; file into an XML file.&lt;/p&gt;

&lt;p&gt;Open a Terminal, and then type in&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;plutil -convert xml1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then press space, then drag the &lt;code&gt;.tapd&lt;/code&gt; file into the terminal window, and then press Enter. You will see that the &lt;code&gt;.tapd&lt;/code&gt; file will be slightly bigger.&lt;/p&gt;

&lt;p&gt;After that, type in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;python
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Press space, and drag these files into the terminal window &lt;strong&gt;in order&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My &lt;code&gt;convert.py&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.sm&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.tapd&lt;/code&gt; file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then go back to terminal and press enter. You should see a list of available step types that can be converted. Type in the name of the step type and press enter. Your &lt;code&gt;.tapd&lt;/code&gt; file should be a lot bigger by now.&lt;/p&gt;

&lt;p&gt;Finally, to convert it back into binary format,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;plutil -convert binary1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then press space, then drag the &lt;code&gt;.tapd&lt;/code&gt; file into the terminal window, and then press Enter. The size of the &lt;code&gt;.tapd&lt;/code&gt; file will be reduced.&lt;/p&gt;

&lt;h3&gt;Copying the Modified Notes Back to Device&lt;/h3&gt;

&lt;p&gt;Copy this file back into your device. You can now play your simfile on your device!&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2011/02/sm2tap/</link>
                <guid>http://me.dt.in.th/2011/02/sm2tap/</guid>
                <pubDate>2011-02-04T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>CoffeeScripting @ Code Jom</title>
                <description>&lt;p&gt;Last year, &lt;a href=&quot;http://blog.dt.in.th/2010/02/javascripting-at-codejom/&quot;&gt;I used JavaScript at Code Jom competition&lt;/a&gt;. It was great, and I thought that I will use JavaScript in this year, but not using the old PHP+SpiderMonkey shell. I wanted to try something different, and I was really interested in &lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; and &lt;a href=&quot;http://narwhaljs.org/&quot;&gt;Narwhal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, I stumbled upon &lt;a href=&quot;http://stackoverflow.com/questions/4679782/can-i-use-coffeescript-instead-of-js-for-node-js&quot;&gt;a question on StackOverflow&lt;/a&gt; asking about &lt;strong&gt;CoffeeScript&lt;/strong&gt;, then I looked at &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;CoffeeScript's home page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I saw the example CoffeeScript in that page, compared to the compiled JavaScript, I had a feeling that I want to try to use it. The code indeed looked a lot less messy! And because CoffeeScript works with Node.js (it is available as a Node.js package), I went on with Node.js.&lt;/p&gt;

&lt;h2&gt;First Round&lt;/h2&gt;

&lt;p&gt;The first round started after I first knew CoffeeScript for less than 1 day. A day before that, I ported my old library for use in Code Jom written in JavaScript into CoffeeScript and used it.&lt;/p&gt;

&lt;p&gt;Surprisingly, I felt very comfortable. I felt like I still have all the power of JavaScript, but in a new, cleaner syntax. I finished the first round with a score of 9 (out of 14, ranked third).&lt;/p&gt;

&lt;h2&gt;Final Round&lt;/h2&gt;

&lt;p&gt;I prepared for the final round by familiarizing myself with CoffeeScript. I made a simple mashup webapp called &lt;a href=&quot;http://dtinth.github.com/crew-standings/&quot;&gt;Crew Standings&lt;/a&gt; in CoffeeScript and using jQuery and YQL.&lt;/p&gt;

&lt;p&gt;Because I planned it a bit wrong and went on working on the main scope, things got messed up when I create functions as sometimes it use the variables outside the function's scope (because I used a variable name outside that scope.&lt;/p&gt;

&lt;p&gt;But JavaScript (and CoffeeScript) is specialized in string handling, for example, when I need to get the first digit of a number, I can just convert the number to a string and use it. When I want to match a pattern from a string, I simply check the string if it matches a regular expression.&lt;/p&gt;

&lt;p&gt;I couldn't do some questions that is based on some algorithm, where some others would be able to do it easily. For example, I was a bit too excited to be able to do the knapsack question.&lt;/p&gt;

&lt;p&gt;Also, a lack of fixed multidimensional arrays in JavaScript made things a bit harder, my solution is to put it in an object:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;price[p + '-' + m] = ......
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But that looked ugly and less straightforward than built-in fixed multidimensional arrays like in C where you can &lt;code&gt;int price[1000][1000];&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, I did it. My team got the first place for the student level.&lt;/p&gt;

&lt;h2&gt;The Library&lt;/h2&gt;

&lt;p&gt;I ported the last year's library to CoffeeScript, so that I don't have to learn all the new set of functions.&lt;/p&gt;

&lt;p&gt;I used a simple hack for forcing functions into the global scope&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(-&amp;gt; # force global scope

    @print = (x...) -&amp;gt;
        sys.print y + '\n' for y in x

).call null
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Anything that got added to &lt;code&gt;this&lt;/code&gt; will be added to the global scope, thanks to CoffeeScript, &lt;code&gt;this.name&lt;/code&gt; can be called &lt;code&gt;@name&lt;/code&gt;, so the above code added &lt;code&gt;print&lt;/code&gt; function to the global scope.&lt;/p&gt;

&lt;p&gt;Here is the full library script:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/807654.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;And a small example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require './LIBRARY'

for testcase in [1..scanNumber()]
    n = scanNumber()
    print (n * (n + 1)) / 2
&lt;/code&gt;&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2011/02/coffeescripting-at-cofejom/</link>
                <guid>http://me.dt.in.th/2011/02/coffeescripting-at-cofejom/</guid>
                <pubDate>2011-02-02T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Serving Files in Current Directory, the Quickest Way</title>
                <description>&lt;p&gt;I need to test some HTML files in other web browsers on other computers, but I don't want to temporarily move/copy/symlink these files to Apache's directory. I found the solution:&lt;/p&gt;

&lt;p&gt;From the &lt;a href=&quot;http://docs.python.org/library/simplehttpserver.html&quot;&gt;docs&lt;/a&gt;,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;python -m SimpleHTTPServer 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Serves files in current directory to everyone connecting to port 8000! Change the port number as needed.&lt;/p&gt;

&lt;p&gt;So I added this to my &lt;code&gt;.bash_profile&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;alias serve=&quot;python -m SimpleHTTPServer&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note: If you don't specify a port number, this one defaults to port 8000. So you can just type &lt;code&gt;serve&lt;/code&gt;.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2011/01/serving-files-in-current-directory/</link>
                <guid>http://me.dt.in.th/2011/01/serving-files-in-current-directory/</guid>
                <pubDate>2011-01-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>My Facebook Friend List Manager</title>
                <description>&lt;p&gt;(Updated: I changed the link to point to a newer version on GitHub, which also supports groups and negation).&lt;/p&gt;

&lt;p&gt;On Facebook, I try to keep all my friends arranged inside at least one list.&lt;/p&gt;

&lt;p&gt;But when I add new friends, I usually forget to put them inside a list. I lost them, because I found no easy way to find all the friends that are not in any lists.&lt;/p&gt;

&lt;p&gt;That is why I made this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://dtinth.github.com/friendlist/&quot;&gt;http://dtinth.github.com/friendlist/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a JavaScript application with no server side stuff and this is my first time using Facebook's API.&lt;/p&gt;

&lt;p&gt;This tool helps you find them (friends not in any lists) and helps you put them in the right list. This tool can also suggest the list based on their mutual friends with you.&lt;/p&gt;

&lt;p&gt;This tool works best when you don't have too much friends, because this tool fetches all of your friends and friend lists at start time. If you have too much of them, not all of them will be fetched and there will be problems. It works fine for me, but I can't guarantee that it will work for everyone.&lt;/p&gt;

&lt;p&gt;Works best in Firefox. Untested in other browsers.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/12/fbfriends/</link>
                <guid>http://me.dt.in.th/2010/12/fbfriends/</guid>
                <pubDate>2010-12-28T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Fix Thai Language Floating Tone Marks Problem in mPDF</title>
                <description>&lt;p&gt;I am working for my school's exhibition web site, which allows students from other schools to register for various competitions and activities in the exhibition day.&lt;/p&gt;

&lt;p&gt;At first, there was only a registration website. Later, I am informed that it should be able to generate the report as PDF file, so it could be printed and handed to the academic administration department quickly.&lt;/p&gt;

&lt;p&gt;I searched for a PDF generation libraries and decided to use &lt;a href=&quot;http://mpdf.bpm1.com/&quot;&gt;mPDF&lt;/a&gt; because its partial support HTML and CSS is really nice and it has UTF-8 support (the database is utf8 encoded).&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;All is going well, except for some floating tone marks that looks too high.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-11/26-2157.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;I wrote a little function that fixes this, it now looks like this:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-11/26-2159.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;As you see, the tone marks do not look to high anymore. Here is the code:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/716814.js&quot;&gt;&lt;/script&gt;

&lt;p
class=&quot;center&quot; &gt;To use it, just before added some data to the PDF, wrap it in thai() function. For example,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$pdf-&amp;gt;WriteHTML ($table-&amp;gt;getHTML());
&lt;/code&gt;&lt;/pre&gt;

&lt;p
class=&quot;center&quot; &gt;...becomes...&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$pdf-&amp;gt;WriteHTML (thai($table-&amp;gt;getHTML()));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's it. I hope that this can be useful for some people generating PDFs with Thai language.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/11/mpdf-thai-tone-marks/</link>
                <guid>http://me.dt.in.th/2010/11/mpdf-thai-tone-marks/</guid>
                <pubDate>2010-11-26T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Test iPhone Web Apps in iPad</title>
                <description>&lt;p&gt;I wanted to test how websites will look on iPhone on iPad because I don't want to buy another device. After a bit of hacking, I found the solution, but you need a jailbroken iPad.&lt;/p&gt;

&lt;p&gt;Here's how (&lt;strong&gt;try it at your own risk!&lt;/strong&gt;):&lt;/p&gt;

&lt;p&gt;First, you need to ssh to your iPad, then&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd /Applications/
cp -R MobileSafari.app/ MobileSafari01.app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This duplicates MobileSafari app. (Thanks to &lt;a href=&quot;http://modmyi.com/forums/native-iphone-ipod-touch-app-discussion/530541-duplicate-any-application.html&quot;&gt;this guide on how to duplicate any application&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Then open your file transfer program (I use &lt;a href=&quot;http://cyberduck.ch/&quot;&gt;Cyberduck&lt;/a&gt;) and go to &lt;code&gt;/Applications/MobileSafari01.app/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Download &lt;code&gt;Info.plist&lt;/code&gt; to your computer, open it with Property List Editor.&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;CFBundleIdentifier&lt;/code&gt; (or &lt;code&gt;Bundle identifier&lt;/code&gt;) to &lt;code&gt;com.apple.mobilesafari01&lt;/code&gt;. This makes iOS know that it's a separate application.&lt;/p&gt;

&lt;p&gt;Go to &lt;code&gt;UIDeviceFamily&lt;/code&gt;, and then remove the item with the value &lt;code&gt;2&lt;/code&gt;. This makes iOS run the application in iPhone mode.&lt;/p&gt;

&lt;p&gt;Save the file, upload it back, and respring. You will have another Safari icon.&lt;/p&gt;

&lt;p&gt;One will run in normal mode and another one will run in iPhone mode.&lt;/p&gt;

&lt;p&gt;Now you can see how web apps will look like in an iPhone, in iPad. Also, in iPhone mode, Safari will identify itself as an iPhone, instead of iPad!&lt;/p&gt;

&lt;p&gt;As the article points out, it will save the settings separately, as far as I have tried, I couldn't see a way to configure the iPhone Safari. If anyone did it, please let me know.&lt;/p&gt;

&lt;p&gt;Also, don't run two versions simultaneously, or they may clash with eachother.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/11/test-iphone-web-apps-in-ipad/</link>
                <guid>http://me.dt.in.th/2010/11/test-iphone-web-apps-in-ipad/</guid>
                <pubDate>2010-11-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Audio Data API in Firefox 4: audio generation demo</title>
                <description>&lt;p&gt;(Update: I just came back home, so I will fill this post with some technical details)&lt;/p&gt;

&lt;p&gt;I just spoke at #barcampbkk4 about the Audio Data API that's coming in Firefox 4.&lt;/p&gt;

&lt;p&gt;The demo: &lt;a href=&quot;http://blog.dt.in.th/stuff/audiodata/&quot;&gt;http://blog.dt.in.th/stuff/audiodata/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click for a crash cymbal.&lt;/li&gt;
&lt;li&gt;Move the mouse: control the appregiator.&lt;/li&gt;
&lt;li&gt;Accelerometer: control pad's lowpass filter (a very simple lowpass)&lt;/li&gt;
&lt;li&gt;Sound only, no visualization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Technical info:&lt;/h2&gt;

&lt;p&gt;There are 5 samples used: kick, snare, closed hihat, open hihat and crash cymbal. These samples are converted to 32bit float raw file using Audacity (44100 hz, mono), and then are converted to array using &lt;a href=&quot;http://blog.dt.in.th/stuff/audiodata/convertpcm.phps&quot;&gt;a convertor written in PHP&lt;/a&gt;. All melodic sounds are generated using an oscillator.&lt;/p&gt;

&lt;p&gt;This demo does not use dsp.js because at that time I haven't figured out how to use it.&lt;/p&gt;

&lt;p&gt;Instead, it used a very simple approach by putting all tracks in a single array. Each track is an object (or you can say singleton class) which has the following methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;init&lt;/strong&gt; will be called at the very beginning, used to set up event handlers (if there are any).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trigger&lt;/strong&gt; will be called every 1 step. The track can use this moment to update its frequency, etc etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sample&lt;/strong&gt; will be called for each sample. This method needs to return the sample for this track.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the beginning, the script will call init() method for each object in the array. When the user clicks the start button, it will create 2 timers, one every 60000 / 130 / 4 msec (= 1/4 beat if BPM is 130), and one every sample.&lt;/p&gt;

&lt;p&gt;The first timer will call the trigger() method on each object in the array, and another one goes through the array, call the sample() method and sum it up, and commit the audio buffer to the audio tag.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/10/audiodata-barcampbkk4/</link>
                <guid>http://me.dt.in.th/2010/10/audiodata-barcampbkk4/</guid>
                <pubDate>2010-10-24T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>I Just Want to Call Twitter's API With My Own Account!</title>
                <description>&lt;p&gt;&lt;strong&gt;I'm not making a new Twitter client, or a Twitter service. I am not making an app for users to use. I just want to call the API with my account!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think OAuth is complicated in some situations, especially when you want to do something very simple, e.g. posting a status update from your own account. &lt;/p&gt;

&lt;p&gt;Before Twitter killed basic authentication, it was as simple as a single line curl command, but now, it's a lot more complicated.&lt;/p&gt;

&lt;h2&gt;Introducing OAuth Damnit&lt;/h2&gt;

&lt;p&gt;So let me introduce &lt;strong&gt;OAuth Damnit&lt;/strong&gt;, a super simple Twitter OAuth library for PHP. This library is for you if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You just want to make a simple PHP script that calls the Twitter API using your account.&lt;/li&gt;
&lt;li&gt;You are not planning to let other users to sign in with your application.&lt;/li&gt;
&lt;li&gt;You want to parse the response yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This library is a very simple implementation of OAuth. It's only job is -- given the consumer key, consumer secret, access token, access token secret, and a GET/POST request to an OAuth service -- to sign the request, send the request to the server, and then pass the response from the server back.&lt;/p&gt;

&lt;p&gt;I coded it based on &lt;a href=&quot;http://github.com/abraham/twitteroauth&quot;&gt;abraham's twitteroauth&lt;/a&gt; project. Did not really copy any code from there, I just look at it to figure out how the OAuth process works.&lt;/p&gt;

&lt;h2&gt;Get OAuth Damnit&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Get &lt;a href=&quot;https://github.com/dtinth/oauthdamnit&quot;&gt;&lt;code&gt;oauthdamnit.php&lt;/code&gt; here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Registering an Application for Your Account&lt;/h2&gt;

&lt;p&gt;To make OAuth calls as an authenticated user, you will need a consumer key + secret and an access token + secret. To get that you will need to register a Twitter application.&lt;/p&gt;

&lt;p&gt;First of all, you will want to create an application for yourself. Sign in with the Twitter account you want to use your application with, then go to &lt;a href=&quot;http://dev.twitter.com/apps/new&quot;&gt;http://dev.twitter.com/apps/new&lt;/a&gt; and register a new application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Application Name&lt;/strong&gt; is what people will see as the source of the tweet. On Twitter it will show as &quot;less than 20 seconds ago via &lt;em&gt;your application name&lt;/em&gt;&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application Website:&lt;/strong&gt; Put in your website address, so that when people click on your application's link, they will go to your website.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application Type:&lt;/strong&gt; Client.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access Type:&lt;/strong&gt; Read &amp;amp; Write.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Getting the Keys, Secrets and Tokens&lt;/h2&gt;

&lt;p&gt;After you register your application, you will be taken to your application's details page. Take note of your application's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer key&lt;/li&gt;
&lt;li&gt;Consumer secret&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now on the right side, click the navigation link that says &quot;My Access Token&quot;. Then take note of your:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access token&lt;/li&gt;
&lt;li&gt;Access token secret&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then make a new file to hold your key, token, and your secrets. Let's name it &lt;code&gt;config.php&lt;/code&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/615127.js?file=config.php&quot;&gt;&lt;/script&gt;

&lt;h2&gt;Using OAuth Damnit&lt;/h2&gt;

&lt;p&gt;How to use it? Simple!&lt;/p&gt;

&lt;p&gt;To create a new instance of the API object, you just:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$api = new OAuthDamnit(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To GET something from the Twitter API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$raw = $api-&amp;gt;get($url, $params);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To POST something to the Twitter API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$raw = $api-&amp;gt;post($url, $params);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where &lt;code&gt;$url&lt;/code&gt; is the &lt;strong&gt;absolute URL&lt;/strong&gt; to Twitter's API endpoint and &lt;code&gt;$params&lt;/code&gt; is an array of parameters to send to Twitter API.&lt;/p&gt;

&lt;p&gt;These 2 functions returns the &lt;strong&gt;raw response&lt;/strong&gt; from Twitter's API and has not been processed in anyway. It's now up to you to do whatever you need to do with it.&lt;/p&gt;

&lt;h2&gt;An Example&lt;/h2&gt;

&lt;p&gt;This example calls &lt;code&gt;verify_credentials&lt;/code&gt; method, parses it and displays the output.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/615127.js?file=test.php&quot;&gt;&lt;/script&gt;

&lt;p&gt;An example of a POST request:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$raw = $api-&amp;gt;post('http://api.twitter.com/1/statuses/update.json', array('status' =&amp;gt; 'Testin it again!'));
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-09/18-2030.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;h2&gt;That's It&lt;/h2&gt;

&lt;p&gt;Oh and if my library somehow doesn't work (it worked for me), please try to fix it and send me a correction. Thanks!&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/09/oauth-damnit/</link>
                <guid>http://me.dt.in.th/2010/09/oauth-damnit/</guid>
                <pubDate>2010-09-18T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Thor, Technical Pattern Wallpaper</title>
                <description>&lt;p
class=&quot;center&quot; &gt;This is a wallpaper of the DJMAX TECHNIKA note pattern of the song Thor.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;It looks very hard, so I made a wallpaper of it. 1280x800.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-09/13-2002.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt; </description>
                <link>http://me.dt.in.th/2010/09/tnk-thor-tp/</link>
                <guid>http://me.dt.in.th/2010/09/tnk-thor-tp/</guid>
                <pubDate>2010-09-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>You Can Distort Time. At Least in JavaScript.</title>
                <description>&lt;p&gt;Tested on Firefox. Untested on other browsers. :P&lt;/p&gt;

&lt;p&gt;Couple of hours ago something crazy came to my head. I want to control the flow of time by manipulating the Date() constructor and see what's gonna happen.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/570289.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;So I wrote this code. This JavaScript code makes the Date() constructor slow down 4 times.&lt;/p&gt;

&lt;p&gt;For example, if I inject the JavaScript at 12:00 PM, then wait 4 minutes, and check the current time, it will say 12:01 PM. You get the point.&lt;/p&gt;

&lt;p&gt;The setInterval and setTimeout function is also modified to be slower.&lt;/p&gt;

&lt;p&gt;As a live example, I have included the script on this page too. All animations on this page will be 4 times slower! Compare it with the home page!&lt;/p&gt;

&lt;div&gt;&lt;script type=&quot;text/javascript&quot;&gt;(function() {

    var factor = 0.25;

    var _Date = Date;
    var _setTimeout = setTimeout;
    var _setInterval = setInterval;
    var start = new _Date().getTime();
    Date = function(a,b,c,d,e,f,g) {
        if (arguments.length == 0) {
            return new _Date(start + (new _Date().getTime() - start) * factor);
        }
        return _Date(a,b,c,d,e,f,g);
    };
    setTimeout = function(x, y) {
        return _setTimeout.call(window, x, y / factor);
    };
    setInterval = function(x, y) {
        return _setInterval.call(window, x, y / factor);
    };

})();&lt;/script&gt;&lt;/div&gt;

&lt;p&gt;You can also have the &lt;a href=&quot;javascript:(function () {var factor = 0.25;var _Date = Date;var _setTimeout = setTimeout;var _setInterval = setInterval;var start = (new _Date).getTime();Date = function (a, b, c, d, e, f, g) {if (arguments.length == 0) {return new _Date(start + ((new _Date).getTime() - start) * factor);}return _Date(a, b, c, d, e, f, g);};setTimeout = function (x, y) {return _setTimeout.call(window, x, y / factor);};setInterval = function (x, y) {return _setInterval.call(window, x, y / factor);};})();&quot;&gt;slow down&lt;/a&gt; bookmarklet.&lt;/p&gt;

&lt;p&gt;Try it! Drag the bookmarklet to the bookmarks bar, and then go to some site with animation effects (for example, &lt;a href=&quot;http://jquery.com/&quot;&gt;http://jquery.com/&lt;/a&gt;) and activate it. You will see that all the animations in the page will be 4x slower.&lt;/p&gt;

&lt;p&gt;The bookmarklet will not work with some websites or JavaScript frameworks that keeps the original Date constructor and use it, but as far as I know, jQuery always use the Date constructor currently present in &lt;code&gt;window&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This bookmarklet will not work with CSS transitions.&lt;/p&gt;

&lt;p&gt;........................&lt;/p&gt;

&lt;p&gt;I'll see if I can do something fun with this.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/09/time-distortion/</link>
                <guid>http://me.dt.in.th/2010/09/time-distortion/</guid>
                <pubDate>2010-09-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Userscript: Drag and Drop Upload for upic.me, making of</title>
                <description>&lt;p&gt;I have just seen upic.me's new style. It looks really nice. At the same moment, I feel that it would be nice to be able to drag and drop pictures from my computer to upload that picture. I knew it was possible because &lt;a href=&quot;http://hacks.mozilla.org/2010/02/an-html5-offline-image-editor-and-uploader-application/&quot;&gt;I have seen this&lt;/a&gt;. So I started coding and here's the result:&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;&lt;a href=&quot;http://userscripts.org/scripts/show/83671&quot;&gt;&lt;strong&gt;upic.me Drag and Drop Upload&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After installing this userscript, try going to &lt;a href=&quot;http://upic.me/&quot;&gt;http://upic.me/&lt;/a&gt;. The box should say &quot;drop here to upload picture&quot; instead of &quot;click there to upload picture.&quot; Try draging some pictures from your computer and drop it on the website. The image you dragged should upload right away.&lt;/p&gt;

&lt;p&gt;This best thing about this is it handles file uploading by itself. It does not require Flash at all.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Update 2012-06-29:&lt;/strong&gt; Now we have the &lt;strong&gt;FormData API&lt;/strong&gt;, the following is not needed anymore!&lt;/p&gt;

&lt;p&gt;Also, the code here is extremely outdated and uses unsupported nonstandard deprecated APIs such as &lt;code&gt;file.getAsBinary&lt;/code&gt; and &lt;code&gt;xhr.sendAsBinary&lt;/code&gt; that no longer work in any browser anymore. &lt;em&gt;Just use the FormData API!&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;del&gt;If you want to implement this on your own userscript or your website, feel free to copy it from my code. You should also read this to learn how to setup drop boxes: &lt;a href=&quot;https://developer.mozilla.org/en/using_files_from_web_applications#Selecting_files_using_drag_and_drop&quot;&gt;Using files from web applications#Selecting files using drag and drop&lt;/a&gt;.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;The uploading part is the one of the hardest parts. That is because you need to create the POST request payload by yourself.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;To do this, first, you can just set up XMLHttpRequest normally.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    var xhr = new XMLHttpRequest();
    xhr.open ('POST', '/upload.php');
    xhr.onreadystatechange = function() {
        // ...
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then make a progress listener if you want to keep track of the progress.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    xhr.upload.addEventListener ('progress', function(e) {
        if (e.lengthComputable) {
            // e.loaded = amount of data sent
            // e.total = total amount of data
        }
    }, false);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to prepare the payload the boundaries.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    var payload = '';
    var boundary = '---------------------------53748593789457348248012312';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I made this 2 utility functions that will help you.&lt;/p&gt;

&lt;p&gt;The first function adds a normal field data to the payload. You will use this for normal form input fields, such as hidden or text input.&lt;/p&gt;

&lt;p&gt;The second function receives a &lt;a href=&quot;https://developer.mozilla.org/en/DOM/File&quot;&gt;HTML5 File&lt;/a&gt; object and adds it to the payload.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    function addFormField(name, value) {
        payload += '\r\nContent-Disposition: form-data; name=&quot;' + name + '&quot;\r\n\r\n' + value + '\r\n--' + boundary;
    }
    function addFile(name, fileName, file) {
        payload += '\r\nContent-Disposition: form-data; name=&quot;' + name + '&quot;; filename=&quot;' + fileName + '&quot;\r\nContent-Type: ' + file.type + '\r\n\r\n' + file.getAsBinary() + '\r\n--' + boundary;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So after you prepare the payload using these 2 functions, now we have a huge string of data waiting to be sent to the server, so now let's upload it!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;multipart/form-data, boundary=&quot;+boundary);
    xhr.setRequestHeader(&quot;Content-Length&quot;, payload.length);
    xhr.sendAsBinary (payload);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want, you can also &lt;a href=&quot;http://userscripts.org/scripts/review/83671&quot;&gt;see the source code of my userscript&lt;/a&gt;. That's it for today's blog post.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/08/upic-dragdrop-upload/</link>
                <guid>http://me.dt.in.th/2010/08/upic-dragdrop-upload/</guid>
                <pubDate>2010-08-15T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>TNK Grid</title>
                <description>&lt;p&gt;First of all,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Browser support:&lt;/strong&gt; Firefox&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operating system support:&lt;/strong&gt; Linux and Mac (I'm sorry Windows users)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a little bookmarklet for DJMAX TECHNIKA players (who uses Linux or Mac). It displays a grid line overlaying the web page. It can help you time the notes, so that when you play, you know exactly when to activate that note, because now you know where exactly the note is.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Suppose you are watching a video of DJMAX TECHNIKA on YouTube.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-08/13-1106.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;You just click on the bookmarklet, and you see a gridline in front of you. You drag the handles of the gridline to fit it on the YouTube video.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-08/13-1111.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;You can then see how the notes are timed.&lt;/p&gt;

&lt;p&gt;In the above picture, thick line represents a &quot;beat&quot; in the song, while thin line represents a &quot;step&quot; or &quot;1/4 beat&quot; in the song.&lt;/p&gt;

&lt;p&gt;Note that in DJMAX TECHNIKA, the curvy dragging notes seems to be shifted slightly toward. It's not really related to this, so see this &lt;a href=&quot;http://www.sicomonline.com/forum/index.php?topic=7556.0&quot;&gt;discussion on activation of different types of note in DJMAX Technika&lt;/a&gt; for more information on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get TNK Grid:&lt;/strong&gt; &lt;a href=&quot;http://blog.dt.in.th/stuff/tnkgrid.html&quot;&gt;Click here to install TNK grid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On that page, drag the blue link to your bookmarks toolbar. If you don't see a link labelled &quot;TNK Grid 2,&quot; then you need a better browser.&lt;/p&gt;

&lt;p&gt;To use, click on the &quot;TNK Grid 2&quot; item on your bookmarks toolbar, you will see a grid. Drag the handles (the borders) of it to size it according to the video.&lt;/p&gt;

&lt;p&gt;You can click on the gridlines to switch the direction of that grid. This makes it possible to see the timing of videos with &quot;left swipe&quot;, &quot;right swipe&quot; or &quot;reverse swipe&quot; effect added.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;By the way, it also works with TECHNIKA 2!&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-08/13-1123.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt; </description>
                <link>http://me.dt.in.th/2010/08/tnkgrid/</link>
                <guid>http://me.dt.in.th/2010/08/tnkgrid/</guid>
                <pubDate>2010-08-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>phpQuery makes scraping a hell lot easier.</title>
                <description>&lt;p&gt;phpQuery is a PHP port of jQuery, so if you know how to use jQuery and PHP, you can easily use phpQuery. It's really awesome.&lt;/p&gt;

&lt;p&gt;You just need to see it: &lt;strong&gt;&lt;a href=&quot;http://code.google.com/p/phpquery/&quot;&gt;http://code.google.com/p/phpquery/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am using phpQuery for my &lt;a href=&quot;http://tnk.dt.in.th/&quot;&gt;DJMAX TECHNIKA Score Tracker&lt;/a&gt;'s backend code which fetchs the score from Platinum Crew's website and puts it in MySQL table every 4 hours, which is then used by the frontend. It also uses the &lt;a href=&quot;http://www.sicomonline.com/forum/index.php?topic=6143.0&quot;&gt;DJMAX Technika API&lt;/a&gt; (Thailand only ;)) to fetch some data instead of scraping in order to save bandwidth.&lt;/p&gt;

&lt;p&gt;I made a simple utility function that makes scraping tabular data from web pages a lot easier.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/480475.js?file=parsedoc.php&quot;&gt;&lt;/script&gt;

&lt;p&gt;All you need to do is throw in a selector for each column on that page. Just make sure that the selector for each column yields the same number of matching element, and then the function uses a parser function, which you define, to take that element and turn it into value.&lt;/p&gt;

&lt;p&gt;You can find the selector for the column you want easily using &lt;a href=&quot;http://www.selectorgadget.com/&quot;&gt;SelectorGadget&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-07/18-2231.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;For example, the following code scans the &lt;a href=&quot;http://www.djmax.in.th/technika/rankDJTitle.asp&quot;&gt;DJ Title Rank&lt;/a&gt; page from Platinum Crew (Thailand)'s website for top 15 DJs.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/480475.js?file=test-phpquery.php&quot;&gt;&lt;/script&gt;

&lt;p&gt;Note that the callback function that I use is a class member of the PCParser class. That's why you see the callback function in arrays. Now here's the output.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/480475.js?file=output.txt&quot;&gt;&lt;/script&gt;

&lt;p&gt;It works like a charm. Whenever the website's design is updated or changed, I just update these selectors (using SelectorGadget gives me the selector in less than one minute) and everything works again.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/07/phpquery-scraping/</link>
                <guid>http://me.dt.in.th/2010/07/phpquery-scraping/</guid>
                <pubDate>2010-07-18T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>My Facebook Account Was Blocked</title>
                <description>&lt;p&gt;I am at school and I want to sign in to Facebook chat from my mobile phone. It is a Nokia 5630. I downloaded &lt;strong&gt;eBuddy Mobile&lt;/strong&gt; from the Ovi Store, but as soon as I sign in to Facebook, it says &quot;wrong username/password.&quot;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;So I opened up Opera Mobile to sign in to Facebook, but it says:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-1243.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;So maybe it's eBuddy's server accessing my Facebook account, so I just continue. The next step is pretty easy: confirm using my mobile phone.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-1246.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;I waited for more than 10 minutes, and no single SMS, so I left the fields blank and confirm the code. I tried this several times, but no SMS sent. I kept retrying.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-1248.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;...until Facebook sends me to this screen:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-1250.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;That looks very fun and exciting. I mean, it is just like a game. If I can remember people's face correctly then I can get my account back. So I pressed Start and then Facebook starts showing me pictures of my friends:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-1252.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Well, A Technika screen? I never have a friend as a Technika screen. I have seen many Technika screens before and they all look the same. I don't even know their name, so who could this be? I have no other choices. I need to skip this question to get my Facebook account back.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-2010.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Now a Facebook logo? Seriously what the fuck is this? I only have 2 skips, and again, I need to use it.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Then I see a photo where I can recognize the face, but...&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/18-2104.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;....but look at these names! How can I know which name to choose? I also run out of skips. So I failed the tests, however, it's good that I have unlimited retries. Just sign out and sign in again.&lt;/p&gt;

&lt;p&gt;I keep retrying until I can get pass through it. It appears that eBuddy's server accessed my account and Facebook never see me using eBuddy, so Facebook locked my account.&lt;/p&gt;

&lt;p&gt;Now that my account was unlocked, I tried again, and then access to my account is blocked again and I have to through all the steps again. I forgot that eBuddy have many servers around the world. When I sign in the second time, it is from another server. I will never try it again. I will just stick with Nimbuzz. :D&lt;/p&gt;

&lt;p&gt;Total time wasted: &lt;strong&gt;around 2 hours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From my experience with Facebook, combined with what happened to me today, &lt;strong&gt;I see these things very annoying on Facebook&lt;/strong&gt;:&lt;/p&gt;

&lt;h2&gt;Tagging People Who Has Nothing To Do With A Photo&lt;/h2&gt;

&lt;p&gt;I &lt;strong&gt;always&lt;/strong&gt; remove my tag from photos that I am not in. I recommend that you do it too.&lt;/p&gt;

&lt;p&gt;Usually when people want to share a photo with their friends, they tag their friends in this photo. To me it seems not right. I think that it's best to tag people in a photo if he/she is &lt;strong&gt;actually in the photo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So how to share your photo with your friends? I think that the best way to use the share feature in Facebook. To share it with all your friends, just click &quot;share&quot; on the sidebar and post it to profile.&lt;/p&gt;

&lt;p&gt;Want to share it with only a number of friends? Click &quot;share&quot; on the sidebar, and then click on &quot;send as a message instead.&quot; You can then choose who to send to.&lt;/p&gt;

&lt;h2&gt;Using An Alias For Their Name On Facebook&lt;/h2&gt;

&lt;p&gt;Most of the time I will &lt;strong&gt;never&lt;/strong&gt; accept friend requests from people who don't use a real name. This is just my personal opinion. I am just annoyed.&lt;/p&gt;

&lt;p&gt;On Windows Live Messenger, I can assign a personal alias to their contacts on their contact list, so I will know who is who. However on Facebook I can't.&lt;/p&gt;

&lt;p&gt;To me, Facebook is different from other social networks. Unlike Twitter or Windows Live Messenger, I think that Facebook is where I can get in touch with people I already know and I will only be friends with people I already know. For Twitter and Windows Live Messenger that I use to chat and meet random people.&lt;/p&gt;

&lt;p&gt;So... that's all for this blog post.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/06/facebook-account-blocked/</link>
                <guid>http://me.dt.in.th/2010/06/facebook-account-blocked/</guid>
                <pubDate>2010-06-18T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Poem Remembering WIN</title>
                <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Sometimes the most dangerous place is the safest place!&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-06/04-2102.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;caption&quot; &gt;บางที ที่ที่อันตรายที่สุดก็อาจจะเป็นที่ที่ปลอดภัยที่สุด...&lt;/p&gt;

&lt;p&gt;Explaination: The picture above is of Thai language class, where everyone needs to remember a 20-line poem, and say it aloud to the teacher without reading it (or let the teacher see that you are reading it).&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/06/poemwin/</link>
                <guid>http://me.dt.in.th/2010/06/poemwin/</guid>
                <pubDate>2010-06-04T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>You don't need to know the victim's IP address to crack their PC.</title>
                <description>&lt;p&gt;I have been chatting with a random guy, in Thai language. The following chat transcription is translated (and is slightly modified).&lt;/p&gt;

&lt;p&gt;First, it was a normal chat. And then he starts out: &lt;em&gt;I am a hacker, white hat hacker. I use my skill to fix others' computer problems without them knowing it.&lt;/em&gt; I think like... really? Let me check if you really are one.&lt;/p&gt;

&lt;p&gt;So first, let me ask you some basic question first.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; What Windows are you using?
&amp;lt; No, not Windows. It's a specialized system for hacking.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I guess he must be a Linux user. What else could it be? Mac? &lt;del&gt;Specialized for hacking? No way.&lt;/del&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; So do you know what version of Windows I'm using?
&amp;lt; Either Windows XP or Windows 7
  So do you use XP?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously, if one does not use Windows XP, they will probably use Windows 7. Vista sucks.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; No.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, it's 50% chance, and he has failed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt; So it must be Windows 7.
&amp;gt; Obviously, but why can't you get it right at the first place?
&amp;lt; It's really hard to see. I have to dig through millions of number.
  However, I can get the right answer if I want it.
  But hey, Windows 7 is a very good operating system—
  it offers good protection!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I already knew about the protection thing of Windows 7, but millions of number? Windows XP is 5.1, and Windows 7 is 6.1. Just look at this damn string, is it so hard to figure out?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; Do you know my IP?
&amp;lt; It will take a long time. There are billions of IP.....
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While I chat with that guy, I made a page that just redirects the viewer to a Wikipedia article about TCP/IP, and gave that link to him, shortened using bit.ly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; Well, I suggest that you read about this: http://bit.ly/.....
  You should learn about TCP/IP.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;He clicked on it. His IP address and user agent string is recorded on the server's log. It shows that he is using Windows XP, and not any kind of a specialized operating system.&lt;/p&gt;

&lt;p&gt;We continued chatting for a while, then I decided to surprise him a bit.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; I will tell you something. Your IP is 124.122.___.___.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But that guy keeps &lt;span style=&quot;cursor:help;border-bottom:1px dotted #aaa&quot; title=&quot;แถ&quot;&gt;&quot;tae&quot;&lt;/span&gt;ing.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt; Hahaha, that was my fake IP.
&amp;gt; Yeah, but I can tell your &quot;fake IP&quot; in seconds.
  So what's your real IP?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I think that the IP I found is already a real IP. If it's not then he must be using a proxy server.&lt;/p&gt;

&lt;p&gt;But the next thing shocked me.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt; I'm not gonna tell you my real IP. But here's a hint:
  My IP starts with 192.16
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What the fuck.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt; And that IP address was the IP address of my server. I put it at Korea.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That IP address comes from Thailand. Everyone knows it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; Let me tell you something. 124.122.___.___ is a Thailand IP address and not Korea. You're also using True Internet.
&amp;lt; But the server is really at Korea.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I then completely ignored this guy.&lt;/p&gt;

&lt;p&gt;That was just for fun. I hope that he didn't take it too seriously. Heheh.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Edit 2012-06-29:&lt;/strong&gt; made few changes to the text to make it more clear.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/06/hack-wtf/</link>
                <guid>http://me.dt.in.th/2010/06/hack-wtf/</guid>
                <pubDate>2010-06-03T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Shuffle for Booklet</title>
                <description>&lt;p&gt;I have a reading record homework, where I have to read 10 stories, write the details about them, give them point of views, and write down 10 new vocabularies for each story. It needs to be printed on an A5 booklet, that is, one A4 paper folded in half to form 4 A5 pages.&lt;/p&gt;

&lt;p&gt;First, I made the template in iWork, but then I realized that iWork can't make booklets. I think that I will use &lt;a href=&quot;http://www.fpdf.org/&quot;&gt;FPDF&lt;/a&gt; and &lt;a href=&quot;http://www.setasign.de/products/pdf-php-solutions/fpdi/&quot;&gt;FPDI&lt;/a&gt; to do this job.&lt;/p&gt;

&lt;p&gt;So here's the thing I am doing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input Data: A pdf file of A5 pages.&lt;/li&gt;
&lt;li&gt;Output Data: An A4 landscape PDF file with all the pages shuffled for printing booklets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I found out that I can only output from first page to the last page, so I need to know first how to print a booklet of N pages. This is the topic of the blog post, which shows you the most straightforward way of computing which input page goes to which side of the output pages. Here's how the algorithm work.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;First, calculate the number of papers needed for N page, which is ⌈N / 4⌉ For example, I want a booklet of 16 pages, I need 4 pieces of paper. That means 8 pages.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/28-1359.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Then, put these papers on top of each other, fold them in half. You get booklet like this.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/28-1400.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Starting from the front of your booklet, label that page 1, then turn your page, label it 2 and 3. Do this for all pages.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/28-1401.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Now you know what to print on each page.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/28-1402.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Transform the above instructions into code. I get this.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/416863.js?file=shuffler.php&quot;&gt;&lt;/script&gt;

&lt;p
class=&quot;center&quot; &gt;An example...&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/416863.js?file=shuffler.example.php&quot;&gt;&lt;/script&gt;

&lt;p&gt;P.S. I should have seen &lt;a href=&quot;http://www.capca.ucalgary.ca/~wdobler/utils/ps2book.xhtml&quot;&gt;ps2book&lt;/a&gt; before I start writing this.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/05/shuffle-for-booklet/</link>
                <guid>http://me.dt.in.th/2010/05/shuffle-for-booklet/</guid>
                <pubDate>2010-05-28T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>How I installed drivers on my dad's PC.</title>
                <description>&lt;p&gt;I just re-installed Windows for my dad's PC. It does not come with any drivers.&lt;/p&gt;

&lt;p&gt;I can't set the screen resolution, I can't play sounds, I can't go to the Internet to download drivers. The first thing that came to my mind is to use Ubuntu.&lt;/p&gt;

&lt;p&gt;I inserted the Ubuntu Live CD, and I found out that everything works! So I used it to find out the drivers I need, and I downloaded them and installed them.&lt;/p&gt;

&lt;p&gt;So, here's how to do it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Insert Ubuntu Live CD and boot.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;System&lt;/strong&gt;, then &lt;strong&gt;Administration&lt;/strong&gt;, then &lt;strong&gt;Software Sources&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enable the &lt;strong&gt;universe&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the mirror close to you.&lt;/li&gt;
&lt;li&gt;Close but do not update yet.&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;gnome-terminal&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo apt-get update&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo apt-get install hardinfo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardinfo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click on the generate report thing. Save your report file somewhere.&lt;/li&gt;
&lt;li&gt;Copy the report to your flashdrive, or scp it to other unix PC.&lt;/li&gt;
&lt;li&gt;Now, on another PC with internet access, open the report that you have just copied. Look for the PCI section, go and download the driver from manufacturer's website. Copy it, and install it. I recommend that you install the network / wifi drivers first, so you can continue on that computer.&lt;/li&gt;
&lt;/ol&gt;</description>
                <link>http://me.dt.in.th/2010/05/how-i-installed-drivers-on-my-dads-pc/</link>
                <guid>http://me.dt.in.th/2010/05/how-i-installed-drivers-on-my-dads-pc/</guid>
                <pubDate>2010-05-21T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Abscapture - Take Screenshot with Transparency (for Linux)</title>
                <description>&lt;p&gt;It has once been posted on my old blog, since my old blog is gone forever, I'm going to re-post this tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abscapture&lt;/strong&gt; is a tool written in Python that allows you to take screenshots with alpha transparency.&lt;/p&gt;

&lt;p&gt;This tools work by capturing 2 screenshots. The first screenshot is the object on black background. The second screenshot is the same object on white background. The application then merges these 2 images together using a simple algorithm, producing a alpha-blended version of it.&lt;/p&gt;

&lt;p&gt;Here is an overview of an algorithm.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Finding the alpha component&lt;/strong&gt;. Because in each pixel, the red, green and blue components shares the same opacity (which is the alpha component), here is a way to find the alpha channel.
&lt;ul&gt;&lt;li&gt;Let B is the average of red, green and blue components of each pixel on the black image.&lt;/li&gt;
&lt;li&gt;Let W is the average of red, green and blue components of the same pixel on the white image.&lt;/li&gt;
&lt;li&gt;The transparency of that pixel in the resulting image is simply &lt;strong&gt;W - B&lt;/strong&gt;. Imagine these examples.
&lt;ul&gt;&lt;li&gt;If the pixel is opaque, then B will be equal to W. The transparency is 0%.&lt;/li&gt;
&lt;li&gt;If the pixel is transparent, then B will be 0% and W will be 100%. The transparency is 100%.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The alpha/channel opacity is the  &lt;strong&gt;100% - transparency&lt;/strong&gt; or &lt;strong&gt;100% - W + B&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Finding the color component&lt;/strong&gt;.
&lt;ul&gt;&lt;li&gt;Let V&lt;sub&gt;b&lt;/sub&gt; be the value of a component (red, green, or blue) of a pixel on the black image.&lt;/li&gt;
&lt;li&gt;Let V&lt;sub&gt;w&lt;/sub&gt; be the value of that component of that pixel on the white image.&lt;/li&gt;
&lt;li&gt;Let V&lt;sub&gt;r&lt;/sub&gt; be the value of that component of that pixel on the resulting image.&lt;/li&gt;
&lt;li&gt;Let A be the opacity of that pixel (calculated using above formula).&lt;/li&gt;
&lt;li&gt;You can see that:
&lt;ul&gt;&lt;li&gt;V&lt;sub&gt;b&lt;/sub&gt; will go towards 0% when opacity decreases, while V&lt;sub&gt;w&lt;/sub&gt; will go towards 100% when opacity increases.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;We can find V&lt;sub&gt;r&lt;/sub&gt; by solving two simultaneous equation:
&lt;ul&gt;&lt;li&gt;V&lt;sub&gt;r&lt;/sub&gt; * A = V&lt;sub&gt;b&lt;/sub&gt;&lt;/li&gt;
&lt;li&gt;V&lt;sub&gt;r&lt;/sub&gt; * A = 100% - V&lt;sub&gt;w&lt;/sub&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;That means: V&lt;sub&gt;r&lt;/sub&gt; = V&lt;sub&gt;b&lt;/sub&gt; / A.&lt;/li&gt;
&lt;li&gt;There is a case where the pixel is transparent, A = 0. There is a need to check for it too or it's division by zero.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p
class=&quot;center&quot; &gt;Now, let's see how the resulting image looks like:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/17-2228.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;caption&quot; &gt;Try it! Load the above image in GIMP and see the transparency for yourself.&lt;/p&gt;

&lt;h2&gt;Download!&lt;/h2&gt;

&lt;p&gt;Download it! &lt;a href=&quot;http://tnk.dt.in.th/blog-data/2010-05/abscapture-2010-05-17.tar.gz&quot;&gt;abscapture-2010-05-17.tar.gz&lt;/a&gt;&lt;/p&gt;

&lt;h2 class=&quot;center&quot;&gt;How to use abscapture?&lt;/h2&gt;

&lt;p
class=&quot;center&quot; &gt;First, install &lt;a href=&quot;apt://scrot&quot;&gt;scrot&lt;/a&gt;.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;After you extract the files, double click on abscapture.py and click &quot;run.&quot;&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/17-2241.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;A dialog box will open, telling you to &lt;strong&gt;set up the scene&lt;/strong&gt;.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Minimize all windows that you don't want in your screenshot. Leaving only the desktop, the panel and the windows you want. When you're ready, press OK. You will have 5 seconds to open up menus, tooltips, or additional elements you want in your screenshot.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-05/17-2243.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;After 5 seconds, the desktop changes to white. About 3 seconds later, the desktop changes to back. 3 seconds and then the desktop returns to normal. A window with a progress bar will appear. Wait for it to finish. That window with progress bar closes automatically when finish. You will have the file &lt;strong&gt;result.png&lt;/strong&gt; which is your screenshot!&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;And again, I hope that someone will pick this up and improve this tool or incorporate the feature of this tool into other software.&lt;/p&gt;

&lt;p&gt;Please add a comment if you have done so, or if you just want to say thanks, that's OK too!&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/05/abscapture/</link>
                <guid>http://me.dt.in.th/2010/05/abscapture/</guid>
                <pubDate>2010-05-17T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Blurry Text using CSS 3</title>
                <description>&lt;p
class=&quot;center&quot; &gt;This is an effect I have been using in a hidden feature of #thaiWitter, where a text pops up, and then blurs and fades away.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;I will show you how it looks like:&lt;/p&gt;

&lt;p
style=&quot;color:#fff;color:rgba(255,255,255,0);text-shadow:0 0 10px #fff;text-align:center&quot; &gt;&lt;span style=&quot;font-size:4em;&quot;&gt;Hello, World!&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;This effect can be achieved using CSS3. By setting the text to transparent and give it a text shadow. However this won't work on WebKit, because on WebKit browsers, if a text is transparent, then its shadow is transparent too, so in the example above you see nothing. Don't know how it looks like on Opera because I don't care. Anyway here's the code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;color: rgba(255, 255, 255, 0);
text-shadow: 0 0 10px #fff;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh and for IE, just use &lt;code&gt;progid:DXImageTransform.Microsoft.Blur&lt;/code&gt; then. In fact it works for images too, not just text.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/05/blurry-text-css/</link>
                <guid>http://me.dt.in.th/2010/05/blurry-text-css/</guid>
                <pubDate>2010-05-14T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>I Bought an In-Ear Earphone From Japan.</title>
                <description>&lt;p
class=&quot;center&quot; &gt;I came back from Japan 3 days ago.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;While I was at the airport I decided to buy some good earphones. So here's my new earphone.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/29-0940.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;And when I open it...&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/29-0944.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Look closely....&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/29-0945.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Ah.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;But it sounds very nice anyway.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/04/in-ear/</link>
                <guid>http://me.dt.in.th/2010/04/in-ear/</guid>
                <pubDate>2010-04-29T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Grader in 35 lines.</title>
                <description>&lt;p&gt;So we're doing some programming tasks at the computer olympics camp. My friend has got the task descriptions and all the testcases for the last year's competitions.&lt;/p&gt;

&lt;p&gt;Now that everyone has finished their codes, we need to grade them and see if....&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The output is correct.&lt;/li&gt;
&lt;li&gt;The code runs in time.&lt;/li&gt;
&lt;li&gt;The code uses not much memory (but I don't know how to check it, so skip it :D)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I don't have a grader so I came up with this real quick.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/381747.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;So there you have it. Read the code to know how to use it.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/04/grader/</link>
                <guid>http://me.dt.in.th/2010/04/grader/</guid>
                <pubDate>2010-04-28T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>My Color Tester</title>
                <description>&lt;p&gt;I'm customizing my text editor's syntax highlighter.&lt;/p&gt;

&lt;p&gt;Usually I start by opening the text editor's option, pick a syntax item and then pick a random color. Apply and see if it looks nice. But then I realize that it doesn't work very well.&lt;/p&gt;

&lt;p&gt;Why? Because there are no plans for what part of a syntax (number, strings, statements) belongs to what color.&lt;/p&gt;

&lt;p&gt;So I need to plan all the color first before I can actually use it in a text editor. So I came up with this.&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;&lt;strong&gt;&lt;a href=&quot;http://blog.dt.in.th/stuff/colortester.html&quot;&gt;My Color Tester&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So to use it, type in some color codes. The first color will be displayed as a background, and the rest will be displayed as text. Still don't get it? Here's a sample. If I typed&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ffffff
#10a520
#aab512
#984151
&lt;/code&gt;&lt;/pre&gt;

&lt;p
class=&quot;center&quot; &gt;The result will look like this:&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/27-2226.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;You can also include some text too to describe the color. So here is my color scheme.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#232323
#dadada for normal text
#80ceff for preprocessors
#80ef50 for comments
#d0f979 for characters
#f9f979 for strings
#ecb760 for keywords
#f08686 for numbers
&lt;/code&gt;&lt;/pre&gt;

&lt;p
class=&quot;center&quot; &gt;And here's how it looks like.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/27-2233.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p
class=&quot;center&quot; &gt;Putting it in my favorite text editor, it now looks like this.&lt;/p&gt;

&lt;p class=&quot;oldblog-image&quot;&gt;&lt;img src=&quot;http://tnk.dt.in.th/blog-data/2010-04/27-2237.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Maybe I will use this scheme for all other codes that I may post on this blog too.&lt;/p&gt;

&lt;p&gt;And oh, I came up with this color scheme because I have bought a black (in fact, it's dark gray) notebook from Japan. All the pages are in dark gray and they need special pens to write on it. So I played with these colored pens and black papers and came up with this color scheme.&lt;/p&gt;

&lt;p&gt;With this color scheme, codes will have hot colors, so yellow for strings, red for numbers and orange for keywords. Comments and pre&amp;shy;processors have colder colors so they stand out.&lt;/p&gt;

&lt;p&gt;So that's it, hope you like it.&lt;/p&gt;

&lt;p&gt;By the way I'm going to a computer olympics camp tomorrow, so I may post some C stuff here lol.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/04/colortester/</link>
                <guid>http://me.dt.in.th/2010/04/colortester/</guid>
                <pubDate>2010-04-27T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Stopwatch</title>
                <description>&lt;p&gt;I was at a computer camp (today I came back to my home but I'll go back to the computer camp for three more days after posting this).&lt;/p&gt;

&lt;p&gt;I learned about sorting algorithms (and their efficiency) and we took the pre-test.&lt;/p&gt;

&lt;p&gt;I have to explain about sorting algorithms and do some data sorting on paper using various algorithms. I got 15 numbers and the test says that I have to sort these data using Insertion Sort, Selection Sort, Merge Sort and Quick Sort, and I have 45 minutes to do it. I didn't finish it in time, so I have to practicing about sorting on paper.&lt;/p&gt;

&lt;p&gt;So I wrote some numbers on the paper, and use my stopwatch to record the time I use to sort it.&lt;/p&gt;

&lt;p&gt;But I don't have a stopwatch... So I decided to open the Terminal and do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time cat
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The timer start, and when I want to stop, I press Ctrl+D, then it tells the time! :P&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/03/stopwatch/</link>
                <guid>http://me.dt.in.th/2010/03/stopwatch/</guid>
                <pubDate>2010-03-28T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>JavaScripting @ Code Jom</title>
                <description>&lt;p&gt;&lt;strong&gt;Update 2012-06-23&lt;/strong&gt;: Now that we have Node.js, this isn't needed anymore. Yay!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I've been to &lt;a href=&quot;http://codejom.thailandoi.org/&quot; target=&quot;_blank&quot;&gt;Thailand Code Jom&lt;/a&gt; today. It's a programming competition but it's focused on speed.&lt;/p&gt;

&lt;p&gt;Competitors can use any language they wish to use. It works by downloading a test case, run it through the program you wrote, and then upload the result. Pretty much like Google's Code Jam.&lt;/p&gt;

&lt;p&gt;My preferred language is JavaScript, and here's how I use JavaScript in this event:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I installed &lt;a href=&quot;http://en.wikipedia.org/wiki/SpiderMonkey_%28JavaScript_engine%29&quot; target=&quot;_blank&quot;&gt;SpiderMonkey JavaScript Engine&lt;/a&gt; and it's JavaScript shell, so it can be called from terminal and other shell scripts.&lt;/li&gt;
&lt;li&gt;I wrote and used &lt;a href=&quot;http://share11.appspot.com/40421&quot; target=&quot;_blank&quot;&gt;this PHP&lt;/a&gt; script that takes the code, the input file, run it and spit out the output (both to the Terminal and to a file)&lt;/li&gt;
&lt;li&gt;The script takes 2 arguments: the code file name and the input file name.&lt;/li&gt;
&lt;li&gt;The script generates a script that stores the input file content in the variable called &quot;input&quot;, includes the file &quot;lib.js&quot;, and then pass the code to the function &quot;runCode()&quot;&lt;/li&gt;
&lt;li&gt;Here's &lt;a href=&quot;http://share11.appspot.com/40422&quot; target=&quot;_blank&quot;&gt;the file lib.js&lt;/a&gt;. It contains the frequently used functions and utility functions.&lt;/li&gt;
&lt;li&gt;After that, then run the script like this: &lt;code&gt;./run code.js input.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Whatever the script prints out will be saved to a file CODEJOM_OUTPUT.txt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the functions in lib.js.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;var x = scanNumber()&lt;/strong&gt; scans a number from the input file and returns it, and remove it from the variable &lt;code&gt;input&lt;/code&gt;. Pretty much like &lt;code&gt;scanf(&quot;%d&quot;, &amp;amp;x);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;var x = scanWord()&lt;/strong&gt; scans a word (sequence of non-whitespace characters) and returns it, also remove it from the variable &lt;code&gt;input&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;var x = scanText()&lt;/strong&gt; scans a line of text (non-whitespace characters followed by any characters except newline) and return it. Removes that line from the variable &lt;code&gt;input&lt;/code&gt;. Like fgets'ing from stdin.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;var x = scanArray()&lt;/strong&gt; scans the entire input file into an array where each array element is one line.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;generatePrimeDB(upto)&lt;/strong&gt; generates all prime numbers upto a specific number. Returns a JavaScript object, which, if an element with that number as a key doesn't exist in the returned object, then it's a prime number. The object also contains a &quot;list&quot; property, which is an array of all prime numbers from 2 to the specified number.&lt;/li&gt;
&lt;li&gt;And the function &lt;strong&gt;runCode()&lt;/strong&gt; which is internal to the run script, so don't use it in your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how simple the code for the &lt;a href=&quot;http://codejom.thailandoi.org/samples/&quot; target=&quot;_blank&quot;&gt;second example in this page&lt;/a&gt; can be.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var n = scanNumber();
for (var i = 0; i &amp;lt; n; i ++) {
    var word = scanWord();
    var len = scanNumber();
    var o = [];
    for (var j = 0; j &amp;lt;= word.length - len; j++) {
        o.push (word.substr(j, len));
    }
    o.sort ();
    print (o[0]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By the way I forgot to include &lt;a href=&quot;http://phpjs.org/functions/_phpjs_shared_bc:868&quot; target=&quot;_blank&quot;&gt;JavaScript Port of BCMath library&lt;/a&gt; in the lib.js file. With it I could compute very large numbers easily.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/02/javascripting-at-codejom/</link>
                <guid>http://me.dt.in.th/2010/02/javascripting-at-codejom/</guid>
                <pubDate>2010-02-12T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Will be AFK for 3 days. </title>
                <description>&lt;p&gt;...because I'm going to Khao Chon Kai.&lt;/p&gt;

&lt;p&gt;By the way I published this post from mobile phone.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/02/will-be-afk-for-3-days/</link>
                <guid>http://me.dt.in.th/2010/02/will-be-afk-for-3-days/</guid>
                <pubDate>2010-02-06T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>A Quick Way of Getting Your Public IP Address</title>
                <description>&lt;p&gt;My ADSL USB MODEM that is connected directly to my server is broken. Now I need to use a router instead.&lt;/p&gt;

&lt;p&gt;However, I can't get noip2 to find my public IP Address, but there is noip2 -i (your ip address).&lt;/p&gt;

&lt;p&gt;So here is my solution:&lt;/p&gt;

&lt;p&gt;Whenever you want to use your public IP address, just type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;`curl http://ip.appspot.com/`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that's it, so my noip2 command would be like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo noip2 -i `curl http://ip.appspot.com/`
&lt;/code&gt;&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2010/01/public-ip-address/</link>
                <guid>http://me.dt.in.th/2010/01/public-ip-address/</guid>
                <pubDate>2010-01-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>HCF Function in PHP</title>
                <description>&lt;p&gt;I just learned more about recursive functions.&lt;/p&gt;

&lt;p&gt;So I made this little function in PHP.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function hcf($a, $b) {
    if ($b &amp;gt; $a) return hcf($b, $a);
    if ($b == 0) return $a;
    return hcf($b, $a % $b);
}

function hcf_array($array) {
    if (count($array) &amp;lt; 1) return false;
    if (count($array) == 1) return $array[0];
    array_unshift ($array, hcf(array_shift($array), array_shift($array)));
    return hcf_array($array);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Function hcf($a, $b) finds the HCF of $a and $b.&lt;/p&gt;

&lt;p&gt;Function hcf_array($a) finds the HCF of array $a.&lt;/p&gt;

&lt;p&gt;May be useful in the future.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/01/hcf-function-in-php/</link>
                <guid>http://me.dt.in.th/2010/01/hcf-function-in-php/</guid>
                <pubDate>2010-01-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>My sound slicer</title>
                <description>&lt;p&gt;(This article should be very confusing for you to read, sorry, but I can't explain this tool I made very well)&lt;/p&gt;

&lt;p&gt;When I was very new to BMS making I use Audacity to slice the sounds to make keysounds manually. It's very tiresome!&lt;/p&gt;

&lt;p&gt;So I made a tool to slice the wav files into parts. Written in PHP:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href=&quot;https://github.com/dtinth/sound-slicer&quot;&gt;https://github.com/dtinth/sound-slicer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, for example, I have a .wav file called &quot;x.wav&quot;, I need to make a text file called &quot;x.txt&quot; and type in some beats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;120bpm
16th
,..,..,. ,..,..,.
,...,... ,...,.,.
12th
,,,,,, ,,,,,,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are the explainations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;120bpm -&amp;gt; The BPM of the wav file is 120 (changes the tempo, affects the commands after it)&lt;/li&gt;
&lt;li&gt;16th -&amp;gt; 1 measure is divided into 16 steps (changes the step size, will affect the commands after it)&lt;/li&gt;
&lt;li&gt;, -&amp;gt; Starts a new wave file and put 1 step into that file.&lt;/li&gt;
&lt;li&gt;. -&amp;gt; Put 1 step into the last file.&lt;/li&gt;
&lt;li&gt;Other texts are treated as comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So from the above text file, the application would slice the wav file like this:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;0.000 sec&lt;/li&gt;
    &lt;li&gt;0.375 sec&lt;/li&gt;
    &lt;li&gt;0.750 sec&lt;/li&gt;
    &lt;li&gt;1.000 sec&lt;/li&gt;
    &lt;li&gt;1.375 sec&lt;/li&gt;
    &lt;li&gt;1.750 sec&lt;/li&gt;
    &lt;li&gt;2.000 sec&lt;/li&gt;
    &lt;li&gt;2.500 sec&lt;/li&gt;
    &lt;li&gt;3.000 sec&lt;/li&gt;
    &lt;li&gt;3.500 sec&lt;/li&gt;
    &lt;li&gt;3.750 sec&lt;/li&gt;
    &lt;li&gt;4.000 sec&lt;/li&gt;
    &lt;li&gt;4.167 sec&lt;/li&gt;
    &lt;li&gt;4.333 sec&lt;/li&gt;
    &lt;li&gt;4.500 sec&lt;/li&gt;
    &lt;li&gt;4.667 sec&lt;/li&gt;
    &lt;li&gt;4.833 sec&lt;/li&gt;
    &lt;li&gt;5.000 sec&lt;/li&gt;
    &lt;li&gt;5.167 sec&lt;/li&gt;
    &lt;li&gt;5.333 sec&lt;/li&gt;
    &lt;li&gt;5.500 sec&lt;/li&gt;
    &lt;li&gt;5.667 sec&lt;/li&gt;
    &lt;li&gt;5.833 sec (and lasts for 0.167 seconds)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated files will be saved in the folder called &quot;wav&quot;. You can them import and use in BMSE.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Update 2012-06-23&lt;/strong&gt;: Updated links to GitHub.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2010/01/my-sound-slicer/</link>
                <guid>http://me.dt.in.th/2010/01/my-sound-slicer/</guid>
                <pubDate>2010-01-08T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Typentilt: Type and Tilt!</title>
                <description>&lt;p&gt;I made something long time ago since I heard the news about accelerometer support in Firefox 3.6.&lt;/p&gt;

&lt;p&gt;I use a MacBook and MacBooks has accelerometer built in, so I made this. I call it Typentilt, which comes from from Type and Tilt!&lt;/p&gt;

&lt;p&gt;&lt;del&gt;To use it just open it in Firefox 3.6 beta 4 or later, type some text in and then rotate your MacBook vertically. The text you type appears, filling the browser. It's best to use this in Full Screen! (Cmd+Shift+F in Firefox 3.6)&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;&lt;strong&gt;Download&lt;/strong&gt;: typentilt.zip&lt;/del&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Update 2012-06-23&lt;/strong&gt;: The MozOrientation is now the standard called &quot;DeviceOrientation&quot; API. And while Firefox claims that it's working, as of writing it doesn't. You should try it on Google Chrome, instead.&lt;/p&gt;

&lt;p&gt;I also moved the files to GitHub: &lt;a href=&quot;http://dtinth.github.com/typentilt/&quot;&gt;http://dtinth.github.com/typentilt/&lt;/a&gt;&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2009/12/typentilt/</link>
                <guid>http://me.dt.in.th/2009/12/typentilt/</guid>
                <pubDate>2009-12-18T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>I Hate Writing Poems</title>
                <description>&lt;pre&gt;I hate writing poems
I hate writing rhymes
Wanna know what's the problem?
That's because I don't have time!&lt;/pre&gt;

&lt;pre&gt;I wasted all the minutes
On play cards
That's why I came up with this shit
Don't know where to start&lt;/pre&gt;

&lt;pre&gt;But now I can do it
I am very proud
I'm writing this in the last minute&lt;/pre&gt;

&lt;p&gt;I'm back from an English camp with AYC. In the English camp they told us to make a poem for the funny poem contest since the first day of camp (it's 3-day camp) but I didn't have time to think about it. Just practicing the talent show and play play play play.&lt;/p&gt;

&lt;p&gt;So in the last day I came up with this stupid poem. And because I wrote the last line in the last minutes, that's an abrupt end.&lt;/p&gt;

&lt;p&gt;Finally, the staff adds in the final line:&lt;/p&gt;

&lt;pre&gt;I'm singing but I've got no crowds.&lt;/pre&gt;</description>
                <link>http://me.dt.in.th/2009/12/i-hate-writing-poems/</link>
                <guid>http://me.dt.in.th/2009/12/i-hate-writing-poems/</guid>
                <pubDate>2009-12-13T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>End of the Moonlight, Technical Pattern Wallpaper</title>
                <description>&lt;p&gt;Well. Finally I can reach the last stage of the Challenger Set. The last song is &quot;End of the Moonlight&quot; (but if you play better you may get &quot;Fermion&quot;. I'm not yet that good). Still, I can't pass this song.&lt;/p&gt;

&lt;p&gt;So I made this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/old/eotm-2.png&quot; alt=&quot;End of the Moonlight, Technical Pattern&quot; class=&quot;post-image&quot;&gt;&lt;/p&gt;

&lt;p&gt;Made using JavaScript and Canvas.&lt;/p&gt;
</description>
                <link>http://me.dt.in.th/2009/12/tnk-moonlight-tp/</link>
                <guid>http://me.dt.in.th/2009/12/tnk-moonlight-tp/</guid>
                <pubDate>2009-12-09T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Monitoring Web Pages</title>
                <description>&lt;p&gt;My friends wanted my help. There is a locked forum topic that will open for reply in the next 20 minutes. He needs to reply on that topic as soon as it is available.&lt;/p&gt;

&lt;p&gt;I used this script.&lt;/p&gt;

&lt;pre&gt;#!/bin/bash
URL='&lt;strong&gt;the url you want to monitor&lt;/strong&gt;'
MATCH='&lt;strong&gt;the text that if match, means that the topic is still locked&lt;/strong&gt;'
while true; do
    if (curl &quot;$URL&quot; | grep &quot;$MATCH&quot;); then
        echo '!!!!!!!!!!!!!!!!~ Not Yet'
    else
        echo '!!%$$%!%$#@$%#$%@%$%$!#%$!%%^!%^@%^!%^@!! NOW!'
    fi
    sleep 60
done&lt;/pre&gt;

&lt;p&gt;So this bash script just periodically checks that page until the match is not found.&lt;/p&gt;

&lt;p&gt;The reason why I need to make a bash script is because I forgot to install the &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/115&quot; target=&quot;_blank&quot;&gt;ReloadEvery extension&lt;/a&gt; for Firefox.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2009/12/web-page-monitor/</link>
                <guid>http://me.dt.in.th/2009/12/web-page-monitor/</guid>
                <pubDate>2009-12-04T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>JScript Hypertext Preprocessor</title>
                <description>&lt;p&gt;I and my team are in a HTML website making competition. We can use only text editors and other tools unrelated to building websites. Here's what they have&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Windows XP&lt;/li&gt;
    &lt;li&gt;Adobe Photoshop&lt;/li&gt;
    &lt;li&gt;Macromedia Flash (Yes, Macromedia.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I asked the staff to let my team install some more applications:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Notepad2&lt;/li&gt;
    &lt;li&gt;GIMP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these 2 applications, I can write HTML codes more comfortable.&lt;/p&gt;

&lt;p&gt;But I still need a way to quickly generate templates (e.g. the header, menu, footer) so when I change something I don't have to edit all the files. Something like a templating system. It makes me think of Windows Scripting Host. What about making a .bat file that runs a JScript script that processes text file?&lt;/p&gt;

&lt;p&gt;So I wrote this something that I call it &quot;JScript Hypertext Preprocessor.&quot; I will start by creating a working directory for the web. In this post I will refer as &lt;strong&gt;&quot;C:\Web&quot;&lt;/strong&gt;. Create the directory structure as follows:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;C:\Web&lt;/strong&gt; - The working directory.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;C:\Web\Dev&lt;/strong&gt; - All the website files will stay in here.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;C:\Web\Dev\include&lt;/strong&gt; - The .jshp files that you don't want to make it publicly available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And these 2 little file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C:\Web\Build.bat&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;cd %0\..

cd Dev
for /r %%i in (*.jshp) do wscript ..\Eval.js %%i
cd ..

del /s /q Publish
xcopy /s /i Dev Publish
cd Publish
del /s *.jshp
rmdir /s /q include
cd ..&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;C:\Web\Eval.js&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;var _sh = WScript.createObject('WScript.Shell');
var _fs = WScript.createObject('Scripting.FileSystemObject');
var _sn = WScript.arguments(0);
var _ob = '';

function alert(x) {
    _sh.popup (x + '');
}

function include(x) {
    var file = _fs.openTextFile(x, 1);
    var content = file.readAll();
    file.close ();
    return content.replace(/[^&amp;lt;]+|\&amp;lt;\?jshp([\s\S]*?)\?\&amp;gt;\s*|\&amp;lt;\?=([\s\S]*?)\?\&amp;gt;\s*|[\s\S]/g, function(a, b, c) {
        if (b) {
            return b + '\n';
        }
        if (c) {
            return 'output(\'\' + eval(unescape(\'' + escape(c) + '\')));\n';
        }
        return 'output(unescape(\'' + escape(a) + '\'));\n';
    });
}

function output(x) {
    _ob += (x);
}

echo = output;
print = output;

function output_file() {
    if (_ob.match(/^\s*$/)) return;
    var file = _fs.createTextFile(_sn.substr(0, _sn.length - 4) + 'html', true);
    file.write (_ob);
    file.close ();
}

eval (include(_sn));
output_file ();&lt;/pre&gt;

&lt;p&gt;Very tiny, isn't it?&lt;/p&gt;

&lt;p&gt;Now, to use it, I will show you some bit of code.&lt;/p&gt;

&lt;p&gt;C:\Web\Dev\index.jshp&lt;/p&gt;

&lt;pre&gt;&amp;lt;?jshp eval(include('include/config.jshp')) ?&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;title&amp;gt;Homepage - &amp;lt;?= siteTitle; ?&amp;gt;&amp;lt;/title&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;PI = &amp;lt;?=Math.PI?&amp;gt;!!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;?jshp
     showGenerated ();
?&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;&lt;/pre&gt;

&lt;p&gt;C:\Web\Dev\include\config.jshp&lt;/p&gt;

&lt;pre&gt;&amp;lt;?jshp

var siteTitle = 'My Web Site Title';

function showGenerated() {
 print ('Generated: ' + new Date().toString());
}

?&amp;gt;&lt;/pre&gt;

&lt;p&gt;Then double click on &quot;Build.bat&quot;.&lt;/p&gt;

&lt;p&gt;If you go and look into the &quot;Dev&quot; directory, you will see that &quot;index.html&quot; file is generated. It is generated from .jshp file.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/images/old/pi.png&quot;&gt;&lt;img class=&quot;size-full wp-image-55 alignnone&quot; title=&quot;.html file is generated from .jshp file.&quot; src=&quot;/images/old/pi.png&quot; alt=&quot;.html file is generated from .jshp file.&quot; width=&quot;563&quot; height=&quot;312&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will note that there is also a directory called &quot;Publish.&quot;&lt;/p&gt;

&lt;p&gt;That directory is, in fact, a copy of the &quot;Dev&quot; directory, with .jshp files and the include directory removed.&lt;/p&gt;

&lt;p&gt;Here are the list of functions you can use:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Functions from JScript.&lt;/li&gt;
    &lt;li&gt;alert(text) - Displays an alert.&lt;/li&gt;
    &lt;li&gt;output(blah), print(blah), echo(blah) - Prints the text into the .html file.&lt;/li&gt;
    &lt;li&gt;eval(include('filename')) - Like include in PHP.&lt;/li&gt;
    &lt;li&gt;print(include('filename')) - Like readfile in PHP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The open and close tags are &amp;lt;?jshp and ?&amp;gt;. I use the PHP styles because text editors with syntax highlighting will treat it as PHP code.&lt;/p&gt;

&lt;p&gt;Oh and about the competition, here is the list of scoring points:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Use frames (10 points)&lt;/li&gt;
    &lt;li&gt;Beautifulness of design (10 points)&lt;/li&gt;
    &lt;li&gt;Use of animations (10 points)&lt;/li&gt;
    &lt;li&gt;Content layouts (10 points)&lt;/li&gt;
    &lt;li&gt;And something I didn't remember (10 points)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn't use frames because I can't remember how to write it. However I used an iframe on one page. I hope that it counts as frames!&lt;/p&gt;

&lt;p&gt;For animations, I just use a subtle animation in the header part so that it does not distract the whole page.&lt;/p&gt;

&lt;p&gt;When the result is out I will tell you.&lt;/p&gt;
</description>
                <link>http://me.dt.in.th/2009/12/jscript-hypertext-preprocessor/</link>
                <guid>http://me.dt.in.th/2009/12/jscript-hypertext-preprocessor/</guid>
                <pubDate>2009-12-01T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Linux: Fixing bad sectors the DtTvB's way!</title>
                <description>&lt;p&gt;&lt;strong&gt;VMware made a bad sector on my hard disk,&lt;/strong&gt; maybe because of the electricity that go down.&lt;/p&gt;

&lt;p&gt;Anyway, 2 days ago, I can't access the virtual machine because whenever I boot it up, the system locks up. When I switch to the console, I saw something like this: { DRDY ERR }, { UNC } and some random numbers!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ata4.01: status: { DRDY ERR }
ata4.01: error: { UNC }
ata4.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
ata4.01: BMDMA stat 0x44
ata4.01: cmd 25/00:08:1e:0a:ab/00:00:54:00:00/f0 tag 0 dma 4096 in ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I ran SMART check:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SMART overall-health self-assessment test result: PASSED
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I ran fsck and everything was clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, what could be the problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After 2 days of searching, I can identify the bad sector and move it out of my way.&lt;/p&gt;

&lt;p&gt;Based on &lt;a href=&quot;http://www.roeckx.be/journal/Finding_which_sector_belongs_to_which_file_on_a_RAID_device_.html&quot;&gt;Kurt Roeckx's article &quot;Finding which sector belongs to which file on a RAID device,&quot;&lt;/a&gt; from the line with random hex number above:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;00:08:&lt;strong&gt;1e:0a:ab&lt;/strong&gt;/00:00:&lt;strong&gt;54&lt;/strong&gt;:00:00&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I know that the random number at the top is not random anymore!&lt;/p&gt;

&lt;p&gt;Ok, so the bad sector must be at &lt;strong&gt;0x54ab0a1e&lt;/strong&gt;, which equals to &lt;strong&gt;1420495390&lt;/strong&gt;. So I tried copying that sector over to other file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo dd if=/dev/sdb of=/media/disk-3/test skip=1420495390 bs=512 count=1 iflag=direct
dd: reading `/dev/sdb': Input/output error
0+0 records in
0+0 records out
0 bytes (0 B) copied, 24.5439 s, 0.0 kB/s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See? It cannot copy. Let's change from 1420495390 to 1420495389 (minus one):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo dd if=/dev/sdb of=/media/disk-3/test skip=1420495389 bs=512 count=1 iflag=direct
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0218896 s, 23.4 kB/s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or plus one:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo dd if=/dev/sdb of=/media/disk-3/test skip=1420495391 bs=512 count=1 iflag=direct
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0255337 s, 20.1 kB/s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok, so the problem is sector number 1420495390. Now I have to identify what partition that causes the error.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo fdisk -lu
   Device Boot      Start         End      Blocks   Id  System
.........      ..........  ..........    ........   ..  ......
.........      ..........  ..........    ........   ..  ......
/dev/sdb4      1240571430  1426073984    92751277+  83  Linux
.........      ..........  ..........    ........   ..  ......
.........      ..........  ..........    ........   ..  ......
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I removed all other entries so that you can focus on only one entry. 1420495390 (the bad sector) is between 1240571430 and 1426073984, so it must be on this partition! Let's unmount it first.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo umount /dev/sdb4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Subtract the bad sector number from the start number:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1420495390 - 1240571430 = 179923960
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And convert it to blocks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(179923960 * 512) / 4096 = 22490495
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Change 4096 to the block size of your file system. Now I have the block number, I ran debugfs on my file system:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo debugfs /dev/sdb4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Find the inode:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;debugfs:  icheck 22490495
Block   Inode number
22490495    3956755
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And find the file name:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;debugfs:  ncheck 3956755
Inode   Pathname
3956755 /VM/WIN2/*************************************.vmem
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alright. So it's a .vmem file. Based on &lt;a href=&quot;http://www.petri.co.il/virtual_vmware_files_explained.htm&quot;&gt;this article&lt;/a&gt;, .vmem file is just a backup file when the virtual machine is not shut down cleanly, well, may be because of electricity. Let's reserve it as a bad sector my moving the file elsewhere (I am not brave enough to &lt;code&gt;dd&lt;/code&gt; directly on this to reallocate).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;debugfs:  q
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This returns you to the shell. Let's mount the file system. (Normally I mount it at /n)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:~$ sudo mount /n
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dttvb@dttvb:/n/VM/WIN2$ mv *************************************.vmem ../bad-sector.001
dttvb@dttvb:/n/VM/WIN2$ rm *************************************.vmem.WRITELOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok, now you have get rid, uh, I mean, move the problem out of your way.&lt;/p&gt;

&lt;p&gt;And now I can boot my virtual machine happily, and everything went back to normal. XD&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2009/04/badsector/</link>
                <guid>http://me.dt.in.th/2009/04/badsector/</guid>
                <pubDate>2009-04-20T00:00:00+00:00</pubDate>
        </item>

        
        <item>
                <title>Mac OS X's say command</title>
                <description>&lt;p&gt;This isn't new at all, but I like it a lot. The &lt;code&gt;say&lt;/code&gt; command is very handy when you want your Mac to say something.
You can use the say command from the terminal, via SSH, or on a web application that can execute the &lt;code&gt;say&lt;/code&gt; command on the Mac.&lt;/p&gt;

&lt;p&gt;Lately, I made a small web app running on the Mac, with an intention to access it from localhost only.
I made an app that basically searchs for tweets that matches a predefined query every once a while, show it on the screen with a very big font, and read it aloud. That way, if I am near my MacBook but I am working on my PC, I can just listen to the tweet. If I am far from the MacBook or can't hear it clearly, I can just look at the screen.&lt;/p&gt;

&lt;p&gt;The following code will only work when you host the script on your Mac. If you access the script on other PC, it will still read aloud on your Mac.&lt;/p&gt;

&lt;p&gt;Here is the PHP code I use in order for a Mac to say:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php exec ('say ' . escapeshellarg(stripslashes($_GET['q']))); ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the JavaScript code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function say(something, callback) {

     var x = new XMLHttpRequest();
     // all browsers on the mac already supports xmlhttprequest
     // except the ancient ones

     x.open ('get', 'say.php?q=' + encodeURIComponent(something), true);
     x.onreadystatechange = function() {
         if (x.readyState == 4) {
             if (callback) (callback) ();
         }
     };
     x.send ('');

}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you can go ahead and implement whatever the hell you want.&lt;/p&gt;</description>
                <link>http://me.dt.in.th/2009/03/macsay/</link>
                <guid>http://me.dt.in.th/2009/03/macsay/</guid>
                <pubDate>2009-03-01T00:00:00+00:00</pubDate>
        </item>


</channel>
</rss>
