<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Paul Legato</title>
	
	<link>http://www.paullegato.com</link>
	<description />
	<lastBuildDate>Fri, 30 Nov 2012 05:40:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PaulLegato" /><feedburner:info uri="paullegato" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>PaulLegato</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Uncaught Exceptions in Clojure</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/MABQBhSP-Kw/</link>
		<comments>http://www.paullegato.com/blog/uncaught-exceptions-in-clojure/#comments</comments>
		<pubDate>Fri, 30 Nov 2012 05:40:57 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=596</guid>
		<description><![CDATA[Uncaught exceptions in Clojure sometimes disappear into the void if they happen in a background thread. Fortunately, the JVM provides a hook for adding a default handler.]]></description>
				<content:encoded><![CDATA[<p>Uncaught exceptions in Clojure sometimes disappear into the void if they happen in a background thread. Fortunately, the JVM provides <a target="_blank" href="http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)" >a hook for adding a default handler</a>:</p>
<pre class="brush: clojure; title: ; notranslate">
  (Thread/setDefaultUncaughtExceptionHandler
   (reify Thread$UncaughtExceptionHandler
     (uncaughtException [this thread throwable]
       ;; do something with the exception here.. log it, for example.
       )))
</pre>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/MABQBhSP-Kw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/uncaught-exceptions-in-clojure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/uncaught-exceptions-in-clojure/</feedburner:origLink></item>
		<item>
		<title>The Clojure Library Ecosystem</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/tgvLyglStjE/</link>
		<comments>http://www.paullegato.com/blog/clojure-library-ecosystem/#comments</comments>
		<pubDate>Wed, 23 May 2012 00:46:50 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=590</guid>
		<description><![CDATA[Clojure's library ecosystem can be a source of confusion for new users. This quick overview will help to orient new Clojure programmers to the current state of the library system, with pointers to resources for further information.]]></description>
				<content:encoded><![CDATA[<p>Clojure&#8217;s library ecosystem can be a source of confusion for new users. This quick overview will help to orient new Clojure programmers to the current state of the library system, with pointers to resources for further information.<span id="more-590"></span></p>
<h2>Leiningen</h2>
<p>Most Clojure projects use <a target="_blank" href="https://github.com/technomancy/leiningen/" >Leiningen</a> as their build and dependency management system. Project dependencies and their required versions are placed in a file called <code>project.clj</code>, and Leiningen takes care of downloading them. Leiningen also creates JARs of the release versions of your project, and can bridge to Emacs&#8217; SLIME mode, run a REPL at the command line, and so on. Many plugins exist to extend Leiningen&#8217;s functionality for other things like testing and deployment.</p>
<p>Under the covers, Leiningen uses <a target="_blank" href="http://maven.apache.org/" >Maven</a> for dependency management. Maven is one of those ridiculously over-engineered Java projects that we all love to hate where you have to write 100 lines of XML boilerplate around 2 lines of actual project-specific configuration data. Fortunately, Leiningen insulates us from all of that.</p>
<p>Users should be aware that, as of this writing (May, 2012), Leiningen is about to release version 2.0, which uses a slightly different <code>project.clj</code> format. Some Leiningen plugins have not been updated for the new format. This is easy enough to work around if you know that there has been a specification change. In particular, many <code>:dev-dependencies</code> that affect Leiningen itself have to be moved to the new <code>:plugins</code> key.</p>
<h2>Clojars and GitHub</h2>
<p>Most Clojure libraries are provided in binary JAR format on <a target="_blank" href="http://clojars.org/" >Clojars</a>, and have their source code hosted on <a target="_blank" href="https://www.github.com/" >GitHub</a>.</p>
<p>Clojure developers frequently face the situation where some critical bugfix or new feature exists only on somebody&#8217;s GitHub fork, but not in the mainline repository. The best option in this case is to get the maintainer to push a new official release with the required changes, but this is not always possible. If the project has a slow release cycle, or if the original developer is not very into the project, it can be months between the creation of patches in a fork and their release from the mainline repository to a new version on Clojars. We have a few options in that case.</p>
<p>For development, it can be convenient to use the <a target="_blank" href="https://github.com/tobyhede/lein-git-deps" >lein-git-deps plugin</a>. This extends Leiningen to allow it to download dependencies from GitHub into a hidden directory in your project. This is something of a fragile hack, though. If the subproject has any dependencies, they will not be checked out by Leiningen &mdash; you have to manually install them in the parent project. Worse, the code on GitHub can change at any time (unless you specify a particular release). If you redeploy your code in the future, you might wind up with a broken project. If it&#8217;s impractical to get the maintainer of a library to produce a new official release, it&#8217;s best to fork the library and make your own stable release.</p>
<p>If you just want to use it locally, check out your fork to your local machine, bump the version number, and do <code>lein install</code>. Within your organization, you can easily host a private Maven repository. If you want to deploy publicly, you can push a forked release to Clojars with a different group-id. Detailled instructions on how to do these things can be found <a target="_blank" href="https://github.com/technomancy/leiningen/blob/stable/doc/DEPLOY.md" >in the Leiningen documentation</a>.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/tgvLyglStjE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/clojure-library-ecosystem/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/clojure-library-ecosystem/</feedburner:origLink></item>
		<item>
		<title>Reading BZip2 Files in Clojure</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/LoHmxjXccfM/</link>
		<comments>http://www.paullegato.com/blog/reading-bzip2-files-clojure/#comments</comments>
		<pubDate>Fri, 18 May 2012 22:56:37 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=576</guid>
		<description><![CDATA[BZip2 compressed files can easily be read in Clojure thanks to Apache Commons Compress. Sample code inside!]]></description>
				<content:encoded><![CDATA[<p>BZip2 compressed files can easily be read in Clojure thanks to <a target="_blank" href="http://commons.apache.org/compress/apidocs/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.html" >Apache Commons Compress</a>. Sample code inside!<span id="more-576"></span></p>
<p>Add an Apache Commons Compress dependency to your Leiningen <code>project.clj</code> file like so:</p>
<pre class="brush: clojure; title: ; notranslate">
(defproject bz2reader &quot;0.1.0-SNAPSHOT&quot;
  :dependencies [
                 [org.clojure/clojure &quot;1.3.0&quot;]
                 [org.apache.commons/commons-compress &quot;1.4&quot;] ;; Read/write compressed files (BZip2, etc.)
                 ])
</pre>
<p>Then, you can make a BZip2 capable reader-generating function as follows:</p>
<pre class="brush: clojure; title: ; notranslate">
(ns bz2reader.util
  (:require [ clojure.java.io :as io])
  (:import (org.apache.commons.compress.compressors.bzip2 BZip2CompressorInputStream)
   ))


(defn bz2-reader
  &quot;Returns a streaming Reader for the given compressed BZip2
  file. Use within (with-open).&quot;
  [filename]
  (-&gt; filename io/file io/input-stream BZip2CompressorInputStream. io/reader))
</pre>
<p>This is based on a line from the <a target="_blank" href="https://github.com/Raynes/fs/blob/master/src/fs/compression.clj#L51"  class="broken_link">fs utilites</a> project, which includes a function to uncompress the file on disk. Rather than send the output of our BZip2 stream to a copy function which writes it to disk, we just return the stream for the user to use in the program. You can use the BZip2-enabled stream with any of the normal Clojure I/O methods, just like any other stream.</p>
<p>Here&#8217;s an example of how you can print the contents of a BZip2-compressed file to stdout using the above function:</p>
<pre class="brush: clojure; title: ; notranslate">
(defn print-bz2-file [filename]
  (with-open [rdr (bz2-reader filename)]
    (doseq [line (line-seq rdr)]
      (println line))))
</pre>
<p>It&#8217;s easy to create similar readers for GZip files, zip files, and so on using the other <a target="_blank" href="http://commons.apache.org/compress/apidocs/index.html" >Apache Commons Compress</a> classes. You can also write BZip2 compressed files similarly, just by piping your regular OutputStream through the encoder.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/LoHmxjXccfM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/reading-bzip2-files-clojure/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/reading-bzip2-files-clojure/</feedburner:origLink></item>
		<item>
		<title>Logging in Clojure with clj-logging-config</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/ipyEXWEMcOA/</link>
		<comments>http://www.paullegato.com/blog/logging-clojure-clj-logging-config/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 03:48:05 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=569</guid>
		<description><![CDATA[So your Clojure app wants to write logfiles. It&#8217;s easier than it used to be, thanks to Malcom Sparks and his clj-logging-config project. All the messy and utterly static log4j.properties stuff has been wrapped up in a nice dynamic Lisp layer! Here&#8217;s how. First, set up your project.clj file to load the appropriate libraries: Then, [...]]]></description>
				<content:encoded><![CDATA[<p>So your Clojure app wants to write logfiles. It&#8217;s easier than it used to be, thanks to Malcom Sparks and his <a target="_blank" href="https://github.com/malcolmsparks/clj-logging-config" >clj-logging-config</a> project. All the messy and utterly static <code>log4j.properties</code> stuff has been wrapped up in a nice dynamic Lisp layer! Here&#8217;s how.</p>
<p><span id="more-569"></span></p>
<p>First, set up your <code>project.clj</code> file to load the appropriate libraries:</p>
<pre class="brush: clojure; title: ; notranslate">
(defproject my-project &quot;1.0.0-SNAPSHOT&quot;
  :description &quot;My Project&quot;
  :dependencies [
                 [org.clojure/clojure &quot;1.3.0&quot;]

                 [log4j/log4j &quot;1.2.16&quot; :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                 [org.slf4j/slf4j-log4j12 &quot;1.6.4&quot;]
                 [org.clojure/tools.logging &quot;0.2.3&quot;]                 
                 [ clj-logging-config &quot;1.9.7&quot;]
               
                 ])
</pre>
<p>Then, run <code>lein deps</code> to fetch these dependencies, and just add a line like the following to your code:</p>
<pre class="brush: clojure; title: ; notranslate">
(ns my.namespace
  &quot;Logging setup&quot;
  (require [ clj-logging-config.log4j :as log-config]
           [ clojure.tools.logging :as log]))


(log-config/set-logger! :level :debug
                        :out (org.apache.log4j.FileAppender.
                              (org.apache.log4j.EnhancedPatternLayout. org.apache.log4j.EnhancedPatternLayout/TTCC_CONVERSION_PATTERN)
                              &quot;logs/foo.log&quot;
                              true))

(log/info &quot;This is a test log message.&quot;)

</pre>
<p>This will get you started with some basic logging to <code>logs/foo.log</code></p>
<p>If you want log rotation, use the <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/DailyRollingFileAppender.html" ><code>DailyRollingFileAppender</code></a> class instead of <code>FileAppender</code>. Many other setups are possible, too, such as logging to Syslog or logging to a socket. Take a look at the subclasses of <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/AppenderSkeleton.html" ><code>AppenderSkeleton</code></a> to get an idea of what&#8217;s there.</p>
<p>If you use the <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/TTCCLayout.html" ><code>TTCC_CONVERSION_PATTERN</code></a> as above, each line will automatically be prepended with the elapsed time since program start, thread name, severity, category, and &#8220;nested diagnostic context.&#8221; It&#8217;s easy to make your own prefix format; take a look at <a target="_blank" href="http://logging.apache.org/log4j/companions/extras/apidocs/org/apache/log4j/EnhancedPatternLayout.html" ><code>EnhancedPatternLayout</code></a> for the options.</p>
<p>Check the <a target="_blank" href="https://github.com/malcolmsparks/clj-logging-config" >clj-logging-config docs</a> and its examples for more ideas. You may also need to delve into <a target="_blank" href="http://logging.apache.org/log4j/1.2/apidocs/index.html" >the Log4J JavaDocs</a>.</p>
<p>Coming soon: how to colorize your logs.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/ipyEXWEMcOA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/logging-clojure-clj-logging-config/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/logging-clojure-clj-logging-config/</feedburner:origLink></item>
		<item>
		<title>The Democratic Party and Postmodernism</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/B2mXMB3QIB0/</link>
		<comments>http://www.paullegato.com/blog/democratic-party-postmodernism/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 00:52:36 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Economics]]></category>
		<category><![CDATA[Politics and International Relations]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=547</guid>
		<description><![CDATA[How creeping far-left postmodernist ideas are infecting the mainstream of thought in California, a symptom of the larger rot that is slowly destroying the Democratic Party nationally.]]></description>
				<content:encoded><![CDATA[<p>I give you another exhibit of <a target="_blank" href="http://www.sfgate.com/cgi-bin/article.cgi?f=%2Fc%2Fa%2F2011%2F12%2F03%2FMNPB1M7IB9.DTL" >how creeping far-left postmodernist ideas are infecting the mainstream of thought in California</a>, a symptom of the larger rot that is slowly destroying the Democratic Party nationally.<span id="more-547"></span></p>
<p>Paragraph after paragraph of heart-rending, maudlin emotional manipulation over the tragic fate of the cherubic little scholar whose only wish is to learn math, but whose test scores will inevitably fall below those of his classmates due to his Dickensian plight; hungry, cold, and homeless, yet cruelly expected to learn as well as his advantaged peers, though his frozen little fingers are too numb to grip a pencil and his stomach rumbles even after the meagre gruel the school provides him for breakfast&#8230;</p>
<p>Then, an entire section is devoted to exploring the city&#8217;s budget for accommodating homeless people at public expense, the message being that the government is failing in its responsibility to this kid by not providing free housing for him and his family.</p>
<p>Not a word is mentioned about any parental responsibility for getting their kid into this situation, nor for their responsibility to get the kid out of it. In fact, his parents are barely mentioned at all, other than to say that they sold all their possessions and moved to SF in September because his dad thought he had a job lined up which didn&#8217;t work out.</p>
<p>What compelled them to pack up and move without any savings? Was it bad luck, desperation, stupidity, some combination of the above? Are they looking for work? Do they have friends or relatives in other cities? Did their savings run out? Were there unexpected medical expenses or something like that? They&#8217;ve only been there for a few months, if the job didn&#8217;t work out, why don&#8217;t they move somewhere less expensive to live than the second-most-expensive city in the US, and to somewhere with better employment prospects for non-professionals? Why are they staying in San Francisco rather than moving somewhere cheaper? Who knows? The reporter didn&#8217;t even ask any of these questions.</p>
<p>To be absolutely clear, I am not against emergency public assistance to help those genuinely in need get back on their feet and begin to help themselves. Perhaps the family genuinely does need and deserve help. I don&#8217;t know; the reporter didn&#8217;t bother to tell us.</p>
<p>What I am against is the notion that the government (that is, the taxpayer) ought to function as a free-flowing money spigot without limits for anyone, forever. This is the mindset that informs both this article and the left wing of the Democratic Party generally. The only question asked is, &#8220;why is the government not doing more to help these people?&#8221; This could be a great question to ask in certain contexts. It should not stand alone as the <em>only</em> question to ask. The government should help, yes; but it should not be the primary responsible party. The key element of personal and parental responsibility is entirely absent from this discussion.</p>
<p>It didn&#8217;t even occur to the reporter to ask such very basic questions about their situation because these more extreme versions of the postmodernist-liberal worldview include a complete abdication of all personal responsibility for one&#8217;s situation in life. The individual is considered a mere kite in the social wind whose thin tether has broken loose, buffeted about by forces entirely beyond his control and with which only a massive and benevolent government bureaucracy can possibly contend. It&#8217;s all up to the government to save this family from the consequences of their bad luck and poor planning, to the extent that questions revolving around the details of the situation are not considered worth mentioning at all, in favor of a discussion of how woefully little money the government is spending on fixing the situation.</p>
<p>Indeed, the notion that government spending programs are the sole answer to this situation is taken entirely for granted in that article and not even an issue; the only point of contention is exactly how much more than present levels the government ought to be spending to fix things. Even then, &#8220;the government finding the parents jobs&#8221; is not floated as a solution; the government ought to just give them a free apartment for as long as they like, apparently.</p>
<p>Anyone who dares suggest that parents have any sort of primary responsibility to provide for their kid rather than the city government and the taxpayer is dismissed out of hand by the far-left as a cruel and unfeeling monster, etc.</p>
<p>Well, awareness of the deeper dynamics is the first step towards halting this trend. There you go.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/B2mXMB3QIB0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/democratic-party-postmodernism/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/democratic-party-postmodernism/</feedburner:origLink></item>
		<item>
		<title>Why is NATO in Libya? Data-based analysis of whether it’s just an oil grab.</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/2wEYKMQPHwE/</link>
		<comments>http://www.paullegato.com/blog/libya-nato-intervention-analysis/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 00:24:41 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Politics and International Relations]]></category>
		<category><![CDATA[libya]]></category>
		<category><![CDATA[nato]]></category>
		<category><![CDATA[oil]]></category>
		<category><![CDATA[politics]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=534</guid>
		<description><![CDATA[Why is the US involved in Libya today? Why is NATO there? Why aren't they doing more or less (depending on your politics) than they are? Is the whole thing yet another evil imperialist plot to make the white man rich by seizing the Other's oil? Let's look at some hard data and see what we can figure out.]]></description>
				<content:encoded><![CDATA[<p>Why is the US involved in Libya today? Why is NATO there? Why aren&#8217;t they doing more or less (depending on your politics) than they are? Is the whole thing yet another evil colonial imperialist plot to make the white man rich by seizing the Other&#8217;s oil? Let&#8217;s look at some hard data and see what we can figure out.<span id="more-534"></span></p>
<h1>Libyan Oil Production</h1>
<ul>
<li><a href="http://www.eia.gov/countries/cab.cfm?fips=LY"  target="_blank">Prewar Libyan oil production capacity ≈ 1.8 million bbl/day in 2010.</a></li>
<li>Prewar Libyan oil actual production in 2010 ≈ 1.65 million bbl/day. (ibid.)</li>
<li>Libyan Proven reserves ≈ 46.4 billion barrels. (ibid.)</li>
<li>Libyan reserves tend to be high quality light (high API gravity), sweet (low-sulfur) oil. (ibid.)</li>
<li>&#8220;the vast majority&#8221; of Libyan oil is exported to Europe (85%); 5% is exported to the US. (ibid.)</li>
<li><a href="http://www.eia.gov/dnav/pet/pet_pri_wco_k_w.htm"  target="_blank">Libyan oil sells for an average price of $117.13 per bbl</a>, as opposed to the world average of $113.87. For reference, Saudi light (high-quality) goes for $114.87; Saudi heavy (low-quality) oil goes for $110.43/bbl; and Mexican Maya heavy goes for $103.29 / bbl.</li>
<li>For comparison:</li>
<ul>
<li><a href="http://www.eia.gov/dnav/pet/pet_crd_pres_dcu_NUS_a.htm"  target="_blank">US domestic proven reserves ≈ 20 billion barrels.</a></li>
<li><a href="http://www.eia.gov/totalenergy/data/monthly/pdf/sec3_3.pdf"  target="_blank">US domestic daily production ≈ 7.48 million bbl /day.</a></li>
<li><a href="http://www.eia.gov/countries/country-data.cfm?fips=SA"  target="_blank">Saudi production ≈ 9.78 million bbl/day.</a></li>
<li>Saudi proven reserves ≈ 266.7 billion bbl. (ibid.)</li>
<li><a href="http://www.eia.gov/cfapps/ipdbproject/IEDIndex3.cfm?tid=5&amp;pid=53&amp;aid=1"  target="_blank">World oil production ≈ 86.8 million bbl/day.</a></li>
<li><a href="http://www.eia.gov/cfapps/ipdbproject/IEDIndex3.cfm?tid=5&amp;pid=57&amp;aid=6"  target="_blank">World proven reserves (2009) ≈ 1,341 billion bbl.</a></li>
</ul>
<li>The US government estimates that <a href="http://www.eia.gov/security/esar/latwom.html"  target="_blank">OPEC immediately available surplus production capacity is 1.5 to 2 million bbl/day</a>, excluding Iraq and Venezuela; over half of this capacity is in Saudi Arabia.</li>
<li><a href="http://articles.cnn.com/2011-02-23/world/libya.saudi.arabia.oil_1_swing-producer-surplus-oil-peter-beutel"  target="_blank">The Saudis claim to have surplus capacity of 4 million bbl/day.</a></li>
<li><a href="http://www.eia.gov/countries/cab.cfm?fips=LY"  target="_blank"><strong>Western oil companies are well represented in Libya</strong></a> (&#8220;Eni, Total, Repsol YPF, StatoilHydro, Occidental, OMV, ConocoPhillips, Hess, Marathon, Shell, BP, ExxonMobil and others.&#8221;)</li>
</ul>
<h1>Cost of NATO intervention in Libya</h1>
<ul>
<li><a href="http://af.reuters.com/article/libyaNews/idAFL6E7HN29420110623"  target="_blank">£260 million to the end of June to Britain</a></li>
<li><a href="http://blogs.abcnews.com/politicalpunch/2011/06/obama-administration-libya-operation-has-cost-more-than-716-million-does-not-require-congressional-a.html"  target="_blank">$716 million through June 3rd to the US alone.</a></li>
<li><a href="http://af.reuters.com/article/topNews/idAFJOE76902T20110710"  target="_blank">€160 million to France through July 10th.</a></li>
<li><a href="http://www.un.org/News/Press/docs/2011/sc10200.doc.htm"  target="_blank">Operations began March 17th.</a>)</li>
</ul>
<div>
<h2>Oil trade generalities</h2>
<div>
<ul>
<li><strong><a href="http://hsgac.senate.gov/public/_files/SenatePrint10965MarketSpecReportFINAL.pdf"  target="_blank">At least 30% of the market price of oil is predicated on speculative activity by non-hedgers</strong></a> (i.e. those who do not actually produce or consume oil, such as hedge funds and investment banks), rather than actual supply and demand for the underlying commodity. See especially p. 12 and 19.</li>
<li>Most world oil trade is conducted in US dollars.</li>
<li>This amounts to a large interest-free loan to the US, since other countries must provide goods to the US in exchange for dollars to use buying oil.</li>
<li><a href="http://www.time.com/time/magazine/article/0,9171,998512,00.html"  target="_blank">Saddam Hussein was converting to all-Euro oil trade when the US invaded</a></li>
<li><a href="http://www.guardian.co.uk/business/2009/oct/06/oil-us-dollar-threat-to-america"  target="_blank">China, Russia, Japan, and Gulf states are now supposedly planning to abandon the USD for oil trade.</a></li>
</ul>
</div>
</div>
<h1>Libyan oil production analysis</h1>
<div>
<ul>
<li>Libyan daily production (pre-war) was ≈ 2.07% of the world supply by volume (1.8/86.8).</li>
<li>Libyan proven reserves are about 3.46% of known world reserves</li>
<li>While unquestionably large, <strong>Libyan oil production capacity and proven reserves are both a tiny fraction of extant world supply.</strong></li>
<li>The spread between high and low quality oil is significant, but small. High quality Libyan oil goes for only 13% more than the price of low quality Mayan Heavy, and only 2% more than the average world oil price.</li>
<li>Thus, as a gross first-approximation estimate, <strong>Libya&#8217;s 2% of world production may be said to contribute about (0.0207&#8230; * 1.02) = 2.12% of world price&#8217;s supply component </strong>(2% of world production, and only 2% more expensive than average oil).</li>
<li>The contribution of the supply component to the final market price of oil is unknown. As a crude first approximation, if we assume 30% of the price derives from financial speculators, that leaves 70% for supply and demand. If these are approximately balanced in the long term, as OPEC actively seeks to do via production controls and leaving some capacity idle, then around 35% of the price is supply and around 35% of the price is demand. This means that, <strong>very roughly estimating, Libyan production contributes about 0.7% of the final price of crude oil</strong> (0.35 * 0.0212). This component is in any case most certainly<strong> orders of magnitude less than the ordinary market volatility</strong> induced by speculative capital flows on a daily basis.</li>
<li><strong>Available OPEC excess production capacity is more than capable of making up for lost Libyan production.</strong></li>
<li>OPEC governments have a strong interest in containing the unrest in Libya.</li>
<li>They don&#8217;t really care who wins, so long as it&#8217;s stable.</li>
<li><strong>OPEC would like NATO / US to arrange for stability in Libya</strong>, as part of the oil-for-security compact negotiated with the US during the late stages of the Cold War.</li>
<li>Thus, motivated to make up for the lost production in exchange for NATO doing that.</li>
<li><strong>NATO is at the advantage</strong> in bargaining in the short and medium term:</li>
<ul>
<li>worst case scenario for NATO is long-term higher energy costs.</li>
<li>worst case scenario for OPEC governments is the protests spreading and leading to dissolution of their regimes and wealth.</li>
<li><strong>major inconvenience for NATO vs. an existential threat for OPEC.</strong></li>
</ul>
</ul>
<h1>Costs of the Libyan war to NATO</h1>
</div>
<div>
<ul>
<li>Cost to Britain is appx. $640,000 per day (1.6 * £400,000 per day (£260 million / (3.5 months * 30 days in a month)))</li>
<li>Cost to the US is appx. $9.5 million / day ($716 million / (2.5 months * 30 days))</li>
<li>Cost to France is appx. $1.86 million / day (1.43 * €1.3 million per day (€160 million / (4 months * 30 days))</li>
<li>Costs to other NATO countries are non-negligible but overlooked here for simplicity</li>
<li>Total cost for 3 main players on the NATO side is ≈ $12 million per day</li>
<li>Costs will continue to grow as the war drags on</li>
<li>Not to mention dead people and political costs</li>
</ul>
<h1>Conclusions</h1>
<ul>
<li><strong>Since Libyan oil was already heavily under the sway of western oil companies, and since they were already exporting almost all of their oil to Europe and the US at market prices, in USD, there was no motive to attack them for access to their their oil per se (as in Iraq).</strong></li>
<li>The contribution to the price of oil made by financial speculators (approximately 30%) is far, far higher than the contribution to the price of oil made by Libyan supply (appx. 2.12% of only the supply component of the price).</li>
<ul>
<li>Regulating hedge funds more strictly would be a far less costly and far less controversial way to bring down crude prices, if that were the goal.</li>
</ul>
<li>One might try to make the case that the intervention is designed to protect the capital investments of western companies in Libya from destruction in a civil war, though this would be hard to establish since <strong>Western oil companies&#8217; capital infrastructure (wells, pipelines, etc) would likely be destroyed anyway even with a full-scale NATO intervention.</strong></li>
<li>Even if all Libyan oil were 100% owned by western companies (very unlikely in any scenario), it would still not contribute a significant amount to world oil supply or prices, nor much addition to oil companies&#8217; profit margins compared with what they were making there before the war.</li>
<ul>
<li>They were already making obscene amounts of money in Libya anyway before the war</li>
<li>The war will shut down production entirely for months, perhaps years</li>
<li>The war will destroy much/most of their very expensive physical capital investment in Libya in infrastructure (wells, pipelines, etc.)</li>
<li>thus, <strong>Western oil companies would have been far better off financially if the war had not happened.</strong></li>
</ul>
<li>Therefore, <strong>it&#8217;s most likely that the war is actually an internal Libyan factional dispute, not engineered by evil western imperialist capitalists for their own benefit.</strong></li>
<li>This is far from a full-scale intervention. <strong>$12 million per day is a drop in the bucket compared to what NATO could be spending on this intervention if they so chose.</strong></li>
<li>Thus, <strong>NATO is not very interested in ending the war in Libya</strong>. It&#8217;d be nice, but they aren&#8217;t going to go out of their way, or to any considerable expense, to do so.</li>
<li><strong>More likely, the intervention is a token effort to placate other OPEC governments&#8217; calls for the US/NATO to do something to stabilize the region while not committing to yet another long and politically unpopular foreign war.</strong></li>
<ul>
<li>Also, a message to the Libyans and to Arabs generally that NATO is paying attention, if not intervening at full capacity, to discourage the unrest from spreading beyond Libya</li>
</ul>
<li>The small scale of the intervention vs. capacity to intervene could also be a bargaining tool to attempt to induce OPEC to increase its daily production more or make other similar concessions.</li>
</ul>
</div>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/2wEYKMQPHwE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/libya-nato-intervention-analysis/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/libya-nato-intervention-analysis/</feedburner:origLink></item>
		<item>
		<title>Torrent Contents – List Files in a Torrent</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/O1VmXjaR9N8/</link>
		<comments>http://www.paullegato.com/blog/torrent-contents-list-files/#comments</comments>
		<pubDate>Tue, 31 May 2011 01:51:10 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=526</guid>
		<description><![CDATA[List the contents of a BitTorrent .torrent file with this small Ruby script.]]></description>
				<content:encoded><![CDATA[<p>List the files in a BitTorrent torrent with this quick Ruby script. Requires that you <code>gem install bencode awesome_print</code> before you run it.</p>
<pre class="brush: ruby; title: ; notranslate">

#!/usr/bin/env ruby
#
# torrentdump - prints the contents of a torrent.
#
# Copyright (C) 2011 Paul Legato. All rights reserved.
# Licensed for personal, non-commercial use only.
# This code comes with NO WARRANTY, express or implied.
#
# Prerequisite gem setup:
#   sudo gem install bencode awesome_print
#

require 'rubygems'
require 'bencode'
require 'awesome_print'

unless ARGV[0]
  STDERR.puts &lt;&lt;END

Usage: torrentdump &lt;filename&gt; &lt;-v&gt;

If -v is given, prints the entire contents of the torrent except the binary &quot;pieces&quot; hash data.

If -vv is given, prints everything, including the binary hash data.

Otherwise, prints only the file list.

END
  exit 1
end

# Method from http://stackoverflow.com/questions/3201890/is-there-an-elegant-way-to-remove-a-specific-key-from-a-hash-and-its-sub-hashes
def recursive_delete!(hash, to_remove)
  hash.delete(to_remove)
  hash.each_value do |value|
    recursive_delete!(value, to_remove) if value.is_a? Hash
  end
end

data = BEncode.load(File.read(ARGV[0]).force_encoding(&quot;binary&quot;))

if ARGV[1] == &quot;-vv&quot;
  ap data
elsif ARGV[1] == &quot;-v&quot;
  recursive_delete!(data, &quot;pieces&quot;)
  ap data
else
  if data[&quot;info&quot;][&quot;files&quot;]
    dir = data[&quot;info&quot;][&quot;name&quot;] || &quot;&quot;
    ap data[&quot;info&quot;][&quot;files&quot;].map {|x| dir + &quot;/&quot; + x[&quot;path&quot;].join(&quot;/&quot;) }  
  else
    ap data[&quot;info&quot;][&quot;name&quot;]
  end
end
</pre>
<p>A quick example:</p>
<pre class="brush: plain; title: ; notranslate">
% torrentdump ubuntu-10.04.2-server-i386.iso.torrent 
&quot;ubuntu-10.04.2-server-i386.iso&quot;
</pre>
<h2>Torrent dissection: of interest here..</h2>
<ul>
<li><a target="_blank" href="http://blog.grayproductions.net/articles/understanding_m17n"  class="broken_link">Ruby 1.9 imposes a character encoding on every string</a> by default. This is fine for dealing with text, but caused errors in the <a target="_blank" href="https://github.com/dasch/ruby-bencode" >BEncode</a> library. (For some reason, the authors of BitTorrent chose to re-invent the wheel and developed their own binary encoding format.) We use the <code>#force_encoding</code> method on the torrent data to make Ruby treat the data as raw binary data and not try to interpret it. </li>
<li><a target="_blank" href="http://wiki.theory.org/BitTorrentSpecification" >More than you ever wanted to know about what&#8217;s inside a <code>.torrent file</code></a></li>
</ul>
<p>The <a target="_blank" href="https://github.com/pjlegato/torrentdump" >Torrentdump source code</a> is available on GitHub.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/O1VmXjaR9N8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/torrent-contents-list-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/torrent-contents-list-files/</feedburner:origLink></item>
		<item>
		<title>Stop Calling Your Tests “Stories”</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/pXrEBmEWeYE/</link>
		<comments>http://www.paullegato.com/blog/stop-calling-your-tests-stories/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 22:28:08 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=515</guid>
		<description><![CDATA[Stop calling your tests &#8220;stories.&#8221; Really. They&#8217;re not &#8220;stories&#8221;. They&#8217;re tests. They don&#8217;t tuck you into bed with a glass of warm milk and a nice fairytale to dream about; they assert that certain things should happen and complain when they don&#8217;t, in a purely mechanical and precise way. We&#8217;re programming computers, machines of pure [...]]]></description>
				<content:encoded><![CDATA[<p><strong>Stop calling your tests &#8220;stories.&#8221;</strong> Really.</p>
<p>They&#8217;re not &#8220;stories&#8221;. They&#8217;re tests. They don&#8217;t tuck you into bed with a glass of warm milk and a nice fairytale to dream about; they assert that certain things should happen and complain when they don&#8217;t, in a purely mechanical and precise way. We&#8217;re programming computers, machines of pure logic here, not reading to children. Let&#8217;s dispense with the pointless cutesy façade and focus precisely on the task at hand. </p>
<p>They don&#8217;t deliver what they promise, anyway. Frameworks like <a target="_blank" href="http://rspec.info/" >RSpec</a> and <a target="_blank" href="http://cukes.info/" >Cucumber</a> do <strong>not</strong> let you write tests in &#8220;plain English&#8221;. They let you write tests in a horrible chimeric programming language that adopts a superficial English-like veneer over top of what&#8217;s essentially a regular old unit testing framework.</p>
<p>It winds up giving you the benefits of neither English nor a well written testing API; your code simply becomes excessively verbose for the sake of a (highly fake and brittle) natural language veneer. You&#8217;re still highly restricted in what you can say, just like a regular old programming language. The set of Englishisms that you can use is so grossly restricted and precisely defined that you can&#8217;t think in anything remotely like English. You have to memorize a precise set of rigid, fixed English labels and use that and only that. You do get the verbosity of natural language, though, along with the restricted semantic domain of the API. You get the benefits of neither and the disadvantages of both.</p>
<p>Since you&#8217;re memorizing a highly restricted API anyway, skip the twee cruft and just use a <a target="_blank" href="https://github.com/seattlerb/minitest" >short and</a> <a target="_blank" href="http://test-unit.rubyforge.org/test-unit/Test/Unit/Assertions.html" >precise API</a> from the start, without the pseudo-natural language clutter.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/pXrEBmEWeYE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/stop-calling-your-tests-stories/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/stop-calling-your-tests-stories/</feedburner:origLink></item>
		<item>
		<title>New Lambda Automaton Song: Yo Yo Globe</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/wFP0ocgf2gs/</link>
		<comments>http://www.paullegato.com/blog/new-lambda-automaton-song-yo-yo-globe/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 02:59:13 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[lambdaautomaton]]></category>
		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=502</guid>
		<description><![CDATA[Here&#8217;s a new song I just wrote: Free mp3s/FLACs/etc are available on my Bandcamp site.]]></description>
				<content:encoded><![CDATA[<p>Here&#8217;s a new song I just wrote:</p>
<p><object data="http://bandcamp.com/EmbeddedPlayer/track=3402685039/size=venti/bgcol=FFFFFF/linkcol=e3b04a//" type="text/html" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="100"><param name="movie" value="http://bandcamp.com/EmbeddedPlayer/track=3402685039/size=venti/bgcol=FFFFFF/linkcol=e3b04a//"><param name="quality" value="high"><param name="allowNetworking" value="always"><param name="wmode" value="transparent"><param name="bgcolor" value="#FFFFFF"><param name="allowScriptAccess" value="never"><object data="http://bandcamp.com/EmbeddedPlayer/track=3402685039/size=venti/bgcol=FFFFFF/linkcol=e3b04a//" type="text/html" width="400" height="100"></object></object></p>
<p>Free mp3s/FLACs/etc are <a target="_blank" href="http://lambdaautomaton.com/track/yo-yo-globe"  class="broken_link">available on my Bandcamp site</a>.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/wFP0ocgf2gs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/new-lambda-automaton-song-yo-yo-globe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/new-lambda-automaton-song-yo-yo-globe/</feedburner:origLink></item>
		<item>
		<title>Custom Dialog Boxes Using Cocos2d on iPhone</title>
		<link>http://feedproxy.google.com/~r/PaulLegato/~3/ijtaJAh_Hiw/</link>
		<comments>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 10:13:03 +0000</pubDate>
		<dc:creator>Paul Legato</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[cocos2d]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.paullegato.com/?p=432</guid>
		<description><![CDATA[Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is [...]]]></description>
				<content:encoded><![CDATA[<p>Custom dialog boxes are a must for any game. iPhone&#8217;s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is a great way to subtly interrupt the immersiveness of their gameplay experience. We don&#8217;t want that, so we need to customize.</p>
<div id="attachment_434"  class="wp-caption center"  style="width: 779px;"><a href="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png"  class="galleryAndCaptionItem" title="" rel="nofollow"><img class="size-full wp-image-434" title="iPhone UIAlertView to custom dialog box example" src="http://www.paullegato.com/wp-content/uploads/2010/12/iPhone-custom-dialog-box.png" alt="iPhone UIAlertView to custom dialog box example. Doesn't the custom one look much better?" width="769" height="268"/></a><span class="wp-caption-text"></span></div>
<p><a target="_blank" href="http://www.cocos2d-iphone.org/" >Cocos2d</a> makes it easy to convert your drab standard UIAlertViews into glorious customized color dialog boxes. Above is an actual UIAlertView / custom dialog box transition from my upcoming iPhone game. Here&#8217;s how I did it. <span id="more-432"></span></p>
<h1>Implementing a Custom Dialog Box in Cocos2d</h1>
<h2>Cocos2d Scene Structure</h2>
<p>Cocos2d uses a <a target="_blank" href="http://en.wikipedia.org/wiki/Scene_graph" >scene graph</a> to hold everything being displayed at any given point in a game. Informally, this data structure is a hierarchy of objects, each of which might display something onscreen, contain other objects to be displayed onscreen, or both. In Cocos2d, these objects are descendants of the <code>CCNode</code> class. </p>
<p>Related objects can be placed into a single container object, which allows them all to be manipulated as a unit when necessary. The root, or lowest-level, container at any given time is an instance of the <code>CCScene</code> class. A <code>CCScene</code> contains <code>CCLayer</code> objects, which themselves contain other objects such as menu labels or sprites to be displayed. Layers, as the name implies, are displayed superimposed upon each other onscreen, which makes a <code>CCLayer</code> perfect for our custom dialog box.</p>
<h2>Custom <code>CCLayer</code></h2>
<p>Here&#8217;s the code for <code>DialogLayer.h</code> and <code>DialogLayer.m</code>. These implement a basic but perfectly servicable custom iPhone dialog box. It can be used as-is or expanded in any number of ways for particular situations. Take a look through the finished product, and then we&#8217;ll go over it below.</p>
<h3><code>DialogLayer.h</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.h
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &lt;Foundation/Foundation.h&gt;
#import &quot;cocos2d.h&quot;

@interface DialogLayer : CCLayer {
  NSInvocation *callback;
}

-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector;
-(void) okButtonPressed:(id) sender;

@end
</pre>
<h3><code>DialogLayer.m</code></h3>
<pre class="brush: objc; title: ; notranslate">
//
//  DialogLayer.m
//  concentrate
//
//  Created by Paul Legato on 12/4/10.
//  Copyright 2010 Paul Legato. All rights reserved.
//

#import &quot;DialogLayer.h&quot;
#import &quot;GameSoundManager.h&quot;

#define DIALOG_FONT @&quot;bicho.fnt&quot;

@implementation DialogLayer
-(id) initWithHeader:(NSString *)header andLine1:(NSString *)line1 andLine2:(NSString *)line2 andLine3:(NSString *)line3 target:(id)callbackObj selector:(SEL)selector
 {
   if((self=[super init])) {

     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];

     CGSize screenSize = [CCDirector sharedDirector].winSize;
     
     CCSprite *background = [CCSprite node];
     [background initWithFile:@&quot;Dialog.png&quot;];
     [background setPosition:ccp(screenSize.width / 2, screenSize.height / 2)];
     [self addChild:background z:-1];


     CCLabelBMFont *headerShadow = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerShadow.color = ccGRAY;
     headerShadow.opacity = 127;
     [headerShadow setPosition:ccp(243, 262)];
     [self addChild:headerShadow];

     CCLabelBMFont *headerLabel = [CCLabelBMFont labelWithString:header fntFile:DIALOG_FONT];
     headerLabel.color = ccBLACK;
     [headerLabel setPosition:ccp(240, 265)];
     [self addChild:headerLabel];

     //////////////////

     CCLabelBMFont *line1Label = [CCLabelBMFont labelWithString:line1 fntFile:DIALOG_FONT];
     line1Label.color = ccBLACK;
     line1Label.scale = 0.84f;
     [line1Label setPosition:ccp(240, 200)];
     [self addChild:line1Label];

     CCLabelBMFont *line2Label = [CCLabelBMFont labelWithString:line2 fntFile:DIALOG_FONT];
     line2Label.color = ccBLACK;
     line2Label.scale = 0.84f;
     [line2Label setPosition:ccp(240, 160)];
     [self addChild:line2Label];

     CCLabelBMFont *line3Label = [CCLabelBMFont labelWithString:line3 fntFile:DIALOG_FONT];
     line3Label.color = ccBLACK;
     line3Label.scale = 0.84f;
     [line3Label setPosition:ccp(240, 120)];
     [self addChild:line3Label];

     CCMenuItemImage *okButton = [CCMenuItemImage itemFromNormalImage:@&quot;OKButton.png&quot; selectedImage:@&quot;OKButtonSelected.png&quot; target:self selector:@selector(okButtonPressed:)];
     [okButton setPosition:ccp(0, 60)];

     CCMenu *menu = [CCMenu menuWithItems: okButton, nil];
     menu.position = ccp(240,0);
     [self addChild:menu];
   }
   return self;
 }

-(void) okButtonPressed:(id) sender
 {
   [[GameSoundManager sharedManager].soundEngine playEffect:@&quot;OK.caf&quot;
                                    pitch:1.0f
                                    pan:0.0f
                                    gain:1.0f];

   [self removeFromParentAndCleanup:YES];
   [callback invoke];
 }


-(void) dealloc
 {
   [callback release];
   [super dealloc];
 }
@end
</pre>
<p><H1>Custom dialog box code analysis</h1>
<h2>Overview</h2>
<p>The dialog box is implemented as a subclass of <code>CCLayer</code>. An <code>initWithHeader</code> method is provided to initialize the layer with a given message and a specified callback method that will be invoked when the dialog&#8217;s &#8220;OK&#8221; button is pressed. It also plays a confirmation sound and switches the &#8220;OK&#8221; button&#8217;s image to a &#8220;pressed button&#8221; when the user taps it.</p>
<p><code>DialogLayer.m</code> requires a few external supports, which must be available as project resources. <code>Dialog.png</code> is the dialog box&#8217;s background image. <code>bicho.fnt</code> is an AngelCode format bitmapped font, used for the labels, and can be substituted with any font you like. <code>OKButton.png</code> and <code>OKButtonSelected.png</code> are the images to be used for the button in unpressed and pressed forms. Finally, <code>OK.caf</code> is the audio file to be played when the user taps the button.</p>
<h2>Analysis</h2>
<h3>Storing the callback</h3>
<pre class="brush: objc; title: ; notranslate">
     NSMethodSignature *sig = [[callbackObj class] instanceMethodSignatureForSelector:selector];
     callback = [NSInvocation invocationWithMethodSignature:sig];
     [callback setTarget:callbackObj];
     [callback setSelector:selector];
     [callback retain];
</pre>
<p>This code is Objective C&#8217;s (massively redundant) way of storing the callback to be activated when the dialog&#8217;s button is pressed. It&#8217;s based on the callback code in Cocos2d itself. (We could also have used <a target="_blank" href="http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html" >Objective C&#8217;s new closure data type, called &#8220;blocks&#8221;</a>, but that syntax grates my Lispy sensibilities even more than the overly verbose Javaish mess here, besides not working out of the box on older versions of iOS.) </p>
<p>The <code>initWithHeader</code> method is given a target object and a method selector. It looks up the class of the target object and then looks up the selector on that class at line 1, resulting in a <code>NSMethodSignature</code> object which encapsulates the class-method combination. Line 2 transforms that class-method signature into an &#8220;invocation,&#8221; which represents the act of actually calling that method on some as yet unspecified object. Line 3 associates the invocation with the particular target object we were given, and line 4 associates the selector (which is utterly odd, since the desired method is encoded in the signature object already.) Finally, we retain the callback so that we can save it for later (to be activated when the user actually presses the &#8220;OK&#8221; button) and it won&#8217;t be deallocated at the end of the present scope.</p>
<h3>Setting up the background and labels</h3>
<p>The remainder of the <code>initWithHeader</code> method, lines 25 to 68 in the main listing above, is pretty straightforward. A <code>CCSprite</code> object is created to store the background image and added to <code>self</code>, that is, to the new custom layer being created. Its position is set to be the center of the screen, and its level on the Z axis is set to -1 so that it will appear below anything else added in the layer.</p>
<p><code>CCLabelBMFont</code>s are then created for the given text and added to the new layer. A shadow effect is created for the header by writing the same thing in grey at a slight offset underneath the main text. All lines except the header are then scaled down to 0.84 of their natural size, so as to enhance the prominence of the header.</p>
<p>A <code>CCMenuItemImage</code> is finally created to be the &#8220;OK&#8221; button. It&#8217;s added to a <code>CCMenu</code>, which handles the logic of button presses for us, and the <code>CCMenu</code> is then added to the new layer. It will take a little experimentation to get the exact placement of the OK button correct (lines 64 and 67) relative to your background image.</p>
<p>Note that the OK button itself takes callback arguments of exactly the same type that our <code>initWithHeader</code> method does (line 63). We might be tempted to forego the construction of our own callback object and just pass the given target and selector on to the OK button, simplifying the design of our <code>DialogLayer</code> a bit, but then we wouldn&#8217;t have the chance to play a sound when the OK buton is pressed. More seriously, we would have no way to destroy the dialog layer and remove it from the screen. So, we give the OK button a target of <code>self</code> and tell it to call the <code>okButtonPressed</code> method when OK is pressed.</p>
<h3>The <code>okButtonPressed</code> callback</h3>
<p>The <code>CCMenuItemImage</code> will invoke this method when the user presses &#8220;OK&#8221;. This means that it&#8217;s time to remove the <code>DialogLayer</code> from the scene (easy enough, line 80). Here, we also play a little click-type sound to make the game seem more interactive; also easy with CocosDenshion, lines 75-78. If you don&#8217;t want to play a sound, you can remove those lines and the <code>GameSoundManager.h</code> include file.</p>
<h3>dealloc</h3>
<p>Nothing fancy here; we just release our retained <code>callback</code> object and then defer to <code>super</code>.</p>
<h1>Using the custom <code>DialogLayer</code></h1>
<p>Adding a custom dialog layer to your game scene is very easy:</p>
<pre class="brush: objc; title: ; notranslate">
   CCLayer *dialogLayer = [[[DialogLayer alloc] 
                            initWithHeader:@&quot;Level 1&quot; 
                            andLine1:@&quot;Tilt The Phone&quot; 
                            andLine2:@&quot;To Balance&quot; 
                            andLine3:@&quot;The Ball!&quot;
                            target:self
                            selector:@selector(beginLevelOne)] autorelease];
   [self addChild:dialogLayer z:200];
</pre>
<h1>Future Expansions</h1>
<p><code>DialogLayer</code> is a simple modal dialog box that can only accept one action from the user. It can easily be enhanced in many ways, depending on your needs. The most obvious enhancement is to add multiple buttons to allow the user to make a choice rather than simply dismissing the box. It could be modified to accept an arbitrary amount of text and divide it up automatically into an aesthetically pleasing configuration.</p>
<p>One thing that <code>DialogLayer</code> does <em>not</em> do is pause the game. I decided that that is not necessarily desirable in all cases; many game scenarios need to present information to the user without stopping the action. It&#8217;s easy enough to pause manually when activating the dialog.</p>
<p>Little enhancements like this are critical as &#8216;polish&#8217; for your game.</p>
<img src="http://feeds.feedburner.com/~r/PaulLegato/~4/ijtaJAh_Hiw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.paullegato.com/blog/custom-dialog-boxes-cocos2d-iphone/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.593 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-24 03:56:48 -->
