<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:snf="http://www.smartnews.be/snf" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        <title>
            <![CDATA[
            Axiomatic Semantics
            ]]>
        </title>
        <link>https:&#x2F;&#x2F;axiomatic.neophilus.net</link>
        <atom:link href="https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;rss.xml" rel="self" type="application/rss+xml"/>
        <description>
            <![CDATA[
            Brute force solutions with proofs by intimidation
            ]]>
        </description>
        <language>en</language>
        <lastBuildDate>Thu, 29 Mar 2018 00:00:00 +0000</lastBuildDate>
        
            <item>
                <title>
                    <![CDATA[
                    Accessing partially recursive data structures in Elm
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;accessing-partially-recursive-data-structures-in-elm&#x2F;</link>
                <pubDate>Thu, 29 Mar 2018 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    A comment on commenting systems, implementation discussion for your discussions on implementations.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>So you've read over the <a href="https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/recursive-alias.md">Recursive Type Aliases</a> hints in the <strong>Elm</strong> compiler documentation and that all seems straightforward.
Mainly because it is, but unfortunately simple examples like this are seldom actually useful when you need to actually <em>do</em> something.</p>
<p>In my <a href="/nesting-structures-from-flat-indexes/">last post</a>, I talked about generating a nested structure of comments and any replies pulled from a database at the backend of <a href="https://github.com/Libbum/oration">oration</a>, so that this data could be exposed via an <abbr title="Application Program Interface">API</abbr> in <abbr title="JavaScript Object Notation">JSON</abbr> format.
Now, I'd like to continue the conversation at the frontend—hopefully answering the question: how do we invoke a recursive type and do some work with one?</p>
<p><a name="continue-reading"></a>
Let's start out with a <a href="https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/recursive-alias.md#less-obvious-but-nicer">less obvious but nicer</a> layout for our comments and replies:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">type alias Comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> text </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">String
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Maybe String
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> hash </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">String
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> created </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">DateTime
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Int
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Int
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Responses
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> visible </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Bool
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> editable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Bool
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Bool
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#c594c5;">type Responses
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;">List Comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span></pre>
<p>At this point, the documentation gives you a nice looking <code>upvote</code> example function which for here would look like <code>{ comment | votes = 1 + comment.votes }</code> for any given <code>comment</code>.
Directly after this though, a small additional quip is added:</p>
<blockquote>
<p>So rather than having to unwrap a Comment to do anything to it, you only have to do some unwrapping in the cases where you are doing something recursive.</p>
</blockquote>
<p>That's great and all (and perhaps someone more versed in <strong>Elm</strong> could set me straight here), but when in this situation would you only be applying functions like <code>upvote</code> to <code>Comments</code> and not <code>Responses</code>?
Since it's considered poor form to index into a list/array in a functional language, such unwrapping seems inevitable.</p>
<h2 id="voting"><a class="gutenberg-anchor" href="#voting" aria-label="Anchor link for: voting">🔗</a>
Voting</h2>
<p>So let's have a look at <a href="https://github.com/Libbum/oration/">oration</a>'s version of <code>upvote</code> to start with.
Each comment's view has like and dislike buttons, which trigger two respective functions on a click event.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">like </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; List Comment -&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">like </span><span style="background-color:#2b2c2f;color:#cccece;">id comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> voteComment </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#6699cc;">, </span><span style="background-color:#2b2c2f;color:#cccece;">True </span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">dislike </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; List Comment -&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">dislike </span><span style="background-color:#2b2c2f;color:#cccece;">id comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> voteComment </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#6699cc;">, </span><span style="background-color:#2b2c2f;color:#cccece;">False </span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span></pre>
<p>Notice the only difference is the value of the bool passed to <code>voteComment</code>, which as you can see, indicates a positive reaction if true.
The reason why we wrap <code>id</code> and the bool into a tuple will become apparent soon.</p>
<p>The layout of both functions is representative of all top level functions that work on a <code>List Comment</code>.
We map over all <code>Comment</code>s in the <code>List</code>, and invoke a helper function inside an anonymous function.
If you're not familiar with functional programming, you can conceptualise this by thinking about <code>for i=1:N</code>, where the for loop is the map, <code>i</code> is <code>comment</code> inside the anonymous function and <code>N</code> would be the length of <code>comments</code>.
The map will visit all elements and expect something in return, but this could just be the element itself without any changes.</p>
<p>Perhaps my thinking here is not functional enough, since as you see I still pass around an <code>id</code>.
This value is stored in the backend database and we need to connect to that at some stage, thus it doesn't represent an index in the list, so hopefully I'm not committing a functional sin with this.
If my view somehow returned the <code>Comment</code> that was just clicked on, this would dramatically reduce the complexity here, and maybe this post wouldn't need to be written.
For the moment though, let's move forward with possibly only a partial understanding of the problem space—this is how we learn.
Since the <code>id</code> could be anywhere in the data structure, we have to map across all elements (which include all recursive <code>Responses</code> lists) to identify the correct comment to alter the vote on.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">voteComment </span><span style="background-color:#2b2c2f;color:#c594c5;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> ( </span><span style="background-color:#2b2c2f;color:#c594c5;">Int</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">Bool</span><span style="background-color:#2b2c2f;color:#cccece;"> ) </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; Comment -&gt; Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">voteComment </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> like </span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">count </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">like </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">True </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">+ </span><span style="background-color:#2b2c2f;color:#f99157;">1
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">False </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">- </span><span style="background-color:#2b2c2f;color:#f99157;">1
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> count
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">False
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">mapChildren </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> like </span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comment voteComment
</span></pre>
<p>In the end, this is ultimately the same as the example <code>upvote</code> function, but it allows you to find the correct comment in the list to upvote.
Two simple aspects of the function we can get out of the way first are the <code>votable</code> bool, which just removes the ability for someone to spam multiple upvote requests to the backend—they should only be able to vote once.
Second, the <code>count</code> variable converts a like or dislike into an increment or decrement on the total vote count.
<code>votes</code> therefore has the ability to cross the zero threshold and become a positive number.
This is probably overkill for an internet commenting system, but it's an edge case we can support without too much hassle.</p>
<p>It's the call to <code>mapChildren</code> when we don't match on <code>id</code> where the magic happens though.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">mapChildren </span><span style="background-color:#2b2c2f;color:#c594c5;">: </span><span style="background-color:#2b2c2f;color:#cccece;">a </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; Comment -&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> (a </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; Comment -&gt; Comment</span><span style="background-color:#2b2c2f;color:#cccece;">) </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">mapChildren </span><span style="background-color:#2b2c2f;color:#cccece;">value comment operation </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;| </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">response </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> operation value response</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> responses
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span></pre>
<p>The function takes a variable of any type, a <code>Comment</code> and a function that takes both of these.
Whilst I'm quite certain that it's possible to simplify this type signature with currying; let's just say that I've kept it explicit like this for you, the reader, to work out on your own.
Write your answer in a comment below—I'll hold of on committing the correct answer to the <a href="https://github.com/Libbum/oration">oration</a> repo until such time as we identify a winner.
Most of the examples I'll go through below only need to pass an <code>Int</code> (in the form of <code>id</code>), but here we need both an <code>Int</code> and a <code>Bool</code>—hence the tuple in <code>voteComment</code>.
The <code>a</code> here is type agnostic and lets us pass anything.</p>
<p>Inside the function, the case statement unwraps any list of replies into the <code>responses</code> variable for the current comment.
As you can see in the initial type signature, <code>responses</code> is now a <code>List Comment</code>, which we can map over in the same manner we did with its parent.
Notice that this calls <code>voteComments</code> in our example above from this nested position (or in fact any function identified as <code>operation</code> which we'll discuss below), and will continue to recurse down each branch of this comment list, checking each one.
The result is returned and re-wrapped into the <code>Responses</code> type via the <code>&lt;|</code> operator, which effectively means <em>apply the result of this function to the left</em>.</p>
<h2 id="visibility"><a class="gutenberg-anchor" href="#visibility" aria-label="Anchor link for: visibility">🔗</a>
Visibility</h2>
<p>With that machinery now built, we can extend the idea to other methods.
For example, if you wish to hide a comment thread, you must at least flag the visibility of the root comment (then, you can remove it and all its children in your view method).</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">toggleVisible </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; List Comment -&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">toggleVisible </span><span style="background-color:#2b2c2f;color:#cccece;">id comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> switchVisible id comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">switchVisible </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; Comment -&gt; Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">switchVisible </span><span style="background-color:#2b2c2f;color:#cccece;">id comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> visible </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> not comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">visible </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">mapChildren </span><span style="background-color:#2b2c2f;color:#cccece;">id comment switchVisible
</span></pre>
<p>As you can see, the templating here is effectively the same—update if there's a hit on <code>id</code>, recurse through the children if not.</p>
<h2 id="updating"><a class="gutenberg-anchor" href="#updating" aria-label="Anchor link for: updating">🔗</a>
Updating</h2>
<p>Updating a comment is a little more complex, but nothing overtly obtuse.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">update </span><span style="background-color:#2b2c2f;color:#c594c5;">: Edited -&gt; List Comment -&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">update </span><span style="background-color:#2b2c2f;color:#cccece;">edit comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> injectUpdates edit comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">injectUpdates </span><span style="background-color:#2b2c2f;color:#c594c5;">: Edited -&gt; Comment -&gt; Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">injectUpdates </span><span style="background-color:#2b2c2f;color:#cccece;">edit comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">edit</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> text </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> edit</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">text
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> edit</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">author
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> hash </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> edit</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">hash
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> editable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">True
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">mapChildren </span><span style="background-color:#2b2c2f;color:#cccece;">edit comment injectUpdates
</span></pre>
<p>Here I've type aliased a subset <code>Comment</code> to sandbox what a user has access to.
This <code>Edited</code> type therefore has the required changes needed for some <code>id</code>.
When the <code>id</code> of a <code>comment</code> in the list and our edited value matches we transfer the values.
It's still possible to leverage the <code>mapChildren</code> function, since the agnostic <code>a</code> type is happy to pass an <code>Edited</code> type down the line.</p>
<h2 id="alterations-on-the-list"><a class="gutenberg-anchor" href="#alterations-on-the-list" aria-label="Anchor link for: alterations-on-the-list">🔗</a>
Alterations on the list</h2>
<p>OK, so we can now alter components of each comment without too much hassle, but what about operating on the list in general?</p>
<p>There are number of these alterations in the <a href="https://github.com/Libbum/oration/blob/master/app/elm/Data/Comment.elm">Data.Comment</a> module if you're looking for more examples, but this post is getting long as it is so we'll stick to just two—they are mostly more of the same but cater to different edge cases.</p>
<h3 id="inserting-a-comment"><a class="gutenberg-anchor" href="#inserting-a-comment" aria-label="Anchor link for: inserting-a-comment">🔗</a>
Inserting a Comment</h3>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">insertNew </span><span style="background-color:#2b2c2f;color:#c594c5;">: Inserted -&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> ( </span><span style="background-color:#2b2c2f;color:#c594c5;">String</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">String</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">DateTime</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">List Comment</span><span style="background-color:#2b2c2f;color:#cccece;"> ) </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">insertNew </span><span style="background-color:#2b2c2f;color:#cccece;">insert current </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;"> commentText</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> hash</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> now</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> comments </span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">current
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">newComment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> text </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> commentText
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> insert</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">author
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> hash </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> hash
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> created </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> now
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> insert</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">0
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#6699cc;">[]
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> visible </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">True
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> editable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">True
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">False
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">isNothing insert</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">parent </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">++ </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">singleton newComment
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> injectNew insert newComment comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">injectNew </span><span style="background-color:#2b2c2f;color:#c594c5;">: Inserted -&gt; Comment -&gt; Comment -&gt; Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">injectNew </span><span style="background-color:#2b2c2f;color:#cccece;">insert newComment comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> insert</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">parent </span><span style="background-color:#2b2c2f;color:#5fb3b3;">? -</span><span style="background-color:#2b2c2f;color:#f99157;">1 </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;|</span><span style="background-color:#2b2c2f;color:#cccece;"> responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">++ </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">singleton newComment
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;| </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">response </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> injectNew insert newComment response</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> responses
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span></pre>
<p>Let's unpack this one a little.
There are a few inputs which allow us to construct the <code>newComment</code>, along with some defaults including an empty <code>Responses</code> list.
The if statement in <code>insertNew</code> checks if the type aliased <code>Inserted</code> structure (which consists of an <code>id</code>, <code>parent</code> and <code>author</code>) has a parent.
In the case of a genuine new comment, we append it to the list, otherwise the standard helper function template is invoked to search for the right place to put the reply.</p>
<p>The <code>children</code> check can't be done via <code>mapChildren</code> since we need to do something a little more complex in this situation.
The method herein attempts to identify the parent id (the <code>insert.parent</code> value is of the <code>Maybe Int</code> type, so we need to unwrap it with a known failure of -1), and if matched we can append the new comment to the end of this <code>Responses</code> list, otherwise we must go deeper.</p>
<h3 id="comment-deletion"><a class="gutenberg-anchor" href="#comment-deletion" aria-label="Anchor link for: comment-deletion">🔗</a>
Comment Deletion</h3>
<p><a href="https://github.com/Libbum/oration/">Oration</a> has two deletion methods, since it's possible that a user (or an admin) wishes to remove an unwanted comment but keep the corresponding replies.
In this instance we effectively cripple the comment—removing all content and author details concerning it, but keep its <code>id</code> and timestamp information so that replies can be rendered in the correct manner.</p>
<p>Alternatively, the is no need to store anything about a deleted comment with no children, so we purge these.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">delete </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; List Comment -&gt; List Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">delete </span><span style="background-color:#2b2c2f;color:#cccece;">id comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> filterComment id comment</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> comments
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> values
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">filterComment </span><span style="background-color:#2b2c2f;color:#c594c5;">: Int -&gt; Comment -&gt; Maybe Comment
</span><span style="background-color:#2b2c2f;color:#6699cc;">filterComment </span><span style="background-color:#2b2c2f;color:#cccece;">id comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5f6364;">--Pure deletes only happen on comments with no children, so only filter if that&#39;s the case
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">noChildren </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">isEmpty responses
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">noChildren </span><span style="background-color:#2b2c2f;color:#c594c5;">then
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">Nothing
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5f6364;">--We must display a masked delete
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#6699cc;">children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                            </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;|</span><span style="background-color:#2b2c2f;color:#cccece;"> values </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;| </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">response </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> filterComment id response</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> responses
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">Just
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> children
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">Nothing
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> hash </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= &quot;&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> text </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= &quot;&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votes </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">0
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> votable </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">False
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">let
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#cccece;">Responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;|</span><span style="background-color:#2b2c2f;color:#cccece;"> values </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;| </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">map </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">response </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> filterComment id response</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> responses
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">in
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">Just </span><span style="background-color:#2b2c2f;color:#6699cc;">{</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">|</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> children </span><span style="background-color:#2b2c2f;color:#6699cc;">}
</span></pre>
<p>These two possibilities force us to alter our template a bit.
On one hand, we may return from our recursion with a complete list with an altered comment, on the other we may have removed a comment entirely.
Thus, it's necessary to return a <code>Maybe Comment</code> from our helper function, then filter out any empty elements using <code>|&gt; values</code> in the outer function <code>delete</code>.</p>
<p>Once we're in the helper function, we can asses each <code>comment</code>'s properties.
Initially, there's a check for an empty children list, which is used to completely delete the comment.
Otherwise, the response is a crippled comment with no data other than its complete child list.
The <code>children</code> methods unwrap <code>Responses</code> in a similar to that of <code>mapChildren</code>, although the <code>Maybe</code> values must be handled explicitly.</p>
<h2 id="counting-comments"><a class="gutenberg-anchor" href="#counting-comments" aria-label="Anchor link for: counting-comments">🔗</a>
Counting Comments</h2>
<p>There's something more simple than all of this that is paramount, and that's counting how many elements you have in this nested list of yours.</p>
<p>No problem right?</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">count </span><span style="background-color:#2b2c2f;color:#c594c5;">: List Comment -&gt; Int
</span><span style="background-color:#2b2c2f;color:#6699cc;">count </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">foldl </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">_ acc </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> acc </span><span style="background-color:#2b2c2f;color:#5fb3b3;">+ </span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#f99157;">0
</span></pre>
<p>But this is only going to count your original, root comments and ignore all replies.
We need to overload the <code>foldl</code> function for our type.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">foldl </span><span style="background-color:#2b2c2f;color:#c594c5;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> (</span><span style="background-color:#2b2c2f;color:#c594c5;">Comment -&gt; </span><span style="background-color:#2b2c2f;color:#cccece;">b </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; </span><span style="background-color:#2b2c2f;color:#cccece;">b) </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; </span><span style="background-color:#2b2c2f;color:#cccece;">b </span><span style="background-color:#2b2c2f;color:#c594c5;">-&gt; List Comment -&gt; </span><span style="background-color:#2b2c2f;color:#cccece;">b
</span><span style="background-color:#2b2c2f;color:#6699cc;">foldl </span><span style="background-color:#2b2c2f;color:#cccece;">f </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">List</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">foldl
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#cccece;">c acc </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">case </span><span style="background-color:#2b2c2f;color:#cccece;">c</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">children </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#cccece;">Responses responses </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#6699cc;">foldl </span><span style="background-color:#2b2c2f;color:#cccece;">f </span><span style="background-color:#2b2c2f;color:#c594c5;">(</span><span style="background-color:#2b2c2f;color:#cccece;">f c acc</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#cccece;"> responses
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span></pre>
<p>Here, we accumulate all the way down each comment branch, and once that's done use the list left fold method to sum the result, which in turn is passed up the chain.</p>
<hr />
<p>For an imperative programmer, functional methods can sometimes seem confusing.
It takes time for them to 'click', but once that happens there is a certain elegance to writing code in this way.
No doubt, a true functional aficionado would scoff at most of this post, so please, if you are such a person—let me know what I can do to improve this.
For the rest of you, I hope that this gives you some more in depth examples to help you with your own projects.</p>
<p><strong>Update 2018-04-05:</strong> Concerning the closing remarks here, writing this post actually made me 'click' even more, allowing me to cut around 30% of the logic in the <a href="https://github.com/Libbum/oration/blob/master/app/elm/Data/Comment.elm">Data.Comment</a> module and simplify this post down in its complexity a good deal.
Feel free to take a look at the history of the module and this post on Github to see the changes.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;accessing-partially-recursive-data-structures-in-elm&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/forest-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Elm</category>
                
                    <category>Algorithms</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Nesting Structures from Flat Indexes
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;nesting-structures-from-flat-indexes&#x2F;</link>
                <pubDate>Sat, 24 Mar 2018 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    I don&#x27;t always use recursion; but when I do, I don&#x27;t always use recursion.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>SQL databases are still one of the best ways of storing relational data, but sometimes you hit a wall transferring your representation to or from a table based layout.</p>
<p>Say we have a table full of <code>Foo</code>s, where some <code>Foo</code>s may have other <code>Foo</code> parents.
This can easily be represented in a table with some unique primary key <code>id</code>, a secondary key <code>parent</code>, which joins to the parent's <code>id</code>, and whatever <code>data</code> <code>Foo</code> may hold.
Retrieving this table into a <strong>rust</strong> data structure, we'd find ourselves with something like <code>Vec&lt;Foo&gt;</code>, where <code>Foo</code> is defined as</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">struct </span><span style="background-color:#2b2c2f;color:#cccece;">Foo </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">parent</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>This isn't really the best way to represent these data though, what you really want is more akin to</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">struct </span><span style="background-color:#2b2c2f;color:#cccece;">Bar </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">children</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">Bar</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p><a name="continue-reading"></a>
This is a problem I came up against when writing the comment <abbr title="Application Program Interface">API</abbr> for <a href="https://github.com/Libbum/oration">Oration</a>.
Each comment is inserted into the database without too much hassle.
We know the parent <code>id</code>, since the frontend forwards us that information, and the unique primary key is simply auto-incremented.
When a select statement returns all comment data for a particular thread, we get a vector of <code>PrintedComment</code>s back.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5f6364;">// Pull data from DB for a given `path`. `conn` here is the connection to the backend database
</span><span style="background-color:#2b2c2f;color:#c594c5;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">PrintedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt; = </span><span style="background-color:#2b2c2f;color:#cccece;">PrintedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">list</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">conn</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> path</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)?;
</span></pre>
<p>The complete <code>PrintedComment</code> struct looks like the following at the time of writing:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">#[</span><span style="background-color:#2b2c2f;color:#cccece;">derive</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">Serialize</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> Queryable</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> Debug</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)]
</span><span style="background-color:#2b2c2f;color:#5f6364;">/// Subset of the comments table which is to be sent to the frontend.
</span><span style="background-color:#2b2c2f;color:#c594c5;">struct </span><span style="background-color:#2b2c2f;color:#cccece;">PrintedComment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Primary key.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Parent comment.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">parent</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Actual comment.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">text</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters author if given.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">author</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">String</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters email address if given.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">email</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">String</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters website if given.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">url</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">String</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters indentifier.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">hash</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Timestamp of creation.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">created</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> NaiveDateTime,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Number of likes a comment has recieved.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">likes</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Number of dislikes a comment has recieved.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">dislikes</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>Since we want to show comment <em>threads</em> to the user; having entries in a flat list, sorted effectively by date isn't that helpful.
We need a <code>NestedComment</code> layout:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">#[</span><span style="background-color:#2b2c2f;color:#cccece;">derive</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">Serialize</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> Debug</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)]
</span><span style="background-color:#2b2c2f;color:#5f6364;">/// Subset of the comments table which is to be nested and sent to the frontend.
</span><span style="background-color:#2b2c2f;color:#c594c5;">pub struct </span><span style="background-color:#2b2c2f;color:#cccece;">NestedComment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Primary key.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Actual comment.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">text</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters author if given.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">author</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Option</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">String</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Commenters indentifier.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">hash</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> String,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Timestamp of creation.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">created</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">DateTime</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">Utc</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Comment children.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">children</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">NestedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">/// Total number of votes.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">votes</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>I'll skip over some of the conversions here, but you can clearly see we compress the commenter's contact details into <code>author</code>, and sum <code>votes</code>.
Most importantly though, we need a way to implement the nesting.</p>
<p>We know that our comments will have at most one parent, and that parent will not be itself.
In that sense, the tree structure we wish to build can be considered as a special case of a directed digraph, and the method to generate a set of <code>NestedComment</code>s involves building such a graph of all <code>PrintedComment</code>s; traversing it recursively, then returning sets of children at each level.</p>
<p><a href="https://github.com/bluss">Bluss</a> has written an excellent graph data structure library called <a href="https://github.com/bluss/petgraph">petagraph</a> from which we'll build a <code>petgraph::DiGraphMap</code>—a directed graph that allows us to control the node <code>id</code>s.
If a node has a parent, we ensure that exists in the graph and add an edge from the parent to the child.
If it doesn't have a parent, we know this is one of our top-level comments, so we stash it aside for later:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">let mut</span><span style="background-color:#2b2c2f;color:#cccece;"> graph </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">DiGraphMap</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">new</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#c594c5;">let mut</span><span style="background-color:#2b2c2f;color:#cccece;"> top_level_ids </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#fac863;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">new</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#c594c5;">for</span><span style="background-color:#2b2c2f;color:#cccece;"> comment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">in &amp;</span><span style="background-color:#2b2c2f;color:#cccece;">comments </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//For each comment, build a graph of parents and children
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">add_node</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Generate edges if a relationship is found, stash as a root if not
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if let </span><span style="background-color:#2b2c2f;color:#fac863;">Some</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">parent_id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) =</span><span style="background-color:#2b2c2f;color:#cccece;"> comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">parent </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">add_node</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">parent_id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">add_edge</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">parent_id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, ());
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">top_level_ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">push</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>Next, we iterate over all of the top-level <code>id</code>s and collect our children:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5f6364;">//Run over all root comments, recursively filling their children as we go
</span><span style="background-color:#2b2c2f;color:#c594c5;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> tree</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;_&gt; =</span><span style="background-color:#2b2c2f;color:#cccece;"> top_level_ids
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">into_iter</span><span style="background-color:#2b2c2f;color:#5fb3b3;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">map</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(|</span><span style="background-color:#2b2c2f;color:#f99157;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">| </span><span style="background-color:#2b2c2f;color:#6699cc;">build_tree</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&amp;</span><span style="background-color:#2b2c2f;color:#cccece;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, &amp;</span><span style="background-color:#2b2c2f;color:#cccece;">comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">))
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">collect</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span></pre>
<p>The <code>build_tree</code> function is the recursive core of the problem.
The implementation first (again) calls the recursive map for all comments and collects direct children at this level into a vector.
The <code>::new</code> constructor on <code>NestedComment</code> is passed this populated list of children, building the complete struct for the given top-level <code>id</code>.
If the child vector is empty, we know the current comment has no replies, and we can therefore pass an empty vector to the <code>NestedComment</code> constructor.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5f6364;">/// Construct a nested comment tree from the flat indexed data obtained from the database.
</span><span style="background-color:#2b2c2f;color:#c594c5;">fn </span><span style="background-color:#2b2c2f;color:#6699cc;">build_tree</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: &amp;</span><span style="background-color:#2b2c2f;color:#cccece;">DiGraphMap</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">()&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#f99157;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">i32</span><span style="background-color:#2b2c2f;color:#cccece;">, </span><span style="background-color:#2b2c2f;color:#f99157;">comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: &amp;</span><span style="background-color:#2b2c2f;color:#cccece;">[PrintedComment]</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) -&gt;</span><span style="background-color:#2b2c2f;color:#cccece;"> NestedComment </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> children</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#cccece;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">NestedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt; =</span><span style="background-color:#2b2c2f;color:#cccece;"> graph
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">neighbors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">map</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(|</span><span style="background-color:#2b2c2f;color:#f99157;">child_id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">| </span><span style="background-color:#2b2c2f;color:#6699cc;">build_tree</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">graph</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> child_id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">))
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">collect</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//We can just unwrap here since the id value is always populated from a map over contents.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">usize </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#cccece;"> comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">iter</span><span style="background-color:#2b2c2f;color:#5fb3b3;">().</span><span style="background-color:#2b2c2f;color:#6699cc;">position</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(|</span><span style="background-color:#2b2c2f;color:#f99157;">c</span><span style="background-color:#2b2c2f;color:#5fb3b3;">| </span><span style="background-color:#2b2c2f;color:#cccece;">c</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">==</span><span style="background-color:#2b2c2f;color:#cccece;"> id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">).</span><span style="background-color:#2b2c2f;color:#6699cc;">unwrap</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">!</span><span style="background-color:#2b2c2f;color:#cccece;">children</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">is_empty</span><span style="background-color:#2b2c2f;color:#5fb3b3;">() {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">NestedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">new</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&amp;</span><span style="background-color:#2b2c2f;color:#cccece;">comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">],</span><span style="background-color:#2b2c2f;color:#cccece;"> children</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">NestedComment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">new</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&amp;</span><span style="background-color:#2b2c2f;color:#cccece;">comments</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">], </span><span style="background-color:#2b2c2f;color:#fac863;">Vec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">::</span><span style="background-color:#2b2c2f;color:#cccece;">new</span><span style="background-color:#2b2c2f;color:#5fb3b3;">())
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>At this point, our list is completely nested and ready to be pushed to the frontend without fear of your witless, snarky responses being incorrectly assigned to the wrong <em>first!</em> comment.</p>
<p>You can take a look at the complete implementation of <code>NestedComment</code>'s methods <a href="https://github.com/Libbum/oration/blob/f323db9d0bea3fc3d581dd31efc2e09fdedc00ed/src/models/comments/mod.rs#L610-L724">here</a>.
In the coming days I plan to write up some further caveats I uncovered when working with this data in <strong>Elm</strong> on the frontside of <a href="https://github.com/Libbum/oration">oration</a>, so please at least attempt to contain your excitement until then.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;nesting-structures-from-flat-indexes&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/shottower-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Rust</category>
                
                    <category>Algorithms</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Clustering Tangent Spheres
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;clustering-tangent-spheres&#x2F;</link>
                <pubDate>Tue, 16 Jan 2018 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Make yourself a little nest of eggs. Where your eggs are perfectly round and magically float in free space.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>So you want to do some sphere packing to make your inflatable <a href="https://github.com/Libbum/space-habitats">space habitats</a> for deployment on the Moon and Mars snug and cozy.
Perfectly straightforward you think to yourself; since one can start with a triplet of spheres tangent pairwise by placing one at some origin on a 2D plane, extending the second out in the \(x\) direction and completing the triangle by identifying the third sphere's position based on the radii of all three.</p>
<figure>
<img src="/images/triplet_diagram.svg" alt="A sphere triplet" width="700px" />
<figcaption>An initial sphere triplet located on the vertices of a triangle with side lengths constructed from sphere radii: \(a=r_B+r_C, b=r_A+r_C, c=r_A+r_B\)</figcaption>
</figure>
<p><a name="continue-reading"></a>
There's not even time to take a mirco-break to refresh your favourite time sink website before you've busted out the coordinates of \(C\)</p>
<p>$$e = \frac{b^2+c^2-a^2}{2c}, \quad f= \sqrt{b^2-e^2}.$$</p>
<p>On a roll, you extend the coordinates of \(A\), \(B\) and \(C\) into three dimensions setting their \(z\) component to \(0\) and construct a tetrahedron from this base triangle and three new distances \(m = r_A+r_D\), \(n = r_B+r_D\), \(p=r_C+r_D\); finding the tetrahedron's fourth vertex</p>
<p>$$x_D = \frac{m^2+c^2-n^2}{2c}, \quad y_D = \frac{f^2c+m^2c-m^2e+n^2e-p^2c-c^2e+e^2c}{2fc}, \quad z_D = \pm\sqrt{m^2-x_D^2-y_D^2}.$$</p>
<p>Pausing for just a moment, you realise you've been on autopilot for a second—since such trivial calculations are self evident.
Reflecting on a time that feels so long ago now, when you learnt that a minimal set of four tangent spheres in three dimensions can be described by a tetrahedron.
The locus of each sphere's center point is one of the tetrahedron's vertices, and the lengths of each edge of the tetrahedron are defined via the radii of the pair of spheres for which the edge connects their centers.
Using the already-known properties of the base triangle; introducing a fourth sphere \(D\) with known radius \(r_D\) and finding its coordinates, is now just some basic geometry—extending the system of equations used to solve the locus of \(C\)</p>
<p>$$\begin{aligned}
e^2+f^2&amp;=b^2\\
(e-c)^2+f^2&amp;=a^2,\\
\end{aligned}$$</p>
<p>to the intersection represented by
$$\begin{aligned}
x_D^2+y_D^2+z_D^2&amp;=m^2\\
(x_D-c)^2+y_D^2+z_D^2&amp;=n^2\\
(x_D-e)^2+(y_D-f)^2+z_D^2&amp;=p^2.\\
\end{aligned}$$</p>
<p>Back from your daydream—that time sink website is calling.
Since you've pretty much wrapped this problem up, why not take a peek?
After a few sensible chuckles, it dawns on you that there's still work to do.
Your sphere packing algorithm is going to feed you positions and radii of arbitrary sets of pairwise tangent triplets for you to calculate the fourth position.
This means that if you are solving the tetrahedron in this simple basis, translation and rotation of \(D\)'s position must occur.</p>
<p>Moreover, this is going to have to happen in a number of steps.</p>
<ol>
<li>Remove \(\triangle ABC\)'s translation component, aligning \(A\) to the origin.</li>
<li>Recalculate \(c, e, f\) in the simple basis for this triplet to solve for the fourth locus.</li>
<li>Denote the solution as \(H\) in tetrahedron \(EFGH\), which now must be translated to tetrahedron \(ABCD\)'s basis to find \(D\).</li>
<li>Rotate \(\overrightarrow{EF}\) onto \(\overrightarrow{AB}\).</li>
<li>Rotate \(G\) to \(C\) by rotating the face normals of the triangle identified in 4 and \(\triangle ABC\).</li>
<li>Translate this triangle to the \(ABC\) basis by returning the translation component removed in 1.</li>
</ol>
<p>None of this is too difficult in of its own, but without proper forethought—you're gonna have a bad time.
Basically you're going to end up catching edge cases just to the left of center like a tennis ball to the nuts of a daydreaming ball boy at the US Open.</p>
<p>What happens when you're sent a triplet that has coordinates (in the translated basis) \((0,0,0)\), \((e,f,0)\), \((c,0,0)\) or in other words: when \(B=G\) and \(C=F\)?
You must check for this mirror symmetry to make sure that the first rotation doesn't place your \(F\) position closer to Alpha Centauri than it does to it's wanted position at \(B\).</p>
<p>The list goes on, but it suffices to say that you start juggling possibilities like some guy trying to wash a car in an infomercial.</p>
<p>Fret not! There is a better way!</p>
<hr />
<p>Consider that we have a pairwise tangent triplet with known radii and arbitrary positions in \(\mathbb{R}^3\).
Additionally, we know the radius of a fourth sphere we wish to add to the cluster.</p>
<p>To not confuse the skimming reader—I will change notations here, and define a tetrahedron with vertices \(S_1\), \(S_2\) and \(S_3\) residing at distances \(d_1\), \(d_2\), \(d_3\) from a fourth vertex \(S_0\), whose coordinates \((x,y,z)\) must be found.</p>
<p>The distance values here are straightforward, since they are defined as the sum of the radii along a given edge: \(d_i=r_i+r_0\).
Since \(S_0\) is at the intersection of three spheres centered at \(S_1\), \(S_2\), \(S_3\) with radii \(d_1\), \(d_2\), \(d_3\), we know its coordinates satisfy the equations</p>
<p>$$\begin{aligned}
(x-x_1)^2+(y-y_1)^2+(z-z_1)^2&amp;=d_1^2\qquad(1)\\
(x-x_2)^2+(y-y_2)^2+(z-z_2)^2&amp;=d_2^2\qquad(2)\\
(x-x_3)^2+(y-y_3)^2+(z-z_3)^2&amp;=d_3^2\qquad(3)\\
\end{aligned}$$</p>
<p>Subtract (1) from (2) &amp; (3) to obtain the equations for two planes, and couple this set with (1) to yield the quadratic system:</p>
<p>$$\begin{aligned}
2(x_1-x_2)x+2(y_1-y_2)y+2(z_1-z_2)z&amp;=d_2^2-d_1^2+x_1^2-x_2^2+y_1^2-y_2^2+z_1^2-z_2^2\\
2(x_1-x_3)x+2(y_1-y_3)y+2(z_1-z_3)z&amp;=d_3^2-d_1^2+x_1^2-x_3^2+y_1^2-y_3^2+z_1^2-z_3^2\\
x^2+y^2+z^2-2 x_1 x-2 y_1 y-2 z_1 z &amp;= d_1^2-x_1^2-y_1^2-z_1^2.\\
\end{aligned}$$</p>
<p>The closed form solution to this system is not the nicest of expressions, so we can consider the equivalent set below in vector format
$$
\begin{aligned}
\vec u\cdot\vec r=a\\
\vec v\cdot\vec r=b\\
\vec r\cdot\vec r+\vec w\cdot\vec r=c\\
\end{aligned}
$$
where \(\vec r=(x,y,z)\) is our unknown vector.
Following from this, we obtain values of most of the components directly,</p>
<p>$$\begin{aligned}
\vec u&amp;=\frac{S_1-S_2}{\left|S_1-S_2\right|}\\
\vec v&amp;=\frac{S_1-S_3}{\left|S_1-S_3\right|}\\
\vec w&amp;=-2S_1\\
a&amp;=\frac{d_2^2-d_1^2+x_1^2-x_2^2+y_1^2-y_2^2+z_1^2-z_2^2}{2\left|S_1-S_2\right|}\\
b&amp;=\frac{d_3^2-d_1^2+x_1^2-x_3^2+y_1^2-y_3^2+z_1^2-z_3^2}{2\left|S_1-S_3\right|}\\
c&amp;=d_1^2-x_1^2-y_1^2-z_1^2\\
\end{aligned}$$</p>
<p>Notice that \(\vec u\) and \(\vec v\) are unit vectors, so we can form a basis with a third vector:</p>
<p>$$\vec t=\frac{\vec u\times\vec v}{\left|\vec u\times\vec v\right|}.$$</p>
<p>A solution to \(\vec r\) can then be obtained in the form \(\vec r=\alpha\vec u+\beta\vec v+\gamma\vec t\) once \(\alpha\), \(\beta\) and \(\gamma\) are identified.
Plugging this expression for \(\vec r\) into the vector equations for \(a\) and \(b\) above immediately yields</p>
<p>$$\alpha=\frac{a-b(\vec u\cdot\vec v)}{1-(\vec u\cdot\vec v)^2},\quad\beta=\frac{b-a(\vec u\cdot\vec v)}{1-(\vec u\cdot\vec v)^2},$$</p>
<p>while the third equation becomes \(\gamma^2+(\vec w\cdot\vec t)\gamma+d=0\) where \(d=\alpha^2+\beta^2+2\alpha\beta(\vec u\cdot\vec v)+\alpha(\vec u\cdot\vec w)+\beta(\vec v\cdot\vec w)-c\).</p>
<p>This last equation can finally be solved for \(\gamma\):</p>
<p>$$\gamma=\frac{1}{2}\left(-(\vec w\cdot\vec t)\pm\sqrt{(\vec w\cdot\vec t)^2-4d}\right).$$</p>
<p>With these values you can now solve the irregular tetrahedron in 3D directly!
This means no edge cases, no recalculation of previously known values or complex <code>if elseif else</code> blocks based on various input conditions.</p>
<figure>
    
    <img src="/images/spherecluster.png" alt="The fruits of your labour made manifest." />
    
    <figcaption>The fruits of your labour made manifest.</figcaption>
</figure>
<p>
                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;clustering-tangent-spheres&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/bubbles-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Geometry</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Code Coverage in Rust
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;code-coverage-in-rust&#x2F;</link>
                <pubDate>Mon, 19 Jun 2017 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Productivity tools you employ to make yourself more efficient that actually take up most of your productive time.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>One side project that has been sitting by the wayside since completing my PhD has been to polish up and publish <a href="https://github.com/Libbum/Wafer">Wa<em>f</em>er</a>: my fancy 3D wavefunction solver.
For reasons, one of which is mostly <a href="http://www.chronicle.com/article/How-to-ProcrastinateStill/93959">structured procratstination</a>, this polishing ended up being a port/re-write in Rust.
Delving into the Rust ecosystem has been fun and if you check Wa<em>f</em>er's commit history you'll notice large rewrites again and again as I basically play around with things; having no real development schedule or design restrictions.</p>
<p>It may seem a little counter intuitive then, that I'm also trying at the same time to learn all the rigid structures of software development.
Proper documentation, testing, error handling, data structures <em>etc</em>.</p>
<p><a name="continue-reading"></a>
The Rust tooling makes much of this a breeze.
For example, you write comments above your functions in markdown, call <code>cargo doc</code> and a complete document is compiled for you.</p>
<p>Rust is actively evolving though, and hiccups do occur—sometimes more that you'd like.
Staying with the documentation example, if you want to document all your routines as more of a developers document, the command to do so is simply</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">cargo rustdoc --open -- --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
</span></pre>
<p>and obviously rolls off the keyboard just as effortlessly as <code>cargo doc</code>.
<a href="https://github.com/rust-lang/cargo/issues/1520">Fixes</a> are in the works for this oversight, and it's really not too much more than a quirk that's fairly obvious to find a solution for.
Usually that comes in the form of a well written article on some well known and respected Rust blogger's site.</p>
<p>Recently, <a href="https://medium.com/@Razican/continuous-integration-and-code-coverage-report-for-a-rust-project-5dfd4d68fbe5">an excellent write up</a> by Razican on getting Rust to play with <a href="https://travis-ci.org/">Travis</a> enabled me to set up a seamless testing environment, with developer documentation instantly updated on every commit (<a href="https://libbum.github.io/Wafer/wafer/index.html">here</a> if you want to check it out).</p>
<p>Formal, structured testing is somewhat new to me, since spitting debug data to stdout and making sure numbers matched up to some expected output has pretty much been end-of-story in the past.
Travis is a tool that other open source projects have had enabled, so it's existence is known to me, and previously I even managed to <a href="https://github.com/JuliaEditorSupport/atom-language-julia/commit/4f249a64ffdb8133e7453cbc28f2573afd85016a">add some tests</a> that did a good job of failing for a while before getting it right.</p>
<p>The idea of code coverage however is something I'd never heard of before Razican's post.
So, to check it out I chucked in the extra configuration steps to my <code>.travis.yml</code> and set up a <a href="https://codecov.io/">Codecov</a> account.
To my surprise, the five or so extremely minimal tests I'd written gave me an impressive 96% coverage!</p>
<p>Something didn't add up.</p>
<p>Pulling up the <a href="https://codecov.s3.amazonaws.com/v4/raw/2017-06-05/D2380B539060047E6F2FB8FE6AEBA933/c495f03ffbdf8a845a7e0bfcf6e0ab0ef5d4750b/2a592f0c-9546-46d8-8951-5ecd48c3ccb0.txt">raw logs</a>, it was clear that <code>total_lines</code> here</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">{&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">file</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/home/travis/build/Libbum/Wafer/src/grid.rs</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">percent_covered</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">100.00</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">covered_lines</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">35</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">total_lines</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">35</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;}
</span></pre>
<p>needs to be a little larger.
That file was 722 lines long at the time.</p>
<p>Codecov support replied to me extremely quickly, although they couldn't help solve the issue: the raw logs are what they match on, so it's the rust compiler that's not producing them correctly.</p>
<p>Here's the point where I'd expect again to say that there's a bit of a quirk with a fairly well documented solution, but this time none was to be found.
Not that there wasn't a solution, but there just wasn't an easily explained blog post about it.
Alas, the burden has therefore fallen squarely on my lap—the not-known-for-much-of-anything guy who's <strong>Rust</strong> tag count on this blog is 1 (provided you count this post in that category).</p>
<hr />
<p>Basically what's happening is <code>kcov</code> (the tool we use to generate the logs that are sent to Codecov from the <code>cargo test</code> run) is quite language agnostic and just follows pathways of code that has been run vs not-run.</p>
<p>For example, a test like this on a convoluted function</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">fn </span><span style="background-color:#2b2c2f;color:#6699cc;">between_five_ten</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">num</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#cccece;"> u23</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) -&gt; </span><span style="background-color:#2b2c2f;color:#c594c5;">bool </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if</span><span style="background-color:#2b2c2f;color:#cccece;"> num </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt; </span><span style="background-color:#2b2c2f;color:#f99157;">5 </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if</span><span style="background-color:#2b2c2f;color:#cccece;"> num </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt; </span><span style="background-color:#2b2c2f;color:#f99157;">10 </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#f99157;">true
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#f99157;">false
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#f99157;">false
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">#[</span><span style="background-color:#2b2c2f;color:#cccece;">test</span><span style="background-color:#2b2c2f;color:#5fb3b3;">]
</span><span style="background-color:#2b2c2f;color:#c594c5;">fn </span><span style="background-color:#2b2c2f;color:#6699cc;">test_four</span><span style="background-color:#2b2c2f;color:#5fb3b3;">() {
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">assert_eq!</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">between_five_ten</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">4</span><span style="background-color:#2b2c2f;color:#5fb3b3;">), </span><span style="background-color:#2b2c2f;color:#f99157;">false</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>will never enter the <code>if num &lt; 10</code> branch, meaning for 11 lines of code we test 6.
If the above file had an additional 50 functions totalling some 800 lines of code, the result of <code>kcov</code>s tests would sill be 6 lines covered of a total of 11 lines.</p>
<p>The Rust compiler is effectively messing up <code>kcov</code> here rather than a bug existing somewhere in <code>kcov</code> itself.
<code>rustc</code> will compile each function (and each global) into its own section of the output object file, then <code>--gc-sections</code> is passed to the linker which eliminates all unused elements.
The reason for this is to cut down binary sizes, as we pull in tonnes of libraries for ease of use when coding up our projects, but seldom actually use all of the features.
This does, however, have the implication that testable functions are stripped by default in test executables if they are not used (more specifically here: not tested), and now we see why <code>kcov</code> isn't handling information as we'd like.</p>
<p>With this now understood, it was easier to identify if a solution had already been implemented or not by trawling the Rust bug tracker.</p>
<p>Thankfully, <a href="https://github.com/rust-lang/rust/pull/31368">the issue was fixed in February</a> by implementing a <code>link_dead_code</code> flag, which explicitly stops the linker from stripping untested code out of the binary.
Ultimately you get a much larger executable, but the point here is to only compile with this flag if you need code coverage information.</p>
<p>So the now-simple fix is to run <code>cargo test</code> as <code>RUSTFLAGS=-Clink-dead-code cargo test</code>.
Updating my <a href="https://github.com/Libbum/Wafer/blob/master/.travis.yml">.travis.yml</a> and pushing a new commit swapped out my impressive 96% coverage to a much more impressive 9%.
Time to get to writing some actual tests then!</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;code-coverage-in-rust&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/control-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Rust</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    From Disqus to Isso
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;from-disqus-to-isso&#x2F;</link>
                <pubDate>Sun, 16 Apr 2017 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Current comment security is a sad state of affairs.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>Due to my erroneous assumption that an OVZ container is indistinguishable from a full OS on the inside, my VPS upgrade from Debian Wheezy to Jessie didn't go exactly as planned…</p>
<p>Starting from a clean install I went about revamping a number of things, as well as keeping on top of the new security measures that have been added to the <a href="https://observatory.mozilla.org">observatory</a> in the past six months.</p>
<p>I love static sites and have no use for too much dynamic frivolity, which also means I can tighten up security policies so my server is (hopefully) more of a vault with an excellent CCTV system for you all to look inside with.
But comments on this blog have been an issue.
<a href="https://disqus.com">Disqus</a> has been a necessary evil since this blog's inception, but both my own and the worries of the <a href="https://stiobhart.net/2017-02-21-disqusting/">internets</a> are something that needed tending to.</p>
<p><a name="continue-reading"></a>
Just look at this CSP header!</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">add_header Content-Security-Policy &quot;default-src &#39;self&#39;; script-src &#39;self&#39; https://axiomatic.disqus.com https://api.github.com https://d3js.org https://code.jquery.com https://cdnjs.cloudflare.com https://a.disquscdn.com https://ajax.googleapis.com; font-src &#39;self&#39; https://fonts.googleapis.com https://fonts.gstatic.com; style-src &#39;self&#39; &#39;unsafe-inline&#39; https://fonts.googleapis.com https://a.disquscdn.com; img-src &#39;self&#39; data: https://referrer.disqus.com https://a.disquscdn.com https://i.creativecommons.org https://licensebuttons.net; frame-src &#39;self&#39; https://disqus.com&quot;;
</span></pre>
<p>Apart from a few CDN and API links (github, d3js and cloudflare) this is all to satiate Disqus, and even then you could watch the developer console in Chrome and see it still bash up against the policy.
I've never had any of the advertising integration turned on either, so I'd hate to see what happened if I was that kind of asshole.</p>
<p>So I've taken the plunge and moved to <a href="https://posativ.org/isso/">Isso</a>: a self hosted alternative which requires no login (can be anonymous if you wish), no external services, no bullshit.
Well, that last one is only partially true unfortunately.
Take a look at my CSP now:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">add_header Content-Security-Policy &quot;default-src &#39;self&#39;; font-src &#39;self&#39; https://fonts.gstatic.com; script-src &#39;self&#39; &#39;unsafe-eval&#39; https://api.github.com https://d3js.org https://cdnjs.cloudflare.com; style-src &#39;self&#39; https://fonts.googleapis.com &#39;unsafe-inline&#39;&quot;;
</span></pre>
<p>Much better; but notice anything suspect? There's one <code>eval</code> in the code-base which means putting in an <code>unsafe-eval</code> and dropping 15 points from my Observatory score.</p>
<p><a href="https://github.com/posativ/isso/issues/274">#274</a> highlights this and it's not an easy fix.
The commenting system relies on an old version of <a href="https://pugjs.org/api/getting-started.html">pug.js</a> to do the templating (back when it was called jade) and thus needs a major overhaul to fix.
So for the moment I've managed to swap implicit problems with Disqus to an explicit issue with Isso.
Even so, this is an issue that is in my power to fix, when (read: if) I have the time.</p>
<p>The moderation system requires an <code>unsafe-inline</code> in <code>script-src</code> to allow one click acceptance or deletion of a comment via an email notification you receive once someone posts.
This, in addition to the eval issue just wont fly with me; but at this point I had already come too far.
The solution is quite straightforward though: just edit the comment database directly.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">select </span><span style="background-color:#2b2c2f;color:#5fb3b3;">* </span><span style="background-color:#2b2c2f;color:#c594c5;">from</span><span style="background-color:#2b2c2f;color:#cccece;"> comments </span><span style="background-color:#2b2c2f;color:#c594c5;">where</span><span style="background-color:#2b2c2f;color:#cccece;"> mode </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">2</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span><span style="background-color:#2b2c2f;color:#c594c5;">update</span><span style="background-color:#2b2c2f;color:#cccece;"> comments </span><span style="background-color:#2b2c2f;color:#c594c5;">set</span><span style="background-color:#2b2c2f;color:#cccece;"> mode </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">1 </span><span style="background-color:#2b2c2f;color:#c594c5;">where</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">28</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">**</span><span style="background-color:#2b2c2f;color:#c594c5;">OR</span><span style="background-color:#2b2c2f;color:#5fb3b3;">**
</span><span style="background-color:#2b2c2f;color:#c594c5;">delete from</span><span style="background-color:#2b2c2f;color:#cccece;"> comments </span><span style="background-color:#2b2c2f;color:#c594c5;">where</span><span style="background-color:#2b2c2f;color:#cccece;"> id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#f99157;">28</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span></pre>
<p>Here, <code>mode = 2</code> means awaiting approval (<code>1</code> is live), and the <code>id</code> is a comment you wish to approve or deny.
A lazy (savvy) user may also script an ssh connection, sqlite connection, and a somewhat modified query/action to generate one click acceptance and deletion links they could replace in their notification emails.</p>
<hr />
<p>Security gripes aside, Isso is quite nice and built close to my principles concerning the current state of the Web.
Initially I thought <a href="https://secure.gravatar.com/">Gravatar</a> integration would be nice, but now I like the philosophy behind the identicon.
Running an sqlite back-end makes sense.
The moderation gate minimises spam intake and doesn't require a hefty Bayesian parser hogging my cycles.
Markdown in comments. <em>etc</em>.</p>
<p>The code-base is also small enough to hack on, and add quick and dirty additions.
One particular thing I missed from Disqus was the obvious <strong>author</strong> attribute to comments.
For the moment each Isso user looks the same—this is fine for a Marxist utopia, but I'm the one yielding what little power I have over this small portion of the web and I intend to let that be known.</p>
<p>You can see in <a href="https://github.com/posativ/isso/blob/d37b5bb030701a601854e463c1789325084ce10b/isso/js/app/text/comment.jade">comment.jade</a> that if we have the avatar system on, Isso generates an identicon for each comment from the <code>comment.hash</code>.
This is a PBKDF2 hash generated from either the email address or IP of the user.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-#{comment.id}</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">conf</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">avatar
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">avatar</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">svg</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">-</span><span style="background-color:#2b2c2f;color:#cccece;">hash</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">#{comment.hash}</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">text-wrapper</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-comment-header</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; </span><span style="background-color:#2b2c2f;color:#cccece;">role</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">meta</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span></pre>
<p>Since this is a hack job, I just identified mine from a comment I had already created, then modified the above to add an additional class if my hash matched the current one the template is processing:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; </span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-#{comment.id}</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">conf</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">avatar
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">avatar</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">svg</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">-</span><span style="background-color:#2b2c2f;color:#cccece;">hash</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">#{comment.hash}</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=(</span><span style="background-color:#2b2c2f;color:#cccece;">comment</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">hash </span><span style="background-color:#2b2c2f;color:#5fb3b3;">== &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">213ac8a3c887</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;) ? &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">text-wrapper author-highlight</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; : &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">text-wrapper</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">div</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">isso-comment-header</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; </span><span style="background-color:#2b2c2f;color:#cccece;">role</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">meta</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)
</span></pre>
<p>and wrote an appropriate style</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#bb80b3;">author-highlight </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">￼    </span><span style="background-color:#2b2c2f;color:#fac863;">background-color</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#6699cc;">rgba</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">200</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">200</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">200</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">0.4</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">￼    </span><span style="background-color:#2b2c2f;color:#fac863;">border-top-right-radius</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#f99157;">25px</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">￼    </span><span style="background-color:#2b2c2f;color:#fac863;">border-bottom-right-radius</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#f99157;">25px</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>At some stage soon I'll put together a pull request to add something similar to Isso directly, but that will probably require an addition to the configuration file. Allowing the author to identify themselves without the above hassle.
To see this in action, perhaps take a look at <a href="/converting-4k-content-for-samsung-uhd-televisions">one of the only actual comment sections on this website</a>.
And yes: the fact that I've just ranted about commenting systems without having much use of a comment system at all does not escape me.
Perhaps my readers don't care for Disqus more-so than I?</p>
<hr />
<p><strong>Update April 21, 2017</strong></p>
<p>I actually managed to build this <a href="https://github.com/posativ/isso/pull/321">pull request</a> much quicker than I anticipated.
This is a fully functional blog author highlighting system—a little different than the one I've written about above, but much less of a hack job.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;from-disqus-to-isso&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/timepc-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>JavaScript</category>
                
                    <category>Security</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Including Small Countries in Your world.json
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;including-small-countries-in-your-world-json&#x2F;</link>
                <pubDate>Mon, 18 Apr 2016 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    The little guy is often the most important.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>In the process of building <a href="https://odyssey.neophilus.net">Odyssey</a>, I came across an omission in most of the world structures on <a href="http://bl.ocks.org/">Bl.ocks</a>. Pretty much everyone nowadays grabs the <a href="http://www.naturalearthdata.com/">Natural Earth</a> <code>ne_110m_admin_0_countries</code> dataset, converts it to <a href="https://github.com/mbostock/topojson">TopoJSON</a>, throws the result to a projection such as</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">   </span><span style="background-color:#2b2c2f;color:#cccece;">d3</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">geo</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">orthographic</span><span style="background-color:#2b2c2f;color:#5fb3b3;">().</span><span style="background-color:#2b2c2f;color:#6699cc;">translate</span><span style="background-color:#2b2c2f;color:#5fb3b3;">([</span><span style="background-color:#2b2c2f;color:#cccece;">width </span><span style="background-color:#2b2c2f;color:#5fb3b3;">/ </span><span style="background-color:#2b2c2f;color:#f99157;">2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#cccece;">height </span><span style="background-color:#2b2c2f;color:#5fb3b3;">/ </span><span style="background-color:#2b2c2f;color:#f99157;">2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">]).</span><span style="background-color:#2b2c2f;color:#6699cc;">scale</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">width </span><span style="background-color:#2b2c2f;color:#5fb3b3;">/ </span><span style="background-color:#2b2c2f;color:#f99157;">2 </span><span style="background-color:#2b2c2f;color:#5fb3b3;">- </span><span style="background-color:#2b2c2f;color:#f99157;">20</span><span style="background-color:#2b2c2f;color:#5fb3b3;">).</span><span style="background-color:#2b2c2f;color:#6699cc;">clipAngle</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">90</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span></pre>
<p>and then move on with their lives.</p>
<p>But what if you care about information on this projection? What if Mike Bostock's <a href="http://bl.ocks.org/mbostock/4183330">World Tour</a> gave you this grandiose idea of an interactive globe for your website that needs to pinpoint tiny countries like Singapore?</p>
<p><a name="continue-reading"></a>
Singapore and other small countries like it are not included in the main 1:110m scale data as they are not large enough to be polytopes. Instead, they are relegated to <code>ne_110m_admin_0_tiny_countries</code> as point information and usually omitted from D3 1:110m globe implementations.</p>
<p>Including this data set adds a small amount of complexity to the build and a bit of finessing of the finished product, but nothing over the top. I'll assume you have TopoJSON setup already and know how to use it. If not, checkout <a href="https://bost.ocks.org/mike/map/">Let's Make A Map</a> for a good overview. For the lazy ones you can grab the end result of the following steps from <a href="world.json">here</a>.</p>
<p>Get the latest data from Natural Earth. This can be whatever you want to combine; I'll be using just <a href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_countries.zip">countries</a>
and <a href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_tiny_countries.zip">tiny country points</a>, but it'd also be possible to use the sovereignty data in place of countries (for example) if you want to drill down a little deeper. Using the 1:50m or 1:10m sets is also fine, however I find that this is too precise (read: too much info) to animate smoothly on your grandma's computer or mobile devices.</p>
<p>Extract both sets into a new directory and convert the shape data to GeoJSON:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">ogr2ogr -f GeoJSON countries.json ne_110m_admin_0_countries.shp
</span><span style="background-color:#2b2c2f;color:#cccece;">ogr2ogr -f GeoJSON tinycountries.json ne_110m_admin_0_tiny_countries.shp
</span></pre>
<p>We now need to manually merge these files. AFAIK, <code>ogr2ogr</code> isn't happy merging poly and non-poly geometry, and the <code>TopoJSON</code> command line tool doesn't merge stuff at all. It's possible to merge this data on the client side each load, but this seems pretty inefficient. One could write a simple shell script for this, but as we're only doing it once I see no need for automation. The GeoJSON format we have output with our two files above follows a simple syntax:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">   </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{ &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">FeatureCollection</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">features</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;: [ </span><span style="background-color:#2b2c2f;color:#cccece;">... </span><span style="background-color:#2b2c2f;color:#5fb3b3;">] }
</span></pre>
<p>with a plethora of <code>Feature</code> elements filling the array. To merge the data one must simply add a comma (<code>,</code>) to the last entry of the <code>countries.json</code> <code>features</code> array, then append the contents of the same array from <code>tinycountries.json</code>. For this example we'll save that file as <code>world.geo.json</code>.</p>
<p>Now, our newly created file can be converted to TopoJSON via</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">topojson -o world.json --id-property su_a3 --properties name -- countries=world.geo.json
</span></pre>
<p>and loaded using a somewhat normal D3 map routine. The important part is the <code>d3.json</code> function. Here we don't use a mesh load but rather a path append:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">d3</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">json</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/assets/world.json</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, </span><span style="background-color:#2b2c2f;color:#c594c5;">function</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">error</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">world</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">error</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) </span><span style="background-color:#2b2c2f;color:#c594c5;">throw </span><span style="background-color:#2b2c2f;color:#cccece;">error</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#6699cc;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">   </span><span style="background-color:#2b2c2f;color:#c594c5;">var </span><span style="background-color:#2b2c2f;color:#cccece;">land </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">topojson</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">feature</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">world</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#cccece;">world</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">objects</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">countries</span><span style="background-color:#2b2c2f;color:#5fb3b3;">).</span><span style="background-color:#2b2c2f;color:#6699cc;">features</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#6699cc;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">   </span><span style="background-color:#2b2c2f;color:#cccece;">svg</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">insert</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">g</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">.graticule</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;).</span><span style="background-color:#2b2c2f;color:#6699cc;">attr</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">countries</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;);
</span><span style="background-color:#2b2c2f;color:#6699cc;">   </span><span style="background-color:#2b2c2f;color:#cccece;">d3</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">selectAll</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">#countries</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;).</span><span style="background-color:#2b2c2f;color:#6699cc;">selectAll</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">path</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;).</span><span style="background-color:#2b2c2f;color:#6699cc;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">land</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#6699cc;">      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">enter</span><span style="background-color:#2b2c2f;color:#5fb3b3;">().</span><span style="background-color:#2b2c2f;color:#6699cc;">append</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">path</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;).</span><span style="background-color:#2b2c2f;color:#6699cc;">attr</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">class</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">land</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;)
</span><span style="background-color:#2b2c2f;color:#6699cc;">      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">attr</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, </span><span style="background-color:#2b2c2f;color:#c594c5;">function</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">d</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">i</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) { </span><span style="background-color:#2b2c2f;color:#c594c5;">return </span><span style="background-color:#2b2c2f;color:#cccece;">d</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">; }).</span><span style="background-color:#2b2c2f;color:#6699cc;">attr</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">d</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, </span><span style="background-color:#2b2c2f;color:#6699cc;">path</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#6699cc;"> </span><span style="background-color:#2b2c2f;color:#5fb3b3;">});
</span></pre>
<p>This, along with a little boiler plate (which you can view <a href="https://bl.ocks.org/Libbum/e8cda20eea9d401f642357c4f46281e4">here</a>), gives us the following globe:</p>
<div id="map"></div>
So what's going on with all of those dots everywhere? Well; they're our small countries, which are not represented by paths but rather just points. On this map they stick out like a sore thumb and it's for this reason they are separated out in the first place. We don't really want to see them either: just be able to reference them and zoom to their location.
<p>To do this one can modify the <code>.data(land)</code> item to include a filter</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">land</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">filter</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">function</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">d</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) { </span><span style="background-color:#2b2c2f;color:#c594c5;">return </span><span style="background-color:#2b2c2f;color:#cccece;">d</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">geometry</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">type </span><span style="background-color:#2b2c2f;color:#5fb3b3;">!== &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">Point</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;; }))
</span></pre>
<p>which will give us back our normal looking globe. However, we now have a complete list of individual countries which we can reference via their <code>su_a3</code> id or name and in-turn, center the viewport on a country even if it isn't visible on this scale. The map below is filtering out ONLY tiny countries and giving you a world tour. Full codebase for this globe is <a href="http://bl.ocks.org/Libbum/ec6a8df2049c6084106512e962788aa5">here</a>.</p>
<div id="countryName"></div>
<div id="map2"></div>
<p>For a better demo of what can be done with this, checkout my photoblog <a href="https://odyssey.neophilus.net">Odyssey</a>.</p>
<p><link rel="stylesheet" href="world.css" /></p>
<script src="https://d3js.org/d3.v3.min.js" integrity="sha384-N8EP0Yml0jN7e0DcXlZ6rt+iqKU9Ck6f1ZQ+j2puxatnBq4k9E8Q6vqBcY34LNbn" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js" integrity="sha384-BUz7BfOv7l6jnNmNtX+Wwvp/+c/jxxOJORIxDbG03T0ZuFtcdvM3b95R3t7fygMU" crossorigin="anonymous"></script>
<script src="scwrldtour.js"></script>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;including-small-countries-in-your-world-json&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/world-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>JavaScript</category>
                
                    <category>D3.js</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Using KaTeX with Hakyll
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;using-katex-with-hakyll&#x2F;</link>
                <pubDate>Thu, 06 Aug 2015 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Lightning fast math rendering on the off-chance I ever get around to posting some maths.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>When <a href="https://www.khanacademy.org/">Khan Academy</a> initially released <a href="http://khan.github.io/KaTeX/">KaTeX</a> 0.1.0 last year I was overjoyed.
The performance comparison against <a href="https://www.mathjax.org/">MathJax</a> was impressive and realistically the only reason <strong>MathJax</strong> has ever needed competition.
For those interested in seeing the difference first hand, <a href="http://www.intmath.com/cg5/katex-mathjax-comparison.php">IntMath</a> has a decent test suite.</p>
<p><a name="continue-reading"></a>
After looking under the hood though I could see my work was going to be cut out for me if I wanted to incorporate it into this blog.
Unlike <strong>MathJax</strong>, which scanned the <code>document.body</code> and rendered math elements (indicated via <code>\[ ... \]</code> tags) on the fly, <strong>KaTeX</strong> required the following syntax:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">katex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">render</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">c = </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\\</span><span style="background-color:#2b2c2f;color:#99c794;">pm</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\\</span><span style="background-color:#2b2c2f;color:#99c794;">sqrt{a^2 + b^2}</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, </span><span style="background-color:#2b2c2f;color:#cccece;">element</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span></pre>
<p>Not really a problem in general, although it was obvious for my case I'd have to write some form of math parser for the markdown portion of <a href="http://jaspervdj.be/hakyll/">Hakyll</a>.
Still being quite the <strong>Haskell</strong> neophyte, this became something for the too hard basket.
Maybe I also rationalised the decision not to work on a solution due to the very restricted subset of <strong>LaTeX</strong> features implemented at the time.
I mean, not that I ever do much with relational algebra, but the natural join operator (aka the bowtie: \(\bowtie\)) wasn't introducted until v0.2.0.
How am I supposed to make a fancy outfit for my mathematical symbol cat illustrations without a bowtie?</p>
<p>Fast forward a year and <strong>KaTeX</strong> has matured immensely, and is currently at v0.5.0.
The feature list is much more expansive, and the only gripes I really have are the missing environments like <code>\align</code> and the font modifers <code>\mathrm</code>, <code>\mathbf</code>, <code>\mathcal</code> <em>etc.</em>
However, it looks like these will all be part of the next release according to the status of <a href="https://github.com/Khan/KaTeX/pull/132">this pull request</a>.</p>
<p>My personal saviour was introduced in v0.3.0 by the way of the <a href="https://github.com/Khan/KaTeX/blob/master/contrib/auto-render/README.md">auto-render extension</a> which acts in a similar fashion to the <strong>MathJax</strong> implementation and scans for <code>$$ ... $$</code>, <code>\[ ... \]</code> and <code>\( ... \)</code> tags.
The first two tags indicate the display size environment whereas the last tag is for inline maths.</p>
<p>Luckily, you can configure <strong>Pandoc</strong> such that <strong>Hakyll</strong> parses the single <code>$ ... $</code> tag in markdown and renders it as <code>\( ... \)</code> for use with <strong>MathJax</strong>.
Travis Athougies has a good writeup on how to do this on his blog <a href="http://travis.athougies.net/posts/2013-08-13-using-math-on-your-hakyll-blog.html">here</a>, although I overload my pandoc options a little different so that <strong>Pygments</strong> can be used to do the syntax highlighting on my blog (see my <a href="https://github.com/Libbum/AxiomaticSemantics/blob/master/Includes/Pandoc.hs">Pandoc.hs</a>):</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">readerOpts </span><span style="background-color:#2b2c2f;color:#c594c5;">:: ReaderOptions
</span><span style="background-color:#2b2c2f;color:#cccece;">readerOpts </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> extensions </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">S</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">fromList [ Ext_tex_math_dollars
</span><span style="background-color:#2b2c2f;color:#cccece;">                              </span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#cccece;">Ext_inline_code_attributes
</span><span style="background-color:#2b2c2f;color:#cccece;">                              </span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#cccece;">Ext_abbreviations
</span><span style="background-color:#2b2c2f;color:#cccece;">                              </span><span style="background-color:#2b2c2f;color:#cccece;">]
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">in</span><span style="background-color:#2b2c2f;color:#cccece;"> def { readerSmart </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">True
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> readerExtensions </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">S</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">union extensions (writerExtensions def)
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#cccece;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">writerOpts </span><span style="background-color:#2b2c2f;color:#c594c5;">:: WriterOptions
</span><span style="background-color:#2b2c2f;color:#cccece;">writerOpts </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">def { writerHTMLMathMethod </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">MathJax </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                                  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> writerHighlight </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">False
</span><span style="background-color:#2b2c2f;color:#cccece;">                                  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;"> writerHtml5 </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">True
</span><span style="background-color:#2b2c2f;color:#cccece;">                                  </span><span style="background-color:#2b2c2f;color:#cccece;">}
</span></pre>
<p>So to get <strong>KaTex</strong> working from this starting point, we just need to build a maths context</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#c594c5;">import qualified </span><span style="background-color:#2b2c2f;color:#cccece;">Data.Map </span><span style="background-color:#2b2c2f;color:#c594c5;">as </span><span style="background-color:#2b2c2f;color:#cccece;">M
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">mathCtx </span><span style="background-color:#2b2c2f;color:#c594c5;">:: Context </span><span style="background-color:#2b2c2f;color:#cccece;">a
</span><span style="background-color:#2b2c2f;color:#cccece;">mathCtx </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">field </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">katex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; $ \</span><span style="background-color:#2b2c2f;color:#cccece;">item </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt; </span><span style="background-color:#2b2c2f;color:#c594c5;">do
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">metadata </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;-</span><span style="background-color:#2b2c2f;color:#cccece;"> getMetadata </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;"> itemIdentifier item
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">return </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$ </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">katex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> `M</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">member` metadata
</span><span style="background-color:#2b2c2f;color:#cccece;">                            </span><span style="background-color:#2b2c2f;color:#c594c5;">then </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;link rel=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">stylesheet</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;"> href=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/css/katex.min.css</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\n</span><span style="background-color:#2b2c2f;color:#99c794;">\
</span><span style="background-color:#2b2c2f;color:#cccece;">                                      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">script </span><span style="background-color:#2b2c2f;color:#c594c5;">type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">text/javascript</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;"> src=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/js/katex.min.js</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;&lt;/script&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\n</span><span style="background-color:#2b2c2f;color:#99c794;">\
</span><span style="background-color:#2b2c2f;color:#cccece;">                                      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">script src</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/js/auto-render.min.js</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;&lt;/script&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                            </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;&quot;
</span></pre>
<p>and apply it to any template where the context is needed. For me, that's:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">loadAndApplyTemplate </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">templates/default.html</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> (mathCtx </span><span style="background-color:#2b2c2f;color:#5fb3b3;">`mappend`</span><span style="background-color:#2b2c2f;color:#cccece;"> postCtx) full
</span><span style="background-color:#2b2c2f;color:#5f6364;">--- ... ---
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;&gt;=</span><span style="background-color:#2b2c2f;color:#cccece;"> loadAndApplyTemplate </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">templates/default.html</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> (mathCtx </span><span style="background-color:#2b2c2f;color:#5fb3b3;">`mappend`</span><span style="background-color:#2b2c2f;color:#cccece;"> indexCtx)
</span></pre>
<p>which you can checkout properly in my <a href="https://github.com/Libbum/AxiomaticSemantics/blob/master/site.hs">site.hs</a>.
The reason I do it this way rather than just calling the stylesheet and .js files in <code>default.html</code> is to keep the site as lean as possible.
Sure, I have some fancy things going on in the header <em>etc.</em> but I'm not pulling in <code>jQuery</code> or some other large library for no good reason, and there's no good reason to load <strong>KaTeX</strong> on every page when only a few places will ever need it.</p>
<p>So I have a <code>katex</code> field which, if activated in the preamble of a post (for instance, see the markdown of this entry <a href="https://raw.githubusercontent.com/Libbum/AxiomaticSemantics/master/posts/2015-08-06-using-katex-with-hakyll.markdown">here</a>), pumps in the return result of the <code>katex</code> field above into <code>default.html</code> (full source <a href="https://github.com/Libbum/AxiomaticSemantics/blob/master/templates/default.html">here</a>) and calls the auto-renderer.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">$if(katex)$ $katex$ $endif$
</span><span style="background-color:#2b2c2f;color:#5f6364;">&lt;!-- ... --&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">$if(katex)$
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#eb606b;">script</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">  </span><span style="background-color:#2b2c2f;color:#6699cc;">renderMathInElement</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#fac863;">document</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#6699cc;">body</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;/</span><span style="background-color:#2b2c2f;color:#eb606b;">script</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">$endif$
</span></pre>
<p>With all that in place, embedding maths into posts is essentially trivial, cross platform and most importantly seemless.
As an example, heres a short discussion about some of my recent work using just the <code>$ ... $</code> inline and <code>$$ ... $$</code> display tags in markdown.</p>
<hr />
<p>Wick rotations are primarily used to find solutions to Minkowski space problems by an Euclidean space mapping.
We can also use the rotation to evolve a time-dependent Schrödinger equation and solve for time-independent solutions in three dimensions.
To do so we transfer our TDSE into an imaginary time basis $t=i\tau$:</p>
<p>$$i \hbar \frac{\partial}{\partial t}\Psi(\vec{r},t) = H\Psi(\vec{r},t) \Rightarrow - \hbar \frac{\partial}{\partial \tau}\Psi(\vec{r},\tau) = H\Psi(\vec{r},\tau)$$</p>
<p>which yields a general solution to the wavefunctions</p>
<p>$$\Psi(\vec{r},\tau) = \sum_{k=0}^\infty a_k\psi_k(\vec{r})e^{-E_k \tau}.$$</p>
<p>Using the Gram-Schmidt orthoganilsation procedure, higher order orthogonal eigenfunctions can be found by projecting a guess along the lower states.
For example</p>
<p>$$\lvert\tilde{\psi^\prime_1}\rangle = \lvert\psi^\prime_1\rangle-\lvert\psi_0\rangle\langle\psi_0\vert\psi^\prime_1\rangle,$$</p>
<p>which can even identify eigenfunctions within a degenerate subspace, as each state is <em>chosen</em> to be orthogonal to the systems' basis.</p>
<p><strong>UPDATE:</strong></p>
<p>As of <code>Hakyll 4.8.0.0</code>, a complete metadata overhaul has occured to support YAML. This has broken the <code>mathCtx</code> function above and should be replaced by</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#6699cc;">mathCtx </span><span style="background-color:#2b2c2f;color:#c594c5;">:: Context </span><span style="background-color:#2b2c2f;color:#cccece;">a
</span><span style="background-color:#2b2c2f;color:#cccece;">mathCtx </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#cccece;">field </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">katex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; $ \</span><span style="background-color:#2b2c2f;color:#cccece;">item </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt; </span><span style="background-color:#2b2c2f;color:#c594c5;">do
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">katex </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;-</span><span style="background-color:#2b2c2f;color:#cccece;"> getMetadataField (itemIdentifier item) </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">katex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">return </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$ </span><span style="background-color:#2b2c2f;color:#c594c5;">case</span><span style="background-color:#2b2c2f;color:#cccece;"> katex </span><span style="background-color:#2b2c2f;color:#c594c5;">of
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Just </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">false</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; -&gt; &quot;&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">Just </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">off</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; -&gt; &quot;&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#cccece;">_ </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-&gt; &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;link rel=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">stylesheet</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;"> href=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/css/katex.min.css</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\n</span><span style="background-color:#2b2c2f;color:#99c794;">\
</span><span style="background-color:#2b2c2f;color:#cccece;">                             </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">script </span><span style="background-color:#2b2c2f;color:#c594c5;">type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">text/javascript</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;"> src=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/js/katex.min.js</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;&lt;/script&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\n</span><span style="background-color:#2b2c2f;color:#99c794;">\
</span><span style="background-color:#2b2c2f;color:#cccece;">                             </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">script src</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">/js/auto-render.min.js</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&gt;&lt;/script&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;
</span></pre>
<p>Additionally, much of the gripes concerning <strong>KaTeX</strong>'s math coverage are null and void as the project has matured immensely since the time I initially wrote this post.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;using-katex-with-hakyll&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/blackboard-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>LaTeX</category>
                
                    <category>Haskell</category>
                
                    <category>JavaScript</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Generating a Publication List From Mulitple ORCiDs
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;generating-a-publication-list-from-mulitple-orcids&#x2F;</link>
                <pubDate>Sat, 23 May 2015 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    AKA getting your professors to manage their own bloody lists so you don&#x27;t have to.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>A website for my research group outside of the bounds of our abysmal university web restrictions has been discussed for quite some time. It's genesis has only really started recently though, because I've had too many other things on my plate and no-one else has any decent web capability. Whilst I'd much prefer to use a simple static site tool or code something completely from scratch, the other members of my team really need something a bit more point and click. Plus, I'll be leaving the group soon so it's in their best interest to have a well rounded CMS interface with which they can administer the site.</p>
<p><a name="continue-reading"></a></p>
<hr />
<p><strong>Update 2018-04-25:</strong> OrcID have removed the v1.2 API from their servers, meaning the code in this blog post no longer functions.
The current version v2.1 is quite annoying for our purposes, as it only returns a summary of works, not all info when we request details on a user.
We can then collect an identifier for each work and request the full content, but can only do this in batches of 50, thus the implementation of a script like the one below is no longer quite straightforward.
With that being said, the Joomla module I wrote for v1.2 has been updated to function with v2.1 and has a number of other improvements which are interesting in their own right.
You can take a look at the module on my github <a href="https://github.com/Libbum/joomla-papers">here</a>; the code discussed in this blog is mostly held within <a href="https://github.com/Libbum/joomla-papers/blob/master/mod_papers/helper.php"><code>mod_papers/helper.php</code></a>.</p>
<hr />
<p>Looking around for the latest and greatest in CMS tools (I haven't worked with one since the very early versions of <strong>e107</strong> 15 years ago) we came across <strong>Joomla</strong>, which incidentally was pre-installed on the shared hosting we'd just purchased for the site, and started porting across content. Now that I'm familiar with the system I can undoubtedly state that building something from scratch and teaching everyone in the group how to code would have been a better choice.</p>
<p>But I'm getting off topic…</p>
<p>Managing publication lists has apparently become yet another piece of administrative overhead for researchers. One needs a ResearcherID, Scopus Author ID, ORCiD, and a google scholar profile; not to mention your institutions' profile of you and—if you give two shits about the corporate world, a LinkedIn.</p>
<p>A publication list is one of the primary items expected on a research groups website, and we really didn't want to add yet another list to the pile. So, against my better judgment, I delved back into the underworld of <strong>PHP</strong> and hacked together a little <strong>Joomla</strong> module that pulls the publications of multiple individuals via the <a href="http://orcid.org/organizations/integrators/API">ORCiD public API</a>. That information is then cleared of duplicates, sorted by year and displayed as a list. See it in action over at <a href="http://tcqp.science/our-science/publication-list">TCQP.Science</a>.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;?php
</span><span style="background-color:#2b2c2f;color:#5f6364;">//Align most sanitised to least, will prefer data from earlier in the array.
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">orcids </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">0000-0002-xxxx-xxxx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">0000-0002-yyyy-yyyy</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">0000-0002-zzzz-zzzz</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;);
</span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">orcids </span><span style="background-color:#2b2c2f;color:#5fb3b3;">as $</span><span style="background-color:#2b2c2f;color:#cccece;">id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">// create a new cURL resource
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">ch  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">curl_init</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">// set URL and other appropriate options
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">options </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#f99157;">CURLOPT_URL </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">http://pub.orcid.org/v1.2/</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">/orcid-works</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#f99157;">CURLOPT_HEADER </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; </span><span style="background-color:#2b2c2f;color:#f99157;">false</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#f99157;">CURLOPT_RETURNTRANSFER </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; </span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#cccece;">,
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#f99157;">CURLOPT_HTTPHEADER </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; </span><span style="background-color:#2b2c2f;color:#6699cc;">array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">Accept: application/orcid+json</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">curl_setopt_array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">ch</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">options</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">// grab URL and pass it to the browser
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">raw </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">curl_exec</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">ch</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">// close cURL resource, and free up system resources
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">curl_close</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">ch</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Decode json data
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">data  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">json_decode</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">raw</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#f99157;">true</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Grab usefull stuff and merge
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">works </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">orcid-profile</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">orcid-activities</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">orcid-works</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">orcid-work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(!</span><span style="background-color:#2b2c2f;color:#6699cc;">empty</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">works</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">id </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">reset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">orcids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">works</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array_merge</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">works</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">//Get all dois
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">dois </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">();
</span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks </span><span style="background-color:#2b2c2f;color:#5fb3b3;">as $</span><span style="background-color:#2b2c2f;color:#cccece;">key </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(!</span><span style="background-color:#2b2c2f;color:#6699cc;">is_null</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifiers</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifiers</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] as $</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">strcmp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier-type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;], &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">DOI</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;) == </span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">dois</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[] = $</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier-id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">key</span><span style="background-color:#2b2c2f;color:#5fb3b3;">] = </span><span style="background-color:#2b2c2f;color:#6699cc;">array_merge</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">key</span><span style="background-color:#2b2c2f;color:#5fb3b3;">], </span><span style="background-color:#2b2c2f;color:#6699cc;">array</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">parse</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;=&gt;</span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#6699cc;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">udoi</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;=&gt;&#39;&#39;)); </span><span style="background-color:#2b2c2f;color:#5f6364;">//Build a parse check field. Parse by default, set to zero if there&#39;s an issue.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#6699cc;">unset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">key</span><span style="background-color:#2b2c2f;color:#5fb3b3;">]); </span><span style="background-color:#2b2c2f;color:#5f6364;">//For now, kill anything without a DOI.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">//Find all unique dois
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">udois </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array_unique</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">dois</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">//sanitise merged array.
</span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks </span><span style="background-color:#2b2c2f;color:#5fb3b3;">as $</span><span style="background-color:#2b2c2f;color:#cccece;">mkey </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=&gt; $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Identify Duplicates
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifiers</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] as $</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">strcmp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier-type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;], &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">DOI</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;) == </span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">doi </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">ids</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-external-identifier-id</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">mkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">udoi</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] = $</span><span style="background-color:#2b2c2f;color:#cccece;">doi</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">key </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">array_search</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">doi</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">udois</span><span style="background-color:#2b2c2f;color:#5fb3b3;">); </span><span style="background-color:#2b2c2f;color:#5f6364;">// Find where DOI is in the unique list
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">unset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">udois</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">key</span><span style="background-color:#2b2c2f;color:#5fb3b3;">]); </span><span style="background-color:#2b2c2f;color:#5f6364;">//Found one, don&#39;t need another.
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">key </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#f99157;">false</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[$</span><span style="background-color:#2b2c2f;color:#cccece;">mkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">parse</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] = </span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">; </span><span style="background-color:#2b2c2f;color:#5f6364;">//Don&#39;t parse this entry
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">//Sort array by year
</span><span style="background-color:#2b2c2f;color:#6699cc;">usort</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">function</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#f99157;">a</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#f99157;">b</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#6699cc;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">return </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">a</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">publication-date</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] &gt; $</span><span style="background-color:#2b2c2f;color:#cccece;">b</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">publication-date</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])</span><span style="background-color:#2b2c2f;color:#6699cc;"> ? </span><span style="background-color:#2b2c2f;color:#5fb3b3;">-</span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#6699cc;"> : </span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">});
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">curr_year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">date</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">Y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;);
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;h2&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; . $</span><span style="background-color:#2b2c2f;color:#cccece;">curr_year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;/h2&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;;
</span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">mergedworks </span><span style="background-color:#2b2c2f;color:#5fb3b3;">as $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Identify Results earlier than 2011
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">publication-date</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt; &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">2011</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">parse</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] = </span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">; </span><span style="background-color:#2b2c2f;color:#5f6364;">//Don&#39;t parse this entry
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt; $</span><span style="background-color:#2b2c2f;color:#cccece;">curr_year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5f6364;">//As our list is sorted, we&#39;ve moved to the previous year now. Separate the results.
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">curr_year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;br&gt;&lt;h2&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot; . $</span><span style="background-color:#2b2c2f;color:#cccece;">curr_year </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &quot;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;/h2&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">//Print results
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">parse</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] === </span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;b&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-title</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">title</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;/b&gt;&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">strcmp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-citation</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-citation-type</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;], &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">BIBTEX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;) == </span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">bibtex </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-citation</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">citation</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">volume </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= &#39;&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">pages  </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= &#39;&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">preg_match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;/volume\\s?=\\s?{(\\d+)}/&#39;, $</span><span style="background-color:#2b2c2f;color:#cccece;">bibtex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">volume </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[</span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">];
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">preg_match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;/pages\\s?=\\s?{([0-9-]+)}/&#39;, $</span><span style="background-color:#2b2c2f;color:#cccece;">bibtex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">pages </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[</span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">];
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(!</span><span style="background-color:#2b2c2f;color:#6699cc;">is_null</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])) {
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">contributor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] as $</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(($</span><span style="background-color:#2b2c2f;color:#cccece;">authors </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">reset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">contributor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])) &amp;&amp; ($</span><span style="background-color:#2b2c2f;color:#cccece;">authors </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">contributor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;]))) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= $</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">credit-name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">reset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">contributor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= $</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">credit-name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">work-contributors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">contributor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;])) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39; </span><span style="background-color:#2b2c2f;color:#99c794;">and </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">credit-name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">credit-name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;];
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5f6364;">//Get authorlist from bibtex
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#6699cc;">preg_match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;/author\\s?=\\s?{(.+)}/&#39;, $</span><span style="background-color:#2b2c2f;color:#cccece;">bibtex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">authorstr </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= $</span><span style="background-color:#2b2c2f;color:#cccece;">match</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[</span><span style="background-color:#2b2c2f;color:#f99157;">1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">];
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">authors   </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#6699cc;">explode</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&quot; </span><span style="background-color:#2b2c2f;color:#99c794;">and </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;, $</span><span style="background-color:#2b2c2f;color:#cccece;">authorstr</span><span style="background-color:#2b2c2f;color:#5fb3b3;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#c594c5;">foreach </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors </span><span style="background-color:#2b2c2f;color:#5fb3b3;">as $</span><span style="background-color:#2b2c2f;color:#cccece;">author</span><span style="background-color:#2b2c2f;color:#5fb3b3;">) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(($</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">reset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) &amp;&amp; ($</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">))) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= $</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">reset</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= $</span><span style="background-color:#2b2c2f;color:#cccece;">author</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=== </span><span style="background-color:#2b2c2f;color:#6699cc;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">($</span><span style="background-color:#2b2c2f;color:#cccece;">authors</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)) {
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39; </span><span style="background-color:#2b2c2f;color:#99c794;">and </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">author </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{
</span><span style="background-color:#2b2c2f;color:#cccece;">                        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">author</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">                    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">                </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output </span><span style="background-color:#2b2c2f;color:#5fb3b3;">.= &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;a href=&quot;http://dx.doi.org/</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">udoi</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">journal-title</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39; </span><span style="background-color:#2b2c2f;color:#99c794;">&lt;b&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">volume </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">&lt;/b&gt; </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">pages </span><span style="background-color:#2b2c2f;color:#5fb3b3;">. &#39; </span><span style="background-color:#2b2c2f;color:#99c794;">(</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39; . $</span><span style="background-color:#2b2c2f;color:#cccece;">work</span><span style="background-color:#2b2c2f;color:#5fb3b3;">[&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">publication-date</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">year</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;][&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">value</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;] . &#39;</span><span style="background-color:#2b2c2f;color:#99c794;">)&lt;/a&gt;&lt;br&gt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#6699cc;">echo </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$</span><span style="background-color:#2b2c2f;color:#cccece;">output</span><span style="background-color:#2b2c2f;color:#5fb3b3;">;
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">?&gt;
</span></pre>
<p>If you want to use this yourself, feel free to copypasta, or get in contact and I'll send you a complete module for <strong>Joomla</strong>. A few things you should be aware of: put the person with the cleanest list first in the array—the script doesn't merge fields it just takes the first it finds when checking against the unique key. Secondly, we don't expect a drastic amount of traffic and would like the list to be as up to date as possible, so we pull this info on each page load. If you're expecting modest traffic, perhaps look into something a little more sophisticated for the API call.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;generating-a-publication-list-from-mulitple-orcids&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/books-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>php</category>
                
                    <category>tcqp</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Makefiles Revisited
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;makefiles-revisited&#x2F;</link>
                <pubDate>Thu, 09 Apr 2015 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    The rabbit hole keeps getting deeper and deeper. But I like what they&#x27;ve done with the place...
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>Writing a thesis. Writing at home, writing at uni, at work, on planes, on machines half way across the planet with Swedish keyboards attached to them. The amount of computers that have my <strong>git</strong> repository cloned on it is either impressive or terrifying depending on how you look at it. One positive thing about my tree is that a good 90–95% of my ridiculous figure count has been built in Ti<em>k</em>z / PGFPlots. Totally source control friendly, small and portable.</p>
<p><a name="continue-reading"></a>
What hasn't been that nice about it are the few binary dependencies I keep forgetting to track or that nasty little bug that <strong>xelatex</strong> has wherein it just utterly fails when you try and draw a gradient or any form of shading. To overcome this issue I've been running a two step compile process, where figures that require shading are built using <strong>pdflatex</strong>, then if text is required (for labels or annotations for example), <strong>xelatex</strong> is called. This allows the figure font to remain homologous with the main text and the pre-rendered shaded geometry can be simply imported with some form of <code>\includegraphics{}</code> command.</p>
<p>However the figure count is now over 50 and climbing, so building all of them on a new machine or propagating broad changes has become a cumbersome task. Ever since writing my first <a href="/unveiling-some-makefile-black-magic">Makefile</a>, I've enjoyed making simple ones for menial tasks. Nothing fancy, but useful enough to take the time and understand the syntax just that little bit more. Building these figures was an obvious case for some new <code>Makefile</code> magic.</p>
<p>Here's what I came up with on a train to Bendigo with two random obnoxious children crawling over me:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">#All files to be built with pdflatex
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">PSOURCES </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#99c794;">aluminium.tex emegir.tex flourish.tex jjschematic.tex oxygen.tex </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\\
</span><span style="background-color:#2b2c2f;color:#cccece;">                                </span><span style="background-color:#2b2c2f;color:#cccece;">oxygenb.tex qabuum.tex sf.tex sio2.tex
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">#All files to be built with xelatex
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">XSOURCES </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">filter-out </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">wildcard </span><span style="background-color:#2b2c2f;color:#ec5f67;">*</span><span style="background-color:#2b2c2f;color:#6699cc;">.tex</span><span style="background-color:#2b2c2f;color:#c594c5;">))
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">PTARGETS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#f99157;">.tex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#f99157;">.pdf</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">XTARGETS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XSOURCES</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:</span><span style="background-color:#2b2c2f;color:#f99157;">.tex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#f99157;">.pdf</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">PDFLATEX </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#99c794;">pdflatex --shell-escape --extra-mem-top=10000000 --save-size=80000
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">XELATEX </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#99c794;">xelatex --shell-escape --extra-mem-top=10000000 --save-size=80000
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">.PHONY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">all clear rebuild clean distclean
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">all</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">xelatex
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">pdflatex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">xelatex</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#ec5f67;">%</span><span style="background-color:#2b2c2f;color:#6699cc;">.pdf</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#ec5f67;">%</span><span style="background-color:#2b2c2f;color:#99c794;">.tex
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">@[ &#39;</span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">&#39; </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#99c794;">= &#39;</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">findstring </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">))</span><span style="background-color:#2b2c2f;color:#99c794;">&#39; ] &amp;&amp; </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PDFLATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#99c794;"> || </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XELATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">@[ &#39;</span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#cccece;">&#39; </span><span style="background-color:#2b2c2f;color:#5fb3b3;">=</span><span style="background-color:#2b2c2f;color:#99c794;">= &#39;</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">findstring </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">))</span><span style="background-color:#2b2c2f;color:#99c794;">&#39; ] &amp;&amp; </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PDFLATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#99c794;"> || </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XELATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">#Dependencies
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">AGS.pdf BGS.pdf </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">sf.tikz
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">rebuild</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">clean all
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">clear</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">@-rm -f *.aux *.log *.dat
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">clean</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">clear
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">@-rm -f </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">) $(</span><span style="background-color:#2b2c2f;color:#f99157;">XTARGETS</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">distclean</span><span style="background-color:#2b2c2f;color:#5fb3b3;">: </span><span style="background-color:#2b2c2f;color:#99c794;">clean
</span></pre>
<p>There are a few interesting things in here that weren't obvious to me at first. For instance the wildcard property allows a list of some input file type to be made into an output file of the same name. The target <code>%.pdf: %.tex</code> says that all output pdf files will require a corresponding tex file. With my particular case this isn't very helpful as I'd like only some tex files rendered to pdf using one method and the rest rendered with a completely different method. Another question I had was &quot;What's the best way to separate the <strong>pdflatex</strong> and <strong>xelatex</strong> runs?&quot;</p>
<p>The second issue could have just been two lists that would need to be updated every time a new figure was added, but that seemed to be a little inefficient and defeat the purpose of the makefiles' automation. The solution comes from this line:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">filter-out </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#5fb3b3;">, </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">wildcard </span><span style="background-color:#2b2c2f;color:#ec5f67;">*</span><span style="background-color:#2b2c2f;color:#6699cc;">.tex</span><span style="background-color:#2b2c2f;color:#c594c5;">))
</span></pre>
<p>which takes the list <code>$(wildcard *.tex)</code> and filters (removes) any matches from <code>$(PSOURCES)</code>. The <code>wildcard</code> command is necessary here to identify this list as iterable for the <code>%.tex</code> target later on. As the sources for the <strong>pdflatex</strong> run are far fewer than those needing the default <strong>xelatex</strong> treatment, it's much easier to filter the exceptions at this juncture. Now all new files that don't require special treatment also don't require any thought when building them.</p>
<p>Separating the two build types became a bit more of a hassle. Initially, I'd implemented something like</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">ifeq </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">findstring </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">))</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PDFLATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PDFLATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XELATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">XELATEX</span><span style="background-color:#2b2c2f;color:#c594c5;">) </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">endif
</span></pre>
<p>for the <code>%.pdf: %.tex</code> target.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">findstring </span><span style="background-color:#2b2c2f;color:#ec5f67;">$&lt;</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">PSOURCES</span><span style="background-color:#2b2c2f;color:#c594c5;">))
</span></pre>
<p>is tasked to find the current tex file during the expansion of the <code>%.tex</code> wildcard (<code>$&lt;</code>) in the <code>$(PSOURCES)</code> list. If the file isn't in the list this function will return an empty string and the <code>ifeq ($&lt;, &quot;&quot;)</code> test will return false. But this never worked and all files ended up trying to compile with <strong>pdflatex</strong>. Without internet and these kids still crawling over me, I gave up in disgust and stared out the window for the rest of the trip.</p>
<p>Later, back in civilisation, I pulled up the <strong>make</strong> documentation and found out why this method was bound to fail: <strong>make</strong> evaluates conditionals when it reads a makefile</p>
<blockquote>
<p>A <strong>conditional</strong> causes part of a makefile to be obeyed or ignored depending on the values of variables. Conditionals can compare the value of one variable to another, or the value of a variable to a constant string. Conditionals control what make actually &quot;sees&quot; in the makefile, so they cannot be used to control shell commands at the time of execution.</p>
</blockquote>
<p>In other words, a first pass of the file will test the <code>ifeq</code> condition, then choose that option for the second (and final) pass. When the second pass meets the wildcard expansion it just inserts whatever commands the first pass sends it and that's all she wrote. So the solution I required here was to export the problem to the shell each wildcard expansion, test the name of the current .tex file and only then invoke the correct compile tool.</p>
<p>All in all, this file does quite a good job. I haven't seen many people discussing their figure build chain online, so if you have an interesting way of making your figures get in contact—I'd be interested to know what you do.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;makefiles-revisited&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/workbench-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>make</category>
                
                    <category>LaTeX</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Converting 4K Content for Samsung UHD Televisions
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;converting-4k-content-for-samsung-uhd-televisions&#x2F;</link>
                <pubDate>Sat, 22 Nov 2014 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    That is, until the Samsung firmware actually supports their own containers...
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>Early adoption of new technologies is usually mired by complications, but what's been shitting me lately is the trend manufacturers seem to have of pushing tech to market that doesn't even support the main draw card of the product. I purchased a Samsung UA55F9000 UHD TV in December 2013: the month they were released, solely for the 4k capability. Fast forward a year later and I'm still fighting with the upper echelons of Samsung tech support concerning the absolute necessity of being able to use my 4k TV to play 4k content.</p>
<p><a name="continue-reading"></a>
You see, the manual states the TV will play a <code>.S4ud</code> file: essentially a <code>H.264</code> video and an <code>AC3</code> audio stream multiplexed into a <code>TS</code> container. No firmware update since the TVs manufacture has actually allowed this. A second possibility is to use QFHD—four separate HD streams that are then joined together to yield a 4K stream. After quite a conversation with Samsung tech support it was elucidated that this is actually happening in-store when you see these TVs in action with those amazing demos.</p>
<p>So off I went and cut up a few sample files and tested it out—no dice. Two of the four segments were playing, the others were a jaggered mess. After more back and forth with the guys in tech, turns out the demo capability had been broken somewhere in an early firmware patch that was propagated through a number of subsequent versions. Thankfully, this debacle has been fixed and I'm now happily viewing my 4K content in all its glory. Downside is it's still QFHD, not a nice single <code>TS</code> container.</p>
<p>There's also a number of caveats with this method, for instance the files must be named <code>UHD_demo_{a,b,c,d}_*.mp4{sub}</code>, where <code>a</code> is the main file (top left), and the <code>b-d</code> files are <code>sub</code> streams.</p>
<p>Long story short, I've developed a few scripts to automatically take care of all of these problems. They could use a little cleaning up, and wifi connectivity problems at my new house has seen me jump back to Windows recently—so these are batch files rather than bash scripts. Shouldn't be too hard to port them yourself though.</p>
<p>UHD 4K is 3840×2160 pixels, although Digital cinema 4K is 4096×2304. Before the resolution standards settled down, a plethora of content out there was letterboxed in some way, but 4096 pixels wide. Considering this, there are three scripts below for each of these three possibilities. Granted, I could set this up to find the resolution first but <em>brevior saltare cum deformibus mulieribus est vita</em> amiright? Call these snippets <code>conv.bat</code> or something to that effect, and run <code>conv inputFile.mp4</code> (for example) at the CLI. The output will be four files titled with the convention above, where <code>*</code> will be <code>inputFile</code> (to keep things in order, these files output to a folder <code>qfhd</code> and the converted file is archived to a <code>converted</code> folder). Then, you'll need to put them on a fast USB3 stick and plug it into the TV. You'll only see the <code>a</code> file, run it and actually enjoy that massive hole you previously burnt into your wallet.</p>
<p><code>Ffmpeg</code> is the only dependency you'll need. Alter the rate factor in the script (<code>-crf</code>) to your liking; but I've found 15 works just fine.</p>
<p><strong>3840×2160</strong></p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> off
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#f99157;">1
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:~</span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#f99157;">-4</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top left corner and sound
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -acodec ac3 -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">crop=iw/2:ih/2:0:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4 qfhd\UHD_demo_a_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Bottom left corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">crop=iw/2:ih/2:0:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4 qfhd\UHD_demo_b_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">crop=iw/2:ih/2:iw/2:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4 qfhd\UHD_demo_c_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">crop=iw/2:ih/2:iw/2:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4 qfhd\UHD_demo_d_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> converted\
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing of </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> Complete
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> on
</span></pre>
<p><strong>4096×2304</strong></p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> off
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#f99157;">1
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:~</span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#f99157;">-4</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top left corner and sound
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -acodec ac3 -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:2160,crop=iw/2:ih/2:0:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4 qfhd\UHD_demo_a_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Bottom left corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:2160,crop=iw/2:ih/2:0:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4 qfhd\UHD_demo_b_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:2160,crop=iw/2:ih/2:iw/2:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4 qfhd\UHD_demo_c_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:2160,crop=iw/2:ih/2:iw/2:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4 qfhd\UHD_demo_d_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> converted\
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing of </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> Complete
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> on
</span></pre>
<p><strong>4096×anything</strong></p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> off
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#f99157;">1
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">set </span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">=%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">:~</span><span style="background-color:#2b2c2f;color:#f99157;">0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#f99157;">-4</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top left corner and sound
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -acodec ac3 -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:-1,pad=3840:2160:0:(2160-ih)/2,crop=iw/2:ih/2:0:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> a.mp4 qfhd\UHD_demo_a_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Bottom left corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:-1,pad=3840:2160:0:(2160-ih)/2,crop=iw/2:ih/2:0:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> b.mp4 qfhd\UHD_demo_b_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:-1,pad=3840:2160:0:(2160-ih)/2,crop=iw/2:ih/2:iw/2:0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> c.mp4 qfhd\UHD_demo_c_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Top right corner
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">ffmpeg -i </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> -vcodec libx264 -crf </span><span style="background-color:#2b2c2f;color:#f99157;">15</span><span style="background-color:#2b2c2f;color:#cccece;"> -an -vf </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">scale=3840:-1,pad=3840:2160:0:(2160-ih)/2,crop=iw/2:ih/2:iw/2:ih/2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move</span><span style="background-color:#2b2c2f;color:#cccece;"> d.mp4 qfhd\UHD_demo_d_</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">name</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">.mp4sub
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">move </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> converted\
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> Processing of </span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;">input</span><span style="background-color:#2b2c2f;color:#5fb3b3;">%</span><span style="background-color:#2b2c2f;color:#cccece;"> Complete
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">@</span><span style="background-color:#2b2c2f;color:#c594c5;">echo</span><span style="background-color:#2b2c2f;color:#cccece;"> on
</span></pre>
                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;converting-4k-content-for-samsung-uhd-televisions&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/hdr-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Video</category>
                
                    <category>4K</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Coloured Tables for the Memoir Class
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;coloured-tables-for-the-memoir-class&#x2F;</link>
                <pubDate>Sun, 16 Nov 2014 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    So long as that colour isn&#x27;t yellow. I hate yellow.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>If you're a fan of <strong>LaTeX</strong> typography, you may have come across the <a href="http://www.motionmountain.net/">Motion Mountain</a> set of physics textbooks.
This long term project has its own class file, which has been tweaked and honed over many years, has seen many of its pages grace many typography showcases (not to mention commercial successes and other recognitions).
One particular stylistic choice that piqued my interest was the use of coloured rules inside the <code>\table{}</code> environment.</p>
<p>There <em>colortbl</em> package (available on <a href="http://www.ctan.org/tex-archive/macros/latex/contrib/colortbl/">CTAN</a>), with albeit hideous examples, allows for the inclusion of colour into tables; usually to highlight cells, but with a bit of finesse can be persuaded to alter the rule colour also.</p>
<p><a name="continue-reading"></a>
<a href="http://www.ctan.org/tex-archive/macros/latex/contrib/memoir">Memoir</a> is by far the most comprehensive class I've come across that should be the default document choice for those wishing to typeset large and complex documents.
Simply adding <em>colortbl</em> into the preamble of ones document will allow access to the capability needed to obtain coloured table rules, but this is not the only option available.
Memoir incorporates the extensions from <a href="http://www.ctan.org/tex-archive/macros/latex/contrib/booktabs">booktabs</a>, which provides much needed enhancements to the default table environment.
Since <em>booktabs</em> has some rudimentary support for <em>colortbl</em>, Memoir already has latent colour capability from the ported legacy code—it just needs to be enabled.</p>
<p>Add this to your preamble:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">makeatletter
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">\def</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">rulecolor</span><span style="background-color:#2b2c2f;color:#cccece;">#1#</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">CT@arc</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">#1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">\def</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">CT@arc</span><span style="background-color:#2b2c2f;color:#cccece;">#1#2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#5f6364;">%
</span><span style="background-color:#2b2c2f;color:#cccece;">      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">ifdim</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">baselineskip</span><span style="background-color:#2b2c2f;color:#cccece;">=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">z@</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">noalign</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">fi
</span><span style="background-color:#2b2c2f;color:#cccece;">      </span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">gdef</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">CT@arc@</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">color</span><span style="background-color:#2b2c2f;color:#cccece;">#1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">#2</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}}}}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">let</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">CT@arc@</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">relax
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">makeatother
</span></pre>
<p>And set table rules via <code>\rulecolor{color}</code>.
With a little bit of tweaking, your tables will scrub up quite well.</p>
<figure>
    
    <img src="/images/table.png" alt="A Memoir class table with coloured horizontal rules" />
    
    <figcaption>A Memoir class table with coloured horizontal rules</figcaption>
</figure>
<p>
                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;coloured-tables-for-the-memoir-class&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/type-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>LaTeX</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Easy Matlabpool Configuration
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;easy-matlabpool-configuration&#x2F;</link>
                <pubDate>Thu, 13 Nov 2014 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Dive in without caring how deep it is.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>The new <code>parpool</code> option for <code>Matlab 2014b</code> is depreciating <code>matlabpool</code>, merging the ideas of parallelisation locally and remotely in to one.
Now, the same code can be easily sent off to a large, remote cluster or ran over a few more cores on your own machine without much hassle.
Another useful feature is the fact that idle pools will close down after inactivity, allowing you to be lazy with your implementations, while at the same time giving the possibility of efficiency if you require the pool again inadvertently.</p>
<p><a name="continue-reading"></a>
A caveat that I find with this implementation is the freedom to alter the pool size dynamically.
Most may not find this an issue, and are happy with setting the pool to 8 and be done; but if writing large amounts of info to disk constantly is your jam this is seldom the optimal choice.
At least for my routines, writing to platter isn't efficient above 2 threads, and to flash disks, 6 appears optimal.
Also: what if you want some cycles free to actually operate your machine whilst its actively causing the <a href="https://en.wikipedia.org/wiki/Heat_death_of_the_universe">heat death</a>?</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">function </span><span style="background-color:#2b2c2f;color:#6699cc;">pool</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#f99157;">num</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">p</span><span style="background-color:#2b2c2f;color:#5fb3b3;"> = </span><span style="background-color:#2b2c2f;color:#cccece;">gcp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(&#39;</span><span style="background-color:#2b2c2f;color:#99c794;">nocreate</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&#39;)</span><span style="background-color:#2b2c2f;color:#cccece;">; </span><span style="background-color:#2b2c2f;color:#5f6364;">% If no pool, do not create new one.
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#5fb3b3;">isempty(</span><span style="background-color:#2b2c2f;color:#cccece;">p</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5f6364;">%poolsize = 0;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">parpool</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">num</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">poolsize</span><span style="background-color:#2b2c2f;color:#5fb3b3;"> = </span><span style="background-color:#2b2c2f;color:#cccece;">p</span><span style="background-color:#2b2c2f;color:#5fb3b3;">.</span><span style="background-color:#2b2c2f;color:#cccece;">NumWorkers;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#cccece;">poolsize</span><span style="background-color:#2b2c2f;color:#5fb3b3;"> ~= </span><span style="background-color:#2b2c2f;color:#cccece;">num
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#6699cc;">delete</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">gcp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">            </span><span style="background-color:#2b2c2f;color:#cccece;">parpool</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">num</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)</span><span style="background-color:#2b2c2f;color:#cccece;">;
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#c594c5;">end
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">end
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">end
</span></pre>
<p>This function asks for <code>num</code>ber of pools you wish to be created.
If a pool of that size is currently active, nothing is required of the function and your code will continue.
Otherwise, the old pool is shut down and a new one is generated.
Personally, I'd like a future release to enable user access to set the read only attribute <code>p.NumWorkers</code>, but I guess we all can't get everything we want in life.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;easy-matlabpool-configuration&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/bokeh-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Matlab</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Workman layout for Vim
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;workman-layout-for-vim&#x2F;</link>
                <pubDate>Tue, 13 Aug 2013 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    For those of us who REALLY need to type using three layouts.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>I've recently switched keyboard layouts from Dvorak to <a href="http://www.workmanlayout.com/blog/">Workman</a>. Dvorak has been good to me over the past 5 years or so, but the philosophy behind it wasn't actualised in it's final design. Workman has been optimised for English and minimises finger strain <em>etc etc</em>. There's no point rabbiting on about it as all of my praises or critiques are already well fleshed out on the Workman website.</p>
<p><a name="continue-reading"></a>
It's been two weeks or so since the switch and I'm at the proficiency stage where I'm not yelling at the awkwardness of my inability to find a letter, but if the switch from Qwerty to Dvorak is any indication it'll be a couple of months until I'm completely up to speed.</p>
<p>I had a fantastic Vim map for Dvorak suggested by <a href="http://stackoverflow.com/questions/165231/vim-dvorak-keybindings-rebindings">Adam Davis</a>, which kept the Qwerty <em>h,j,k,l</em> navigation keys in the same place; remapping sane Dvorak keys with minimal disruption. So obviously something similar for Workman that didn't disrupt Vim flow is needed.</p>
<p>Taking the laziest approach first; google tells me there are only two current suggestions. First, Matt Weolk has taken the complete remap Qwerty:Workman approach, which is outlined in this <a href="https://gist.github.com/MattWoelk/887861">gist</a> and takes the idea from <em>colqer</em>; a Colemak solution to the same issue. I really don't like the blind approach this method uses as I remember Vim keybindings more on their associations (y = yank), than muscle memory of their original Qwerty locations. The second solution is a simple <em>j ↔ t</em> switch discussed in <a href="http://www.workmanlayout.com/forum/viewtopic.php?id=6">this</a> thread. Closer to what I'm after, and I used it for a while; but ultimately the navigation keys being separated and not entirely on the home row doesn't sit with me.</p>
<p>So, here's my attempt at a decent Workman remapping for Vim:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> l o
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> o l
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> L O
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> O L
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> j n
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> n j
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> J N
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> N J
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gn gj
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gj gn
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> k e
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> e k
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> K E
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> E </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;nop&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gk ge
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> ge gk
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> h y
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">onoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> h y
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> y h
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> H Y
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> Y H
</span></pre>
<p><em>h,j,k,l</em> are replaced by the Workman <em>y,n,e,o</em> home keys, with a few new associations:</p>
<ul>
<li>(<strong>Y</strong>)ank -&gt; (<strong>H</strong>)aul</li>
<li>Search (<strong>N</strong>)ext -&gt; (<strong>J</strong>)ump</li>
<li>(<strong>E</strong>)nd word -&gt; brea(<strong>K</strong>) of word [yeah, that one's a push...]</li>
<li>(<strong>O</strong>)pen new line -&gt; (<strong>L</strong>)ine</li>
</ul>
<p>Considering I now use three different layouts depending on where I am, I've had to set up a layout remap function in my .vimrc. Here it is in it's present state at the time of writing; check my <a href="https://github.com/Libbum/dotfiles">dotfiles</a> repository for updates though.</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot; Keyboard  **************************
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">function </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">type)
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">if </span><span style="background-color:#2b2c2f;color:#6699cc;">a</span><span style="background-color:#2b2c2f;color:#c594c5;">:</span><span style="background-color:#2b2c2f;color:#cccece;">type == </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;dvorak&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapWorkman</span><span style="background-color:#2b2c2f;color:#cccece;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> d h
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> h j
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> t k
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> n l
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> s :
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> S :
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> j d
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">onoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> j d
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> l n
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> L N
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> - $
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> _ ^
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> N </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;C-w&gt;&lt;C-w&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> H </span><span style="background-color:#2b2c2f;color:#f99157;">8</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;Down&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> T </span><span style="background-color:#2b2c2f;color:#f99157;">8</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;Up&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> D </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;C-w&gt;&lt;C-r&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">elseif </span><span style="background-color:#2b2c2f;color:#6699cc;">a</span><span style="background-color:#2b2c2f;color:#c594c5;">:</span><span style="background-color:#2b2c2f;color:#cccece;">type == </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;workman&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapDvorak</span><span style="background-color:#2b2c2f;color:#cccece;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;(O)pen line -&gt; (L)ine
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> l o
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> o l
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> L O
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> O L
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;Search (N)ext -&gt; (J)ump
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> j n
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> n j
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> J N
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> N J
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gn gj
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gj gn
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;(E)nd of word -&gt; brea(K) of word
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> k e
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> e k
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> K E
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> E </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;nop&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> gk ge
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> ge gk
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;(Y)ank -&gt; (H)aul
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> h y
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">onoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> h y
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> y h
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> H Y
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#6699cc;">nnoremap</span><span style="background-color:#2b2c2f;color:#cccece;"> Y H
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">else </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot; qwerty
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapDvorak</span><span style="background-color:#2b2c2f;color:#cccece;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapWorkman</span><span style="background-color:#2b2c2f;color:#cccece;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">endif
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">endfunction
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">function </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapDvorak</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;Unmaps Dvorak keys
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> d
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> h
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> t
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> n
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> s
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> S
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> j
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">ounmap</span><span style="background-color:#2b2c2f;color:#cccece;"> j
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> l
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> L
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> -
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> _
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> N
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> H
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> T
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> D
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">endfunction
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">function </span><span style="background-color:#2b2c2f;color:#6699cc;">UnmapWorkman</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#5f6364;">&quot;Unmaps Workman keys
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> h
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">ounmap</span><span style="background-color:#2b2c2f;color:#cccece;"> h
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> j
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> k
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> l
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> y
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> n
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> e
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> o
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> H
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> J
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> K
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> L
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> Y
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> N
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> E
</span><span style="background-color:#2b2c2f;color:#cccece;">        </span><span style="background-color:#2b2c2f;color:#cccece;">silent! </span><span style="background-color:#2b2c2f;color:#6699cc;">nunmap</span><span style="background-color:#2b2c2f;color:#cccece;"> O
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">endfunction
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">function </span><span style="background-color:#2b2c2f;color:#6699cc;">LoadKeyboard</span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#6699cc;">let</span><span style="background-color:#2b2c2f;color:#cccece;"> keys = $keyboard
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">if</span><span style="background-color:#2b2c2f;color:#cccece;"> (keys == </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;workman&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#cccece;">(</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;workman&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">           </span><span style="background-color:#2b2c2f;color:#cccece;">call </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#cccece;">(</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;dvorak&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">       </span><span style="background-color:#2b2c2f;color:#c594c5;">endif
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">endfunction
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#6699cc;">autocmd</span><span style="background-color:#2b2c2f;color:#cccece;"> VimEnter * call </span><span style="background-color:#2b2c2f;color:#6699cc;">LoadKeyboard</span><span style="background-color:#2b2c2f;color:#cccece;">()
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">:</span><span style="background-color:#2b2c2f;color:#6699cc;">noremap </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;Leader&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">q :call </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#cccece;">(</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;qwerty&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">:echom </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;Qwerty Keyboard Layout&quot;</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">:</span><span style="background-color:#2b2c2f;color:#6699cc;">noremap </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;Leader&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">d :call </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#cccece;">(</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;dvorak&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">:echom </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;Dvorak Keyboard Layout&quot;</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">:</span><span style="background-color:#2b2c2f;color:#6699cc;">noremap </span><span style="background-color:#2b2c2f;color:#fac863;">&lt;Leader&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">w :call </span><span style="background-color:#2b2c2f;color:#6699cc;">Keyboard</span><span style="background-color:#2b2c2f;color:#cccece;">(</span><span style="background-color:#2b2c2f;color:#99c794;">&quot;workman&quot;</span><span style="background-color:#2b2c2f;color:#cccece;">)</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;</span><span style="background-color:#2b2c2f;color:#cccece;">:echom </span><span style="background-color:#2b2c2f;color:#99c794;">&quot;Workman Keyboard Layout&quot;</span><span style="background-color:#2b2c2f;color:#fac863;">&lt;CR&gt;
</span></pre>
                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;workman-layout-for-vim&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/typewriter-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Vim</category>
                
                    <category>Workman</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Unveiling some Makefile Black Magic
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;unveiling-some-makefile-black-magic&#x2F;</link>
                <pubDate>Thu, 28 Mar 2013 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Go back to the shadows.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>Whilst my higher education started off in the computer science realm, I quickly became disillusioned and, excluding a decent temporal shift, moved more into the physical sciences. Whilst I never finished my CS degree; what I completed gave me an adequate understanding of development life cycles, program design and sufficient competency in <strong>c++</strong> to get shit done. When I started heavily coding again, forces shunted me towards <strong>Matlab</strong> and higher level quick and dirty rapid prototyping. As we all know; you can only go so far in this world and I've recently found myself back into the depths with <strong>c</strong>, <strong>fortran</strong> and even a little <strong>assembly</strong>.</p>
<p>Ultimately though, my <strong>c++</strong> programs never needed to link to external libraries or worry about machine specific configurations the <code>-o</code> switch was the only one I needed when calling <code>gcc</code> pretty much. Now I'm building <abbr title="Message Passing Interface">MPI</abbr> tools to run on supercomputing clusters that need the highly optimised linear algebra routines; written down by our forefathers in a more civilised age.</p>
<p><a name="continue-reading"></a>
I need a Makefile, the file filled with dark arts known only to those with neck beards and ghostly white skin.</p>
<p>Realistically, Makefiles are relatively simple things, but seem to have a stigma associated with them if you're outside the computer science sphere. In fact; here's a quote from my PhD supervisor when I told him about my knowledge gain concerning this post:</p>
<blockquote>
<p>Hehe, careful.  Those that learn how to write makefiles are usually doomed to vanish … banished to a basement (or IT department of a fortune 500 company) for all eternity.</p>
</blockquote>
<p>I guess writing this post and publishing it on the internet is sealing my fate…</p>
<p>The <em>my first Makefile</em> tutorials around the internet are not too bad (take a look at <a href="http://www.wlug.org.nz/MakefileHowto">WLUG</a> and <a href="http://mrbook.org/blog/tutorials/make/">Mrbook</a> to get started); but the Black Magic I eluded to in the title of this post is much cooler than just typing <code>make</code> instead of <code>g++ main.cpp interrobang.cpp -o omgwtfbbq</code>.</p>
<h3 id="pre-processor-macros"><a class="gutenberg-anchor" href="#pre-processor-macros" aria-label="Anchor link for: pre-processor-macros">🔗</a>
Pre-processor macros</h3>
<hr />
<p>The specific problem I needed to overcome was managing one set of code that requires different linking libraries depending on what machine it was running on.</p>
<ul>
<li><strong>Vayu</strong> uses intel compilers and requires the MKL libraries</li>
<li><strong>Trifid</strong> uses gcc compilers and requires the blas and lapack libraries</li>
</ul>
<p>Because of these conditions, code in certain files differ. For example, calls to linear algebra routines on <strong>Vayu</strong> require an <code>MKL_int</code> type, whereas the same call on <strong>Trifid</strong> asks for <code>int</code>. A pre-processor macro defining a generalised int type <code>LP_INT</code> enables me to overcome this problem. This macro uses an <code>if-elif-else</code> formalism to check what machine the code is compiling on and adds additional headers if needed:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#if defined</span><span style="background-color:#2b2c2f;color:#cccece;">(VAYU)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#include </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&lt;</span><span style="background-color:#2b2c2f;color:#99c794;">mkl</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&gt;
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#define </span><span style="background-color:#2b2c2f;color:#cccece;">LP_INT MKL_INT
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#elif defined</span><span style="background-color:#2b2c2f;color:#cccece;">(TRIFID)
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#define </span><span style="background-color:#2b2c2f;color:#cccece;">LP_INT </span><span style="background-color:#2b2c2f;color:#c594c5;">int
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#else
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#error </span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;</span><span style="background-color:#2b2c2f;color:#99c794;">One of VAYU or TRIFID must be defined</span><span style="background-color:#2b2c2f;color:#5fb3b3;">&quot;
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">#endif
</span></pre>
<p>Now, how can we define these <code>VAYU</code> and <code>TRIFID</code> variables? SUMMON THE MAKEFILE:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">HOST_NAME </span><span style="background-color:#2b2c2f;color:#5fb3b3;">:= </span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#6699cc;">shell hostname</span><span style="background-color:#2b2c2f;color:#c594c5;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">ifeq </span><span style="background-color:#2b2c2f;color:#5fb3b3;">(</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">HOST_NAME</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#5fb3b3;">,</span><span style="background-color:#2b2c2f;color:#cccece;">trifid</span><span style="background-color:#2b2c2f;color:#5fb3b3;">)
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">LAPACK </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#99c794;">/usr/local/lapack/3.4.2/lib/liblapack.so /usr/local/blas/1.0.248/lib/libblas.so -lm
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">LIBS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#99c794;">-L/usr/local/lapack/3.4.2/lib
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">CXX </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#99c794;">g++ </span><span style="background-color:#2b2c2f;color:#5f6364;">#icpc
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">CPPFLAGS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">+= </span><span style="background-color:#2b2c2f;color:#99c794;">-DTRIFID=1
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">else
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">INCLUDES </span><span style="background-color:#2b2c2f;color:#5fb3b3;">+= </span><span style="background-color:#2b2c2f;color:#99c794;">-I</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">MKL</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#99c794;">/include
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">LAPACK </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#99c794;">-lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">LIBS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">= </span><span style="background-color:#2b2c2f;color:#99c794;">-L</span><span style="background-color:#2b2c2f;color:#c594c5;">$(</span><span style="background-color:#2b2c2f;color:#f99157;">MKL</span><span style="background-color:#2b2c2f;color:#c594c5;">)</span><span style="background-color:#2b2c2f;color:#99c794;">/lib/intel64
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#cccece;">CPPFLAGS </span><span style="background-color:#2b2c2f;color:#5fb3b3;">+= </span><span style="background-color:#2b2c2f;color:#99c794;">-DVAYU=1
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#c594c5;">endif
</span></pre>
<p>Grab the hostname of the machine &amp; check it against known results (in my case I just check for <em>trifid</em>). Any shell call can be used here if hostname isn't appropriate. Then, setup the required libraries, includes and compiler information specific to the identified machine. Most importantly: append <code>CPPFLAGS</code> to incorperate a machine bool set to 1 which the pre-processor macros are looking for.</p>
<p><em>Et voilà!</em> Call <code>make</code> on either machine and build without a hassle. No more merge conflicts between git branches for me. <em>A shoutout to <a href="http://tuxdude.github.com/">Ash</a> who put me on the right path with this issue.</em></p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;unveiling-some-makefile-black-magic&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/lantern-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>C++</category>
                
                    <category>make</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Using datatool and TikZ to generate figures from data
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;using-datatool-and-tikz-to-generate-figures-from-data&#x2F;</link>
                <pubDate>Sat, 16 Mar 2013 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Or just use print screen and MS Paint, you know, what ever is easiest...
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>If you're not already using <a href="http://sourceforge.net/projects/pgf/">PGF and Ti<em>k</em>Z</a> for figures in your <strong>LaTeX</strong> documents, I suggest you take a few evenings and get acquainted with a number of <a href="http://texample.net/tikz/">examples</a>, so you can grasp the magnitude of its' capability—you certainly won't be disappointed.</p>
<p>Building static diagrams and graphs (adding <a href="http://pgfplots.sourceforge.net/">PGFPlots</a> into the mix) is fine, but I find myself constantly wanting decent plots from real data, that don't fit the usual line/surface paradigm. The <a href="http://www.ctan.org/pkg/datatool">datatool</a> package is perfect for this kind of work.</p>
<p><a name="continue-reading"></a>
Something I'm working on currently is the classification of voids in amorphous solids, voronoi networks seem to be a great way of expressing the arrangement of atoms in these systems. The following example uses an amorphous aluminium oxide and is represented in 2D so as not to complicate the problem too much.</p>
<p>To simplify things further, I've separated my input data into three <abbr title="Comma Separated Value">csv</abbr> files that look something like this:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">1,Al,10.331817,36.323166,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">2,Al,5.092404,21.862188,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">3,Al,2.332884,23.765770,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">4,Al,13.550237,30.676344,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">5,Al,0.676694,28.555687,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">6,Al,14.927469,33.200344,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">7,Al,4.266311,33.304264,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">8,Al,7.634949,33.187614,1.250000
</span><span style="background-color:#2b2c2f;color:#cccece;">...
</span></pre>
<p>The <code>datatool</code> package reads this information in through its <em>load database</em> command <code>\DTLloaddb</code></p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLloaddb</span><span style="background-color:#2b2c2f;color:#cccece;">[noheader,keys=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">idx,species,x,y,r</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">]</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data2Dtest.csv</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>pulling the file into the <code>data</code> variable, and assigning <code>keys</code> to each column. Now using a <code>foreach</code> command to loop over all rows in <code>data</code>,</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLforeach</span><span style="background-color:#2b2c2f;color:#cccece;">*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">idx</span><span style="background-color:#2b2c2f;color:#cccece;">=idx, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">species</span><span style="background-color:#2b2c2f;color:#cccece;">=species, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">x</span><span style="background-color:#2b2c2f;color:#cccece;">=x, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">y</span><span style="background-color:#2b2c2f;color:#cccece;">=y, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">r</span><span style="background-color:#2b2c2f;color:#cccece;">=r</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>I can draw a circle of radius <code>\r</code> at position (<code>\x</code>,<code>\y</code>); as well as color each circle depending on its associated <code>\species</code> key [lines 23--30 in the <a href="#code">full code</a> below].</p>
<p>Two other functions of <code>datatool</code> that I use in this example are extremely useful:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLcomputebounds</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>computes the bounds of the (x,y) data, which I use to draw a bounding box;</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">oneX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">one</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
<p>grabs the location of <code>x</code> from <code>data</code> at <code>idx</code>, where that index value equals <code>\one</code> from another data set.</p>
<p>If you include all of this with some Ti<em>k</em>Z trickery, it's fairly simple to generate a number of figures like this incredibly fast with a myriad of different data sets.</p>
<figure>
    
    <img src="/images/voronoi.png" alt="Voronoi diagram of amorphous aluminium oxide" />
    
    <figcaption>Voronoi diagram of amorphous aluminium oxide</figcaption>
</figure>
<p>
<p>The entire code-set for this project is below. The in-line comments expand on the syntax I outline above and should answer most questions you may have about each functions purpose.</p>
<p><a name="code" /></p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#5f6364;">% generates a 2D voronoi diagram from input files in tikz
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">documentclass</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#fac863;">article</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">pagestyle</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">empty</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">usepackage</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#fac863;">tikz</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">usepackage</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#fac863;">datatool</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">usepackage</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#fac863;">graphicx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLloaddb</span><span style="background-color:#2b2c2f;color:#cccece;">[noheader,keys=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">idx,species,x,y,r</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">]</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data2Dtest.csv</span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#5f6364;">%CSV data
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLloaddb</span><span style="background-color:#2b2c2f;color:#cccece;">[noheader,keys=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">one,two,three</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">]</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">tri</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">tri2Dtest.csv</span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#5f6364;">%delaunay triangulation data
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLloaddb</span><span style="background-color:#2b2c2f;color:#cccece;">[noheader,keys=</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">vxx,vxy,vyx,vyy</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">]</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">vor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">vor2Dtest.csv</span><span style="background-color:#2b2c2f;color:#5fb3b3;">} </span><span style="background-color:#2b2c2f;color:#5f6364;">%voronoi data
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">usetikzlibrary</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">calc,fadings</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%To save output, uncomment next three lines (Third only to force recompile).
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Then execute with pdflatex -shell-escape voronoi2D.tex
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\usetikzlibrary{external}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\tikzexternalize % activate!
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\tikzset{external/force remake}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">begin</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#f99157;">document</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\begin{figure}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\resizebox{\textwidth}{!}{
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">begin</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#f99157;">tikzpicture</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}[</span><span style="background-color:#2b2c2f;color:#f99157;">scale</span><span style="background-color:#2b2c2f;color:#cccece;">=0.5</span><span style="background-color:#2b2c2f;color:#5fb3b3;">]
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw Atoms
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLforeach</span><span style="background-color:#2b2c2f;color:#cccece;">*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">idx</span><span style="background-color:#2b2c2f;color:#cccece;">=idx, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">species</span><span style="background-color:#2b2c2f;color:#cccece;">=species, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">x</span><span style="background-color:#2b2c2f;color:#cccece;">=x, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">y</span><span style="background-color:#2b2c2f;color:#cccece;">=y, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">r</span><span style="background-color:#2b2c2f;color:#cccece;">=r</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">%Choose color based on species, draw circle at current point
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">ifthenelse</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">pdfstrcmp</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">species</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">Al</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">=0</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">shade</span><span style="background-color:#2b2c2f;color:#cccece;">[ball color=gray] (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">x</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">y</span><span style="background-color:#2b2c2f;color:#cccece;">) circle(0.4*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">r</span><span style="background-color:#2b2c2f;color:#cccece;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">shade</span><span style="background-color:#2b2c2f;color:#cccece;">[ball color=red] (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">x</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">y</span><span style="background-color:#2b2c2f;color:#cccece;">) circle(0.4*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">r</span><span style="background-color:#2b2c2f;color:#cccece;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw Delaunay Simlpexes
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLforeach</span><span style="background-color:#2b2c2f;color:#cccece;">*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">tri</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">one</span><span style="background-color:#2b2c2f;color:#cccece;">=one, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">two</span><span style="background-color:#2b2c2f;color:#cccece;">=two, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">three</span><span style="background-color:#2b2c2f;color:#cccece;">=three</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">%One, two and three are indexes of the corners of each D triangle
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">%Get locations from \x &amp; \y in data db for each index
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">oneX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">one</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">oneY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">one</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">twoX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">two</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">twoY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">two</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">threeX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">three</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLgetvalueforkey</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">threeY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">idx</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">three</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw triangle
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">draw</span><span style="background-color:#2b2c2f;color:#cccece;"> (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">oneX</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">oneY</span><span style="background-color:#2b2c2f;color:#cccece;">) -- (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">twoX</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">twoY</span><span style="background-color:#2b2c2f;color:#cccece;">) -- (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">threeX</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">threeY</span><span style="background-color:#2b2c2f;color:#cccece;">) -- cycle;
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw Bounding Box
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Grab max/min of coords
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLcomputebounds</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">data</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">x</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{</span><span style="background-color:#2b2c2f;color:#cccece;">y</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxX</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxY</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw Box
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">draw</span><span style="background-color:#2b2c2f;color:#cccece;">[gray, thick] (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minX</span><span style="background-color:#2b2c2f;color:#cccece;">-1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxX</span><span style="background-color:#2b2c2f;color:#cccece;">-1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">) rectangle (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minY</span><span style="background-color:#2b2c2f;color:#cccece;">+1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxY</span><span style="background-color:#2b2c2f;color:#cccece;">+1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">);
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Set clipping path for voronoi data
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">clip</span><span style="background-color:#2b2c2f;color:#cccece;"> (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minX</span><span style="background-color:#2b2c2f;color:#cccece;">-1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxX</span><span style="background-color:#2b2c2f;color:#cccece;">-1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">) rectangle (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">minY</span><span style="background-color:#2b2c2f;color:#cccece;">+1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{\</span><span style="background-color:#2b2c2f;color:#6699cc;">maxY</span><span style="background-color:#2b2c2f;color:#cccece;">+1</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}</span><span style="background-color:#2b2c2f;color:#cccece;">);
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw Voronoi cells
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">DTLforeach</span><span style="background-color:#2b2c2f;color:#cccece;">*</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#cccece;">vor</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{\</span><span style="background-color:#2b2c2f;color:#6699cc;">vxx</span><span style="background-color:#2b2c2f;color:#cccece;">=vxx, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vxy</span><span style="background-color:#2b2c2f;color:#cccece;">=vxy, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vyx</span><span style="background-color:#2b2c2f;color:#cccece;">=vyx, </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vyy</span><span style="background-color:#2b2c2f;color:#cccece;">=vyy</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}{
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5f6364;">%Draw line
</span><span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">draw</span><span style="background-color:#2b2c2f;color:#cccece;">[blue,dashed] (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vxx</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vyx</span><span style="background-color:#2b2c2f;color:#cccece;">) -- (</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vxy</span><span style="background-color:#2b2c2f;color:#cccece;">,</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#6699cc;">vyy</span><span style="background-color:#2b2c2f;color:#cccece;">);
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#f99157;">tikzpicture</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span><span style="background-color:#2b2c2f;color:#5f6364;">%\end{figure}
</span><span style="background-color:#2b2c2f;color:#cccece;">
</span><span style="background-color:#2b2c2f;color:#5fb3b3;">\</span><span style="background-color:#2b2c2f;color:#c594c5;">end</span><span style="background-color:#2b2c2f;color:#5fb3b3;">{</span><span style="background-color:#2b2c2f;color:#f99157;">document</span><span style="background-color:#2b2c2f;color:#5fb3b3;">}
</span></pre>
                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;using-datatool-and-tikz-to-generate-figures-from-data&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/paper-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>LaTeX</category>
                
                    <category>TikZ</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Octopress and jQuery
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;octopress-and-jquery&#x2F;</link>
                <pubDate>Mon, 11 Mar 2013 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    It&#x27;s always the little things that take hours to figure out.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>In the process of theming <a href="https://axiomatic.neophilus.net">Axiomatic Semantics</a>, I came across a virtually undocumented (in the Octopress sphere) caveat when including jQuery elements. A number of javascript functions in the Octopress source use <code>$</code> as a variable. This is not uncommon; although <code>jQuery</code> aliases to <code>$</code> - which causes some confusion in the processing of Octopress' functions. My issue was the GitHub aside constantly being stuck at the <em>Status Updating...</em> phase. To overcome this issue, the simplest method is to insert the jQuery include in <code>after_footer.html</code>, but if you need the call before then for whatever reason and want it in <code>head.html</code>; you're gonna have a bad time.</p>
<p><a name="continue-reading"></a>
The fix is quite simple:</p>
<pre style="background-color:#2b2c2f">
<span style="background-color:#2b2c2f;color:#cccece;">    </span><span style="background-color:#2b2c2f;color:#5fb3b3;">$.</span><span style="background-color:#2b2c2f;color:#6699cc;">noConflict</span><span style="background-color:#2b2c2f;color:#5fb3b3;">()
</span></pre>
<p>will return control of <code>$</code> back to Octopress as old references of <code>$</code> are saved during jQuery initialization; <code>noConflict()</code> simply restores them for use again. You can read more about it in the <a href="http://api.jquery.com/jQuery.noConflict/">jQuery documentation</a>.</p>
<p><strong>Note:</strong> This is not to be confused with the <em>Status Updating…</em> bug that was rectified in Octopress 2.0 when GitHub updated their API to v3. If you're using an older Octopress version, a <code>rake update_source</code> should take care of that problem.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;octopress-and-jquery&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/jquery-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Octopress</category>
                
                    <category>jQuery</category>
                
            </item>
        
            <item>
                <title>
                    <![CDATA[
                    Hello World
                    ]]>
                </title>
                <link>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;hello-world&#x2F;</link>
                <pubDate>Sat, 02 Mar 2013 00:00:00 +0000</pubDate>
                <description>
                    <![CDATA[
                    Tabula Rasa.
                    ]]>
                </description>
                <content:encoded>
                    <![CDATA[
                    <p>In the past, my blogs have always been akin to a public, online diary. They tended to generally be inane drivel about what we got up to on Friday night. With that being said, the era I'm referring to is circa 2002; modern technology has moved on—now we have Facebook for that kind of shit.</p>
<p><a name="continue-reading"></a>
My goals for this blog are somewhat different. I've realised that my grandiose schemes for this domain (<a href="https://www.neophilus.net">neophilus.net</a>) are most likely never going to happen, and my life now is considerably busier than it was back in the day. Also, no-one gives two shits about some random guys' everyday life; not unless they're a 13 yo girl swooning over a pop star.</p>
<p>If you are a 13 yo girl; fan-mail is appreciated, although I highly doubt you're my target audience.</p>
<p>I'm a physicist, interested in high performance computing, Linux, electronics, UAVs, hardware &amp; software hacking, optimisation and science in general (I elaborate a little more on my <a href="/about">about</a> page). My blog will mostly be about these topics (there will likely be a few posts on ancient history or linguistics from time to time as well).</p>
<p>Initially, I intend <a href="https://axiomatic.neophilus.net">Axiomatic Semantics</a> to be a log of things I'm learning as I push through this barrier I seem to be approaching presently: a capable programmer that isn't really working on public projects at all, but feels he should be. Also, there's a massive amount of information I'm discovering as I complete my PhD, or my research work at DSTO—a lot of it I feel may be useful to others out there. There's also the added bonus of this ultimately being an easy archive for me to come back to in the future—once I've totally forgot about something and attempt to reinvent the wheel.</p>
<p>Bear with me for a bit whilst I get the back end set up to my liking—actual content will soon follow.</p>

                    ]]>
                </content:encoded>
                <guid>https:&#x2F;&#x2F;axiomatic.neophilus.net&#x2F;hello-world&#x2F;</guid>
                <enclosure url="https:&#x2F;&#x2F;axiomatic.neophilus.net/images/sunrise-banner.jpg" length="0" type="image/jpeg"/>
                <dc:creator>Tim DuBois</dc:creator>
                
                    <category>Entropy</category>
                
            </item>
        
    </channel>
</rss>
