<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>ByteSizedWorkbench</title>
        <link>https://www.bytesizedworkbench.com</link>
        <description><![CDATA[A Tiny Platform to Discuss the Art of Software Development]]></description>
        <atom:link href="https://www.bytesizedworkbench.com/rss.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Fri, 09 Jan 2026 22:26:47 UT</lastBuildDate>
        <item>
    <title>Treating AI Like a Contractor: Guide to Force Multiplication</title>
    <link>https://growingliberty.com/blog/treating-ai-like-a-contractor-guide-to-force-multiplication/index.html</link>
    <description><![CDATA[<p>AI proficiency has become the difference between thriving and being left behind in software development.
AI advances rapidly, so we must rapidly improve our ability to use it effectively.</p>
<p>The good news? Like any skill, deliberate practice builds competence<span class="citation" data-cites="ericsson_peak_2016"><a href="#ref-ericsson_peak_2016">[1]</a></span>. The more targeted experience you gain, the more you accomplish.
This article shares what works based on practical experience.
<!--more--></p>
<figure>
<img src="mind-for-bicycle-ai-contractor.png" width="100%" class="center-me"/>
<figcaption>
Mind for bicycle. AI image
</figcaption>
</figure>
<h2 id="the-contractor-in-your-ide">The Contractor in Your IDE</h2>
<p>Think of AI as a type of contractor: brilliant, fast, and tireless—but with no memory, no wisdom, and no stake in your project’s success.
This mental model changes how you interact with AI tools. Future articles will explore other mental models in detail.</p>
<p>Just as with human contractors, you must clearly communicate your needs and expectations to AI. Great results require clear context, concrete constraints, and validation checkpoints.</p>
<p><strong>The harsh truth</strong>: AI excels at certain tasks, delivering results faster and cheaper than any human. Many developers initially reject this reality.</p>
<p>Have you thought or said something like this?</p>
<blockquote>
<p>I have tried AI. It’s nothing more than a fancy auto-complete.</p>
</blockquote>
<p>Or</p>
<blockquote>
<p>I tried it. I can produce better code faster without its so-called help.</p>
</blockquote>
<p>I thought exactly these things before I realized the problem wasn’t AI, it was my approach. More specifically, my lack of skill in working with it.
If you cannot write better software faster than you ever imagined using AI, then the issue is technique, and that’s fixable.</p>
<h2 id="ai-as-a-force-multiplier">AI as a Force Multiplier</h2>
<p>AI isn’t a 10x developer, it’s a <a href="https://en.wikipedia.org/wiki/Force_multiplication">force multiplier</a>.
A developer understands how the project fits with the business, larger mission, and other knowledge not available to the AI.
This means you must carefully focus and direct the AI to useful activities. When done well, you benefit from useful results quickly.</p>
<p>Here’s what that means in practice.</p>
<h3 id="ai-contractor-superpowers">AI Contractor Superpowers</h3>
<ul>
<li>Execute tasks at superhuman speed</li>
<li>Recognize patterns across vast knowledge domains</li>
<li>Generate creative solutions you might not consider</li>
<li>Work tirelessly without reduction in performance</li>
</ul>
<h3 id="how-ai-contractors-differ-from-humans">How AI Contractors Differ from Humans</h3>
<ul>
<li>No memory between interactions unless you explicitly provide it</li>
<li>Zero wisdom about your codebase, architecture, or constraints</li>
<li>Will confidently hallucinate when uncertain, responding with convincing (and sometimes amusing) but incorrect information<span class="citation" data-cites="floridi_gpt_2020">[2]</span></li>
<li>Cannot make strategic decisions</li>
<li>Can enter repetitive loops when stuck on a problem</li>
</ul>
<p>While these appear to be limitations, understanding them transforms them into manageable constraints. Sometimes these characteristics can even be useful.</p>
<h3 id="your-responsibilities">Your Responsibilities</h3>
<ul>
<li>Provide robust, efficient context</li>
<li>Validate every output</li>
<li>Make architectural decisions with clear implementation expectations</li>
<li>Iterate and refine specifications and improve problem definitions</li>
<li>Redirect to ensure effective progress</li>
<li>Use the best tool for each job</li>
<li>Protect your private data</li>
</ul>
<p>You must define <em>what</em> you want done, <em>how</em> to do it, and <em>establish validations</em>.</p>
<h4 id="data-privacy-and-security">Data Privacy and Security</h4>
<p>Like human contractors, AI tools require careful data management. Never assume data you share is private. Encrypt or obscure sensitive information before sharing with AI.</p>
<p>Tools like <a href="https://github.com/FiloSottile/age">Age</a> provide practical encryption without complex infrastructure.
Remember that AI assistants may not follow instructions as literally as traditional software.
For example, if you specify a working directory but later reference an external file, the AI might access that file despite your initial constraints.</p>
<h4 id="choosing-the-right-tool-and-mission">Choosing the Right Tool and Mission</h4>
<p>AI focus has two aspects: knowing where to apply AI and maintaining proper aim. AI is not the best tool for every job, so focus on the things it does best.
I am reminded of Star Trek where Dr. McCoy, when asked to do something outside his area of expertise, often reminds the captain that he is a doctor and not trained as a bricklayer or whatever.</p>
<p>Just as you expect better results for a plumbing job when hiring a plumbing contractor than a roofing contractor,
you need to ensure you use the best models and tools for the job at hand. Future articles will explore this in detail.</p>
<p>A force multiplier is useful only when it brings you closer to your goal. Think of golf. The goal is to move the ball into the hole with the fewest strokes.
Beginner golfers often focus on hitting the ball as far as they can. Golfers quickly learn that hitting the ball twice as far is good only when this results in moving the ball closer to the hole.
Aim is as important as distance.</p>
<figure>
<img src="./ai-proficiency-levels.png" width="100%"/>
<figcaption>
Fig 1: The AI Proficiency Progression Path
</figcaption>
</figure>
<h2 id="understanding-ai-behavior">Understanding AI Behavior</h2>
<p>What we observe as hallucinations aren’t defects, they’re features of probabilistic design<span class="citation" data-cites="floridi_gpt_2020"><a href="#ref-floridi_gpt_2020">[2], [3]</a></span>.
They enable creativity but require validation loops.</p>
<p>Test-Driven Development still holds regardless of how the code is written<span class="citation" data-cites="beck_test_2003"><a href="#ref-beck_test_2003">[4]</a></span>. When interacting with AI, we also need, <em>Validation-Driven Prompting</em> (VDP).</p>
<p>Test‑Driven Development ensures code aligns with expectations defined in tests; similarly, Validation-Driven Prompting ensures AI responses or agent actions align with expectations defined in prompts.</p>
<p>I recommend instructing AI agents to develop software using TDD. AI agents benefit from TDD the same way human developers do. Defining tests first helps communicate more precisely what we need.</p>
<p>It provides better context.</p>
<p>VDP helps the AI know when and how a response meets our needs. Here is a quick example.</p>
<p>While working on a markdown table, I asked AI to insert two new columns.
Multiple prompts failed until I instructed the AI to validate each field as a data matrix. After adding that validation instruction, the AI updated the table correctly.
This is just one example of many I have experienced personally.</p>
<p>For this series, when I use the term “AI,” I generally mean Large Language Models (LLMs) — systems trained to predict probable text outputs based on input patterns<span class="citation" data-cites="openai_gpt4_2023"><a href="#ref-openai_gpt4_2023">[5]</a></span>. Understanding they’re probabilistic, not deterministic, explains both their power and pitfalls.</p>
<p>Steve Jobs famously described a computer as a <a href="https://www.youtube.com/watch?v=NjIhmzU0Y8Y">bicycle for the mind</a>.
AI is becoming a <em>mind for that bicycle</em>. The difference between beautiful, production-ready code and total garbage comes down to how you interact with that mind.
While this is true when working with any contractor, your AI contractor lacks the agency afforded a human, so you must adjust your approach accordingly.</p>
<h2 id="building-skill-on-a-moving-frontier">Building Skill on a Moving Frontier</h2>
<p>AI skill development requires deliberate practice with feedback loops<span class="citation" data-cites="ericsson_peak_2016"><a href="#ref-ericsson_peak_2016">[1]</a></span>.
But here’s the twist: the frontier moves while you’re learning it.</p>
<p>AI changes so quickly that some things true today are outdated tomorrow. Another challenge is grasping non-linear improvement.
AI capabilities don’t grow steadily, they move, stall, and make dramatic jumps.</p>
<h3 id="this-means-two-things">This Means Two Things</h3>
<ol type="1">
<li><p><strong>Focus on transferable skills</strong>: Context engineering, validation patterns, and mental models (like the contractor framework) remain valuable even as specific tools change.</p></li>
<li><p><strong>Build your practice loop</strong>: Nobody knows what will work best tomorrow because those techniques don’t exist yet. You need a system for continuous experimentation and improvement.</p></li>
</ol>
<figure>
<img src="improvement-loop.png" width="60%" class="center-me"/>
<figcaption>
Fig 2: Continuous improvement prompt loop.
</figcaption>
</figure>
<h2 id="the-context-engineering-evolution">The Context Engineering Evolution</h2>
<p>Prompt engineering exemplifies how the field evolves. Initially popular, it was declared unnecessary as models gained automated reasoning capabilities.
Then practitioners discovered it wasn’t dead—</p>
<blockquote>
<p>Response quality still depends on context quality.</p>
</blockquote>
<p>The “death” of <em>prompt engineering</em> gave birth to <em>context engineering</em><span class="citation" data-cites="anthropic_context_2024"><a href="#ref-anthropic_context_2024">[6]</a></span>.
The net here is that no matter what you do with AI, context matters. Mastering context is a transferable skill.</p>
<h2 id="what-this-series-covers">What This Series Covers</h2>
<p>This series targets developers with basic AI experience who want to move from “fancy autocomplete” to genuine force multiplication<span class="citation" data-cites="peng_impact_2023"><a href="#ref-peng_impact_2023">[7]</a></span>.</p>
<p>Examples will be based on my macOS setup, but translate easily to other platforms.</p>
<h2 id="next-steps">Next Steps</h2>
<p>AI isn’t magic. It’s a tool that rewards skill.
Like learning any technology, you need deliberate practice, feedback loops, and experimentation. The difference?
The frontier keeps moving, so your learning system matters more than memorizing specific techniques.</p>
<p>The most important transferable skill right now? <strong>Context engineering.</strong></p>
<p>The next articles will focus on context engineering, including some things rarely discussed elsewhere.</p>
<p><strong>Try this now:</strong> Take your last frustrating AI interaction. How many prompts did it take until you were satisfied with the response or gave up?
If you were finally satisfied, what did your last prompt provide that was missing from the previous prompts? If you were never satisfied with the response, why not?</p>
<p>Questions? Experiments to share? Reach out. We accomplish more through collaboration.</p>
<h2 id="references">References</h2>
<div id="refs" class="references csl-bib-body" data-entry-spacing="0" role="list">
<div id="ref-ericsson_peak_2016" class="csl-entry" role="listitem">
<div class="csl-left-margin">[1] </div><div class="csl-right-inline">K. A. Ericsson and R. Pool, <em>Peak: Secrets from the new science of expertise</em>. Boston, MA: Houghton Mifflin Harcourt, 2016. Available: <a href="https://archive.org/details/peaksecretsfromn0000eric_c6q1">https://archive.org/details/peaksecretsfromn0000eric_c6q1</a></div>
</div>
<div id="ref-floridi_gpt_2020" class="csl-entry" role="listitem">
<div class="csl-left-margin">[2] </div><div class="csl-right-inline">L. Floridi and M. Chiriatti, <span>“GPT-3: Its nature, scope, limits, and consequences,”</span> <em>Minds and Machines</em>, vol. 30, no. 4, pp. 681–694, 2020, doi: <a href="https://doi.org/10.1007/s11023-020-09548-1">10.1007/s11023-020-09548-1</a>.</div>
</div>
<div id="ref-ji_survey_2023" class="csl-entry" role="listitem">
<div class="csl-left-margin">[3] </div><div class="csl-right-inline">Z. Ji <em>et al.</em>, <span>“Survey of hallucination in natural language generation,”</span> <em>ACM Computing Surveys</em>, vol. 55, no. 12, pp. 1–38, 2023, doi: <a href="https://doi.org/10.1145/3571730">10.1145/3571730</a>.</div>
</div>
<div id="ref-beck_test_2003" class="csl-entry" role="listitem">
<div class="csl-left-margin">[4] </div><div class="csl-right-inline">K. Beck, <em>Test-driven development: By example</em>. Boston, MA: Addison-Wesley, 2003. Available: <a href="https://archive.org/details/est-driven-development-by-example">https://archive.org/details/est-driven-development-by-example</a></div>
</div>
<div id="ref-openai_gpt4_2023" class="csl-entry" role="listitem">
<div class="csl-left-margin">[5] </div><div class="csl-right-inline">OpenAI, <span>“GPT-4 technical report.”</span> 2023. Available: <a href="https://arxiv.org/abs/2303.08774">https://arxiv.org/abs/2303.08774</a></div>
</div>
<div id="ref-anthropic_context_2024" class="csl-entry" role="listitem">
<div class="csl-left-margin">[6] </div><div class="csl-right-inline">Anthropic, <span>“Effective context engineering for AI agents.”</span> 2024. Available: <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents</a></div>
</div>
<div id="ref-peng_impact_2023" class="csl-entry" role="listitem">
<div class="csl-left-margin">[7] </div><div class="csl-right-inline">S. Peng, E. Kalliamvakou, P. Cihon, and M. Demirer, <span>“The impact of AI on developer productivity: Evidence from GitHub copilot,”</span> <em>arXiv preprint arXiv:2302.06590</em>, 2023, Available: <a href="https://arxiv.org/abs/2302.06590">https://arxiv.org/abs/2302.06590</a></div>
</div>
</div>]]></description>
    <pubDate>Sat, 29 Nov 2025 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/treating-ai-like-a-contractor-guide-to-force-multiplication/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>The Joy of Alacritty</title>
    <link>https://growingliberty.com/blog/the-joy-of-alacritty/index.html</link>
    <description><![CDATA[<p>I have been using <a href="http://iterm2.com">iTerm2</a> for ages and would have continued had a recent
update not broken ligatures for me. I am so glad it did, because it lead me to
<a href="https://github.com/jwilm/alacritty">Alacritty</a>.</p>
<h2 id="what">What</h2>
<p><a href="https://github.com/jwilm/alacritty">Alacritty</a> does all the things I need and may even be faster than iTerm2.
It is also <!--more--> a kick-butt <a href="https://www.rust-lang.org">Rust</a> based
project. What more could you ask for? If you say <em>tabs</em>, well then no,
<a href="https://github.com/jwilm/alacritty">Alacritty</a> does not support tabs. I use Tmux in place of tabs, so for me
this just means that <a href="https://github.com/jwilm/alacritty">Alacritty</a> is a better targeted solution.</p>
<p>I need a terminal emulator to be fast, support color, ligatures, Tmux, and VIM
simultaneously and seamlessly. <a href="https://github.com/jwilm/alacritty">Alacritty</a> does all this very well.</p>
<p>If I notice terminal introduced latency then it is too slow, if I do not, then
it is fast enough. I use color to provide semantic clues. I expect at least
256 colors. Tmux and VIM should work together largely the way they work
separately. Ligatures require more explanation.</p>
<p>A ligature is a single character representation of a symbolic concept resulting
from the joining of two or more characters<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>. It is useful in some
programming languages to simplify the display of compound ASCII symbols.</p>
<p>Here are two ways to represent <code>not equal</code>.</p>
<dl>
<dt>Not Equal - ASCII</dt>
<dd>
<img src="/images/posts/alacritty/not-equal-ascii.png" width="30em" />
</dd>
<dt>Not Equal - Ligature</dt>
<dd>
<img src="/images/posts/alacritty/not-equal-lig.png" width="25em" />
</dd>
</dl>
<p>I use ligatures as a way to <em>display</em> symbols, comprised of multiple ASCII
characters, as a simpler rendering, without altering the actual source
characters. Here is an example from <a href="https://github.com/tonsky/FiraCode">Fira Code</a> that shows and
example of the ASCII saved in a file, on the right, and the ligature
representation displayed, on the left.</p>
<p><img
src="/images/posts/alacritty/ligatures.png"
alt="comparing original and ligature versions of Fira Font" width="100%"/></p>
<p>This enables me to view some characters as ligatures, but not to enforce my
preference on other users of a source file. I like having the control of when
to obscure the actual ASCII with ligatures. When I am editing a line, I like
to see the original ASCII on that line so I can see what I am editing. The
<a href="http://iterm2.com">iTerm2</a> update forced the display of ligatures all the time. The
<a href="http://iterm2.com">iTerm2</a> configuration for this feature was disabled.</p>
<figure>
<img src="/images/posts/alacritty/you-must-use-ligatures.png" title="Always display ligatures" alt="Always display ligatures" />
<figcaption aria-hidden="true">Always display ligatures</figcaption>
</figure>
<p>In order for me to control the expression of ligatures, I need the terminal
emulator to display the actual character. I use tools like
<a href="https://github.com/enomsg/vim-haskellConcealPlus">enomsg/vim-haskellConcealPlus</a>
to obscure the ASCII with ligatures when that is my preference.</p>
<p>Notice how some of the characters are displayed as ligatures even on the cursor
line. The cursor is narrow in the in the screen-shot but look at the character
just left of <code>liftIO</code>.</p>
<p><img src="/images/posts/alacritty/still-see-ligatures.png" title="Still see ligatures" /></p>
<h2 id="how">How</h2>
<p>Here is how I got <a href="https://github.com/jwilm/alacritty">Alacritty</a> working on my Mac (Sierra 10.12.x). If you do
not use Mac then your setup will be different.</p>
<h3 id="fonts">Fonts</h3>
<p>I am using two fonts, <a href="https://github.com/tonsky/FiraCode">Fira Code</a> and <code>Menlo</code>. I beleive that
<code>Menlo</code> ships with Mac, but <a href="https://github.com/tonsky/FiraCode">Fira Code</a> does not. Open <code>Font Book</code>
to ensure both are installed. To install <a href="https://github.com/tonsky/FiraCode">Fira Code</a>, simply follow
the instructions <a href="https://github.com/tonsky/FiraCode/wiki">here</a>. I just
downloaded the <a href="https://github.com/tonsky/FiraCode">Fira Code</a> fonts and installed them with <code>Font Book</code>, rather than using <code>homebrew</code>. Once installed you should see the
following in <code>Font Book</code>.</p>
<dl>
<dt>Fira Code</dt>
<dd>
<img src="/images/posts/alacritty/Font-Book-Fira-Code.png" title="Font Book - Fira Code" />
</dd>
<dt>Menlo</dt>
<dd>
<img src="/images/posts/alacritty/Font-Book-Menlo.png" title="Font Book - Menlo" />
</dd>
</dl>
<h3 id="tmux">Tmux</h3>
<p>Make sure Tmux is installed and reasonably updated. I found that the version
from homebrew did not work fully, so I uninstalled it and installed the
following from macports<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>.</p>
<ul>
<li><code>tmux</code> <span class="citation" data-cites="2.5_0">@2.5_0</span></li>
<li><code>tmux-pasteboard</code> <span class="citation" data-cites="2.6_0">@2.6_0</span></li>
</ul>
<p>I updated my <code>~/.tmux.conf</code> to change the default terminal identifier.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="bu">set</span> <span class="at">-g</span> default-terminal <span class="st">&quot;tmux-256color&quot;</span></span></code></pre></div>
<h3 id="alacritty"><a href="https://github.com/jwilm/alacritty">Alacritty</a></h3>
<p>Manually install <a href="https://github.com/jwilm/alacritty">Alacritty</a> as shown
<a href="https://github.com/jwilm/alacritty#manual-installation">here</a>, i.e. <strong><em>do not
use homebrew</em></strong>.</p>
<p>Edit the <code>.config/alacritty/alacritty.yml</code> configuration file.</p>
<h4 id="update-the-fonts">Update the fonts</h4>
<p>I am using <a href="https://github.com/tonsky/FiraCode">Fira Code</a> for <em>regular</em> and <em>bold</em> fonts. I am using
<code>Menlo</code> for <em>Italic</em>.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Font configuration (changes require restart)</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu">font</span><span class="kw">:</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co">  # The normal (roman) font face to use.</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">normal</span><span class="kw">:</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">family</span><span class="kw">:</span><span class="at"> Fira Code</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="co">    # Style can be specified to pick a specific face.</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">style</span><span class="kw">:</span><span class="at"> Regular</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="co">  # The bold font face</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">bold</span><span class="kw">:</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">family</span><span class="kw">:</span><span class="at"> Fira Code</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="co">    # Style can be specified to pick a specific face.</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">style</span><span class="kw">:</span><span class="at"> Bold</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="co">  # The italic font face</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">italic</span><span class="kw">:</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">family</span><span class="kw">:</span><span class="at"> Menlo</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="co">    # Style can be specified to pick a specific face.</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">style</span><span class="kw">:</span><span class="at"> Italic</span></span></code></pre></div>
<h4 id="misc">Misc</h4>
<p>The terminal setting should look like.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">TERM</span><span class="kw">:</span><span class="at"> xterm-256color</span></span></code></pre></div>
<p>Look over the rest of the config and ensure it matches your environment. I
also changed the <code>bash</code> used to the version installed in <code>/opt/local/bin</code>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">shell</span><span class="kw">:</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="at">   </span><span class="fu">program</span><span class="kw">:</span><span class="at"> /opt/local/bin/bash</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="at">   </span><span class="fu">args</span><span class="kw">:</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="at">      </span><span class="kw">-</span><span class="at"> --login</span></span></code></pre></div>
<p>The colors can be manually modified by providing the hex value.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">  # Normal colors</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">normal</span><span class="kw">:</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">black</span><span class="kw">:</span><span class="at">   </span><span class="st">&#39;0x000000&#39;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">red</span><span class="kw">:</span><span class="at">     </span><span class="st">&#39;0xd54e53&#39;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">green</span><span class="kw">:</span><span class="at">   </span><span class="st">&#39;0xb9ca4a&#39;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">yellow</span><span class="kw">:</span><span class="at">  </span><span class="st">&#39;0xe6c547&#39;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">blue</span><span class="kw">:</span><span class="at">    </span><span class="st">&#39;0x7aa6da&#39;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">magenta</span><span class="kw">:</span><span class="at"> </span><span class="st">&#39;0xc397d8&#39;</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">cyan</span><span class="kw">:</span><span class="at">    </span><span class="st">&#39;0x70c0ba&#39;</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="at">    </span><span class="fu">white</span><span class="kw">:</span><span class="at">   </span><span class="st">&#39;0xffffff&#39;</span></span></code></pre></div>
<p>If you are moving from another terminal emulator, like <code>iTerm2</code> you can view
the defined colors, for example from
<a href="http://iterm2colorschemes.com">iTerm2ColorSchemes.com</a>, and grab the hex value
with <code>Digital Color Meter</code>.</p>
<p>Open <code>Digital Color Meter</code> and then <code>menu</code>, <code>view</code>, <code>display values</code>, and
select <code>as hexadecimal</code>. Then fly over the color and then hit <code>Shift - Command - c</code>, to copy the hex value to the clipboard. Then from the clipboard, you can
paste them to the <code>.config/alacritty/alacritty.yml</code> configuration file for the
given color.</p>
<p>Also if you like the color schemes at
<a href="http://iterm2colorschemes">iTerm2ColorSchemes.com</a> you can find the scheme you
like and read the <code>termite</code> config in github.</p>
<p>If for example you like the
<a href="https://github.com/mbadolato/iTerm2-Color-Schemes#softserver">SoftServer</a>
scheme, you can view the hex values in
<a href="https://github.com/mbadolato/iTerm2-Color-Schemes/blob/master/termite/SoftServer">github.com/mbadolato/iTerm2-Color-Schemes/blob/master/termite/SoftServer</a>.
The <code>termite</code> config file looks like this.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode ini"><code class="sourceCode ini"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">[colors]</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="dt">background </span><span class="ot">=</span><span class="st"> #242626</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="dt">cursor </span><span class="ot">=</span><span class="st"> #d2e0de</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="dt">foreground </span><span class="ot">=</span><span class="st"> #99a3a2</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="dt">color0 </span><span class="ot">=</span><span class="st"> #000000</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="dt">color1 </span><span class="ot">=</span><span class="st"> #a2686a</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="dt">color2 </span><span class="ot">=</span><span class="st"> #9aa56a</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="dt">color3 </span><span class="ot">=</span><span class="st"> #a3906a</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="dt">color4 </span><span class="ot">=</span><span class="st"> #6b8fa3</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="dt">color5 </span><span class="ot">=</span><span class="st"> #6a71a3</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="dt">color6 </span><span class="ot">=</span><span class="st"> #6ba58f</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="dt">color7 </span><span class="ot">=</span><span class="st"> #99a3a2</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="dt">color8 </span><span class="ot">=</span><span class="st"> #666c6c</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="dt">color9 </span><span class="ot">=</span><span class="st"> #dd5c60</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="dt">color10 </span><span class="ot">=</span><span class="st"> #bfdf55</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="dt">color11 </span><span class="ot">=</span><span class="st"> #deb360</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="dt">color12 </span><span class="ot">=</span><span class="st"> #62b1df</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a><span class="dt">color13 </span><span class="ot">=</span><span class="st"> #606edf</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="dt">color14 </span><span class="ot">=</span><span class="st"> #64e39c</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="dt">color15 </span><span class="ot">=</span><span class="st"> #d2e0de</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a><span class="dt">colorBD </span><span class="ot">=</span><span class="st"> #d2e0de</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a><span class="dt">colorIT </span><span class="ot">=</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="dt">colorUL </span><span class="ot">=</span></span></code></pre></div>
<p>If manually editing is not your thing, there might be a color scheme that you can use.
<a href="https://github.com/arcticicestudio/nord-alacritty">Nord Alacritty</a> looks nice.</p>
<h3 id="man">Man</h3>
<p>I went ahead and added some color for Man pages also.</p>
<ul>
<li>Update <code>~.bashrc</code></li>
</ul>
<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># color for less and man </span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">MANPAGER</span><span class="op">=</span><span class="st">&#39;less -s -M +Gg&#39;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS</span><span class="op">=</span><span class="st">&quot;--RAW-CONTROL-CHARS&quot;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="va">lesscolors</span><span class="op">=</span><span class="va">$$</span>HOME/bin/.LESS_TERMCAP</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">[[</span> <span class="ot">-f</span> <span class="va">$$</span>lesscolors <span class="kw">]]</span> <span class="kw">&amp;&amp;</span> <span class="bu">.</span> <span class="va">$$</span>lesscolors</span></code></pre></div>
<ul>
<li>Create or edit <code>~/bin/.LESS_TERMCAP</code></li>
</ul>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_mb</span><span class="op">=</span><span class="va">$$(</span>tput bold<span class="er">;</span> tput setaf 2<span class="va">)</span> <span class="co"># green</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_md</span><span class="op">=</span><span class="va">$$(</span>tput bold<span class="er">;</span> tput setaf 6<span class="va">)</span> <span class="co"># cyan</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_me</span><span class="op">=</span><span class="va">$$(</span>tput sgr0<span class="va">)</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_so</span><span class="op">=</span><span class="va">$$(</span>tput bold<span class="er">;</span> tput setaf 3<span class="er">;</span> tput setab 4<span class="va">)</span> <span class="co"># yellow on blue</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_se</span><span class="op">=</span><span class="va">$$(</span>tput rmso<span class="er">;</span> tput sgr0<span class="va">)</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_us</span><span class="op">=</span><span class="va">$$(</span>tput smul<span class="er">;</span> tput bold<span class="er">;</span> tput setaf 7<span class="va">)</span> <span class="co"># white</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_ue</span><span class="op">=</span><span class="va">$$(</span>tput rmul<span class="er">;</span> tput sgr0<span class="va">)</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_mr</span><span class="op">=</span><span class="va">$$(</span>tput rev<span class="va">)</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_mh</span><span class="op">=</span><span class="va">$$(</span>tput dim<span class="va">)</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_ZN</span><span class="op">=</span><span class="va">$$(</span>tput ssubm<span class="va">)</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_ZV</span><span class="op">=</span><span class="va">$$(</span>tput rsubm<span class="va">)</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_ZO</span><span class="op">=</span><span class="va">$$(</span>tput ssupm<span class="va">)</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">LESS_TERMCAP_ZW</span><span class="op">=</span><span class="va">$$(</span>tput rsupm<span class="va">)</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">GROFF_NO_SGR</span><span class="op">=</span>1         </span></code></pre></div>
<h3 id="enjoy">Enjoy</h3>
<p>Here is are a few examples of the results.</p>
<h4 id="this-shows-the-way-i-use-ligatures.-also-note-the-italic-comments.">This shows the way I use ligatures. Also note the italic comments.</h4>
<p><img src="/images/posts/alacritty/correct-ligatures-and-italics-show-actual.png"
alt="Correct use of ligatures" width="100%" /></p>
<h4 id="here-is-a-man-page-using-color.">Here is a Man page using color.</h4>
<p><img src="/images/posts/alacritty/Ag-man-page.png" alt="Ag Man Page" width="100%"/></p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>This is a simplified definition. See a better one
<a href="https://en.wikipedia.org/wiki/Typographic_ligature">here</a>.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>If I recall correctly the macports version has a patch of some kind.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Tue, 24 Oct 2017 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/the-joy-of-alacritty/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>programming the KBParadise V60 polestar keyboard</title>
    <link>https://growingliberty.com/blog/programming-the-kbparadise-v60-polestar-keyboard/index.html</link>
    <description><![CDATA[<h2 id="kbparadise-v60-polestar-keyboard">KBParadise V60 Polestar Keyboard</h2>
<p>I recently purchased my first non-<a href="https://en.wikipedia.org/wiki/Model_M_keyboard">Model-M</a> mechanical
keyboard, the <a href="https://mechanicalkeyboards.com/shop/index.php?l=product_detail&amp;p=2528" title="KBParadise V60 Type R Polestar White LED 60% Mechanical Keyboard">KBParadise V60 polestar</a>.</p>
<dl>
<dt>Night</dt>
<dd>
<img src="/images/posts/keyboard/kbparadise-v60-mechanical-keyboard-1.jpg" class=""  alt="KBParadise V60 Polestar - Night" width="30%"/>
</dd>
<dt>Day</dt>
<dd>
<img src="/images/posts/keyboard/kbparadise-v60-mechanical-keyboard-2.jpg" class="" alt="KBParadise V60 Polestar - Day" width="30%"/>
</dd>
</dl>
<p>I like the 60% size, the feel of the cherry MX clear key switches, and the
customization potential from its <a href="https://www.microchip.com/wwwproducts/en/ATMEGA32U4" title="8-bit AVR® RISC-based microcontroller">ATMEGA32u4</a> microcontroller. The
original layout of the keyboard did not <!--more--> match the way I prefer
for use with a Mac or Linux system, but this can be easily changed. I am using
the U.S. layout, other layouts likely work similarly. The following
describes how to customize the keyboard from a Mac, for comfortable Mac use.</p>
<p>This is the layout defined by default for the keyboard. This layout shows two
layers with the first layer printed on the tops of the keys, the top legend,
and the second layer on the front. <img src="/images/posts/keyboard/original-layout.png"
alt="original keyboard layout" width="80%"/></p>
<p>The real difference is with the arrangement of the modifier keys. The important
modifiers being at the bottom left. Here is the default Mac layout from an
actual mac keyboard.</p>
<p><img src="/images/posts/keyboard/mac-keyboard.jpg" alt="mac keyboard layout" width="30%"/></p>
<dl>
<dt>Mac order</dt>
<dd>
<code>Ctrl</code>, <code>Option</code>/<code>Alt</code>, <code>Command</code>/<code>Win</code>
</dd>
<dt>Windows order</dt>
<dd>
<code>Ctrl</code>, <code>Command</code>/<code>Win</code>, <code>Option</code>/<code>Alt</code>
</dd>
</dl>
<h2 id="tools">Tools</h2>
<p>Updating the layout from my Mac was simple using a few freely available tools.</p>
<h3 id="tkg-toolkit"><a href="https://github.com/kairyu/tkg-toolkit" title="A collection of tools used for supporting TKG (TMK Keymap Generator)">tkg-toolkit</a></h3>
<p>The TKG toolkit is a selection of tools supporting the TMK Keymap Generator.
It is used to update the keyboard’s EEPROM and firmware. It should be possible
to program this keyboard using <a href="qmk.fm">Quantum Mechanical Keyboard Firmware</a>,
but at the time of writing this, the keyboard is not fully supported by
<a href="qmk.fm">qmk</a>.</p>
<h3 id="keyboard-layout-editor.com"><a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a></h3>
<p>The Keyboard Layout Editor makes it simple to define a layout by mapping key
locations to names.</p>
<h3 id="tmk-keymap-generator"><a href="https://kai.tkg.io">TMK Keymap Generator</a></h3>
<p>The TMK Keymap Generator converts a keymap string, such as produced by the
<a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a>, and generates a file that can be used to update
the keyboard’s EEPROM. This is then provided to <a href="https://github.com/kairyu/tkg-toolkit" title="A collection of tools used for supporting TKG (TMK Keymap Generator)">tkg-toolkit</a> to flash the
new layout.</p>
<h3 id="mac-keyboard-viewer">Mac Keyboard Viewer</h3>
<p>Mac OS X has a keyboard viewer that can be accessed by mouse or other pointing
device. This is helpful when keyboard input is required but the physical
keyboard is busy being updated.</p>
<h2 id="howto">Howto</h2>
<h3 id="tkg-toolkit-setup">tkg-toolkit setup</h3>
<p>Clone the <a href="https://github.com/kairyu/tkg-toolkit" title="A collection of tools used for supporting TKG (TMK Keymap Generator)">tkg-toolkit</a> git repository. The current version of the {{page.tkg-toolkit-link}} does not contain the firmware
for this keyboard, <code>fantastic60.hex</code>, as described in <a href="https://github.com/kairyu/tkg-toolkit/pull/12">this pull
request</a>. I added it to my local repository from
<a href="https://github.com/nminchow/tkg-toolkit/tree/master/common/firmware">here</a>.</p>
<p>The firmware hex file, <code>fantastic60.hex</code>, does not appear to be required if all you wish to do is update the EEPROM with a
new layout. I feel is it wise to keep a copy of the current firmware.</p>
<h4 id="use-git-to-clone-the-tkg-toolkit-repo">Use git to clone the tkg toolkit repo</h4>
<p>Execute the following from the command line.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">clone</span> git@github.com:kairyu/tkg-toolkit.git</span></code></pre></div>
<h4 id="ensure-that-libusb-compat-is-installed.">Ensure that <code>libusb-compat</code> is installed.</h4>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">brew</span> install libusb-compat</span></code></pre></div>
<h4 id="prepare-to-reflash.">Prepare to reflash.</h4>
<p>From the tk-toolkit repo, do the following.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> mac</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">./setup.sh</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="va">PATH</span><span class="op">=</span><span class="va">$$</span>PATH:<span class="va">$$</span><span class="kw">(</span><span class="bu">pwd</span><span class="kw">)</span><span class="ex">/bin</span></span></code></pre></div>
<p>During setup you will be prompted to select your keyboard. Select the option for <code>Fantastic60</code>. You will then be
prompted to select your bootloader. Select the option for <code>atmel_dfu</code>. The <code>setup.sh</code> script does two things. It
creates a <code>conf</code> directory then a configuration file named <code>default.ini</code>.</p>
<p>The <code>conf/default.ini</code> created by <code>setup.sh</code> should look like this.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="va">Name</span><span class="op">=</span><span class="st">&quot;Fantastic60&quot;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="va">MCU</span><span class="op">=</span>atmega32u4</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="va">Firmware</span><span class="op">=</span>fantastic60.hex</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="va">Bootloader</span><span class="op">=</span>atmel_dfu</span></code></pre></div>
<p>Setting the path with <code>PATH=$$PATH:$$(pwd)/bin</code> is temporary, so you would
either want to update your path differently or just execute this each time
before you re-flash.</p>
<h3 id="setup-alternate-keyboard">Setup Alternate keyboard</h3>
<p>Ensure that you can access the Mac Keyboard Viewer. On my system, the Keyboard
Viewer looks like this.</p>
<p><img src="/images/posts/keyboard/keyboard-viewer.png" alt="Example mac keyboard viewer" width="80%"></p>
<p>It should be possible to activate the keyboard viewer from one of these paths:</p>
<ul>
<li><a href="https://support.apple.com/kb/PH25242?locale=en_US">Apple menu &gt; System Preferences, click Keyboard, click Keyboard, then select “Show keyboard and emoji viewers in menu bar.”</a></li>
<li><a href="https://discussions.apple.com/thread/3326700?start=0&amp;tstart=0">System Preferences &gt; Language &amp; Text &gt; Input Sources &gt; Check the box “Keyboard &amp; Character Viewer.”</a></li>
</ul>
<h3 id="define-layouts">Define layouts</h3>
<p>This keyboard can have multiple layered layouts. The way this works is explained in the <a href="https://github.com/tmk/tmk_keyboard">TMK Keyboard Firmware
Collection</a>
<a href="https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/doc/keymap.md">here</a>. The keyboard shipped with two layers,
but as shown in <a href="https://www.youtube.com/mechmerlin">MechMerlin’s</a> video <a href="https://youtu.be/47G_m3M8P8I">here</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, I too
add a third layer.</p>
<p>Define a layout for each layer using <a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a>. Save the
layouts by saving the <code>raw data</code>. This can be done using the github
functionality provided in the <a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a> site, or manually
from the <code>raw data</code> tab.</p>
<p>The user manual describes the original layout. My customization includes three
layers, numbered zero through two, to match the numbering used by
[tkm-keymapgenerator-link][]. Higher numbered layers apply changes for mapped
keys and are transparent for un-mapped keys. By transparent I mean that if a
higher numbered layer does not define a mapping for a given key, then that key
will function as defined in the next lower numbered layer, with a mapping.</p>
<p>I created a public gist for the raw data and a link to load each layout into
the keyboard layout editor.</p>
<p><a name="table1"></a></p>
<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 44%" />
</colgroup>
<thead>
<tr>
<th>Layer</th>
<th>Links</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td><a href="https://gist.github.com/mmynsted/5aa5ad452d59f7e57ec2a036def3088d">raw data gist</a>, <a href="http://www.keyboard-layout-editor.com/#/gists/5aa5ad452d59f7e57ec2a036def3088d">load in page</a></td>
</tr>
<tr>
<td>1</td>
<td><a href="https://gist.github.com/mmynsted/e0b519c426c2c4a883bd940e272f0fd1">raw data gist</a>, <a href="http://www.keyboard-layout-editor.com/#/gists/e0b519c426c2c4a883bd940e272f0fd1">load in page</a></td>
</tr>
<tr>
<td>2</td>
<td><a href="https://gist.github.com/mmynsted/f7a70870789febbd4ffe87903411d3eb">raw data gist</a>, <a href="http://www.keyboard-layout-editor.com/#/gists/f7a70870789febbd4ffe87903411d3eb">load in page</a></td>
</tr>
</tbody>
</table>
<p>Each of the layers are defined against a <code>Default 60%</code> keyboard.</p>
<h4 id="layer-0">Layer 0</h4>
<p>The <em>first</em> layer is named layer <em>zero</em>. Here I have altered the order of the
meta keys on lower left and remapped the <code>caps-lock</code> key to the <code>esc</code> key. The
new meta key order matches the default for a mac keyboard. I also altered the
original <code>esc</code> key to produce the <code>`</code> and <code>~</code> characters.</p>
<p><img src="/images/posts/keyboard/layer0h.png" alt="layer zero keyboard layout" width="80%"></p>
<p>Make sure you save your customizations to <em>your</em> gist.</p>
<h4 id="layer-1">Layer 1</h4>
<p>The <em>second</em> layer, layer <em>one</em>, is modified to change the <code>space-bar</code> to
execute firmware function <code>Fn11</code>. The <code>Fn11</code> key is <strong><em>not</em></strong> the same as the
<code>F11</code> key. The <code>F11</code> key is a normal keyboard key. <code>F11</code> activation is passed
on to the operating system for interpretation, and in this layer, is still
mapped to the key that is <code>-</code> on layer zero. I added a few more normal
function keys to this layout in case they are actually used by the operating
system.</p>
<p>Notice that in this layer the <code>space-bar</code> key has been re-mapped to <code>Fn11</code>.</p>
<p><img src="/images/posts/keyboard/layer1.png" id="id" class="class" style="width:80.0%" alt="layer one keyboard layout" /><br />
</p>
<h4 id="layer-2">Layer 2</h4>
<p>Layer two will map only four keys.</p>
<h5 id="transparent-layout">Transparent layout</h5>
<p>{:.no_toc}</p>
<p>When there are few keys to map, it is easier to start from a fully transparent layout. I created such a layout. Its
gist is <a href="https://gist.github.com/mmynsted/344b28f5d97b6e82ab9c1db7d3e387aa">here</a> and can be loaded from
<a href="http://www.keyboard-layout-editor.com/#/gists/344b28f5d97b6e82ab9c1db7d3e387aa">here</a>.</p>
<p><img src="/images/posts/keyboard/blank.png" alt="transparent keyboard layout" width="80%"></p>
<h5 id="arrow-keys-defined-for-layer-2">Arrow keys defined for Layer 2</h5>
<p>{:.no_toc}</p>
<p>Here all the keys are transparent except the arrow keys defined in the lower
right corner.</p>
<p><img src="/images/posts/keyboard/layer2.png" alt="layer two keyboard layout" width="80%"></p>
<h3 id="make-a-keymap-with-tmk-keymap-generator">Make a keymap with <a href="https://kai.tkg.io">TMK Keymap Generator</a></h3>
<ul>
<li><p>Go to <a href="https://kai.tkg.io">TMK Keymap Generator</a>.</p></li>
<li><p>Select the <code>Fantastic60</code> keyboard.</p></li>
</ul>
<p><img src="/images/posts/keyboard/select-fantastic60-keyboard.png" alt="select the
fantastic60 keyboard"></p>
<ul>
<li><p>Select layer mode <code>Normal</code>.</p></li>
<li><p>Select <code>3</code> layers.</p></li>
<li><p>Paste each of the three layers we created above into their respective text area.</p></li>
</ul>
<p>You can paste the raw data or you can paste the <a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a>
links with the saved content. I have links for my layers in the table
<a href="#table1">here</a>. Your cursor must leave the text area in order for the URL to
be fetched and the data parsed. You might need to click on the page outside a
text area to trigger the action. You will be presented with errors and
warnings if applicable. I have found that errors typically mean that I have
pasted data incorrectly.</p>
<ul>
<li>Define the firmware functions.</li>
</ul>
<p>The mapping for the <code>Fn</code> keys should largely be the same as the default, but
with the addition of a toggle setting for <code>Fn11</code>. Note the action for <code>Fn0</code> and
<code>Fn11</code>. In both cases they are a toggle to a new layer as described
<a href="https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/doc/keymap.md#223-toggle-switch">here</a>.
This means that with each press and release of the key the active layer
changes. <code>Fn0</code> is being used to activate and deactivate layer one (the second
layer). <code>Fn11</code> is being used to likewise activate and deactivate layer two, the
third and final layer.</p>
<p><img src="/images/posts/keyboard/fn-mapping.png" alt="Fn mapping" width="80%"></p>
<ul>
<li>Click the <code>Download .eep file</code> button to download the <code>.eep</code> file.</li>
</ul>
<h3 id="flashing-the-keymap-to-eeprom">Flashing the keymap to EEPROM</h3>
<ul>
<li><p>Go back to the command line. You should be in your <code>tkg-toolkit</code> git repo in
the <code>mac</code> directory. You should be there from where you executed the setup
and updated the path above.</p></li>
<li><p>reflash the EEPROM and provide the path to your newly downloaded <code>.eep</code> file.
Where <code>./keymap.eep</code> is replaced with the actual path and file name for the
newly created <code>.eep</code> file.</p></li>
</ul>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./reflash.sh</span> ./keymap.eep</span></code></pre></div>
<p>You will be presented with a prompt asking if you want to continue.</p>
<ul>
<li><p>Open the keyboard viewer.</p></li>
<li><p>Turn over the keyboard you are flashing, and push the reset button, located
on the bottom of the keyboard.</p></li>
<li><p>Using the <strong><em>keyboard viewer</em></strong>, Type <code>Y</code> to answer the <code>continue</code> prompt.
Prevent the keyboard from being interrupted during the flashing process.</p></li>
<li><p>When the flashing process is complete, you will be prompted to press any key
to continue. Use the keyboard viewer to press any key.</p></li>
<li><p>Disconnect the keyboard from the USB cable, and then re-connect it. Now test
out each layer and ensure it is working the way you want.</p></li>
<li><p>You are done. Enjoy!</p></li>
</ul>
<h2 id="useful-links">Useful links</h2>
<ul>
<li><a href="https://dfu-programmer.github.io">dfu programmer</a></li>
<li><a href="http://qmk.fm">qmk</a></li>
<li><a href="https://docs.qmk.fm">QMK Firmware docs</a></li>
<li><a href="https://www.facebook.com/KBParadise">KBParadise</a></li>
<li><a href="https://www.microchip.com/wwwproducts/en/ATMEGA32U4" title="8-bit AVR® RISC-based microcontroller">ATMEGA32U4</a></li>
<li><a href="https://mechanicalkeyboards.com/shop/index.php?l=product_detail&amp;p=2528" title="KBParadise V60 Type R Polestar White LED 60% Mechanical Keyboard">KBParadise V60 polestar</a></li>
<li><a href="https://github.com/kairyu/tkg-toolkit" title="A collection of tools used for supporting TKG (TMK Keymap Generator)">tkg-toolkit</a></li>
<li><a href="http://www.keyboard-layout-editor.com">keyboard-layout-editor.com</a></li>
<li><a href="https://kai.tkg.io">TMK Keymap Generator</a></li>
<li><a href="https://youtu.be/47G_m3M8P8I">MechMerlin’s video for programming this keyboard from Windows</a></li>
<li><a href="https://youtu.be/MclO0cLKOj4">MechMerlin’s video reviewing this keyboard</a></li>
<li><a href="https://www.dropbox.com/sh/c1qvrzgagqj8wvg/AADeKPl9BdvUQ3R30m4CsQOga?dl=0">Programming Manual from KBParadise for the V60 Type R Keyboard</a></li>
<li><a href="https://brew.sh">Homebrew package manager</a></li>
</ul>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>The video shows, step by step, how to program this keyboard using
<a href="https://github.com/kairyu/tkg-toolkit" title="A collection of tools used for supporting TKG (TMK Keymap Generator)">tkg-toolkit</a> and the other tools listed above, on a Windows system. I
found his programming video and his <a href="https://youtu.be/MclO0cLKOj4">review</a> of
the keyboard to be quite helpful.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Mon, 07 Aug 2017 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/programming-the-kbparadise-v60-polestar-keyboard/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>scala notes number madness</title>
    <link>https://growingliberty.com/blog/scala-notes-number-madness/index.html</link>
    <description><![CDATA[<p>This is another article in the <a href="/tags/scala-notes/">scala-notes</a> series. This one
deals with what I call <strong>number madness</strong>.</p>
<h2 id="what">What!?</h2>
<p>Numbers are used everywhere in code, and often the type used is something like
<code>Int</code> (Scala) or <code>Integer</code>/<code>int</code> (Java). These simple types are familiar to
those of us who used languages like C but should not be used without
considering <!--more--> their inherent limitations. Let’s imagine an example
web application that during its normal operation records interesting events…</p>
<p>Imagine a field used to represent the key of a database table named
<code>INTERESTING_EVENT</code>, specifically an automatically incrementing surrogate key,
as is typical. (This is not the best example, in part because one would rarely
need perform arithmetic on a key value, but it is simple to explain.) Let’s say
that on average, only twenty <code>INTERESTING_EVENT</code> records are populated per
second.</p>
<p>Is an <code>Int</code> or <code>Integer</code> safe? Let’s get some perspective…</p>
<dl class="long">
<dt>
365 days per year
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='28.746487pt' height='8.201245pt' style='vertical-align: -0.251058pt' viewBox='.645579 -7.950187 28.746487 8.201245'>
<title>= 365</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.781613-2.044334C17.781613-3.144209 16.89693-4.004981 15.749234-4.208219C16.789334-4.507098 17.458823-5.379826 17.458823-6.312329C17.458823-7.256787 16.478499-7.950187 15.318848-7.950187C14.123331-7.950187 13.238649-7.220922 13.238649-6.348194C13.238649-5.869988 13.609259-5.774346 13.788587-5.774346C14.039645-5.774346 14.326569-5.953674 14.326569-6.312329C14.326569-6.694894 14.039645-6.862267 13.776631-6.862267C13.7049-6.862267 13.68099-6.862267 13.645125-6.850311C14.099421-7.663263 15.223207-7.663263 15.282983-7.663263C15.677503-7.663263 16.454589-7.483935 16.454589-6.312329C16.454589-6.085181 16.418724-5.415691 16.072024-4.901619C15.713369-4.375592 15.306893-4.339726 14.984103-4.327771L14.625448-4.291905C14.422211-4.27995 14.37439-4.267995 14.37439-4.160399C14.37439-4.040847 14.434166-4.040847 14.649359-4.040847H15.199296C16.215486-4.040847 16.669782-3.203985 16.669782-2.056289C16.669782-.490162 15.856831-.071731 15.271028-.071731C14.697179-.071731 13.716856-.3467 13.370156-1.135741C13.752721-1.075965 14.099421-1.291158 14.099421-1.721544C14.099421-2.068244 13.848362-2.307347 13.513618-2.307347C13.226694-2.307347 12.915859-2.139975 12.915859-1.685679C12.915859-.621669 13.979869 .251059 15.306893 .251059C16.729558 .251059 17.781613-.836862 17.781613-2.044334Z'/>
<path d='M23.63466-2.438854C23.63466-4.028892 22.522829-5.092902 21.327313-5.092902C20.263303-5.092902 19.868782-4.172354 19.74923-3.837609V-4.160399C19.74923-7.185056 21.219716-7.663263 21.865295-7.663263C22.295681-7.663263 22.726067-7.531756 22.953215-7.173101C22.809753-7.173101 22.355457-7.173101 22.355457-6.682939C22.355457-6.419925 22.534785-6.192777 22.845619-6.192777C23.144498-6.192777 23.347736-6.372105 23.347736-6.718804C23.347736-7.340473 22.89344-7.950187 21.85334-7.950187C20.346989-7.950187 18.768907-6.40797 18.768907-3.777833C18.768907-.490162 20.203527 .251059 21.219716 .251059C22.522829 .251059 23.63466-.884682 23.63466-2.438854ZM22.654336-2.450809C22.654336-1.841096 22.654336-1.303113 22.427188-.848817C22.128309-.274969 21.697923-.071731 21.219716-.071731C20.466541-.071731 20.107885-.74122 20.000289-.992279C19.892692-1.303113 19.773141-1.888917 19.773141-2.725778C19.773141-3.670237 20.203527-4.853798 21.279492-4.853798C21.937026-4.853798 22.283726-4.411457 22.463054-4.004981C22.654336-3.56264 22.654336-2.964882 22.654336-2.450809Z'/>
<path d='M29.392066-2.402989C29.392066-3.825654 28.435653-5.009215 27.18036-5.009215C26.498915-5.009215 25.972888-4.710336 25.662054-4.375592V-6.850311C26.176126-6.682939 26.594557-6.670984 26.726063-6.670984C28.076997-6.670984 28.93777-7.663263 28.93777-7.830635C28.93777-7.878456 28.913859-7.938232 28.842128-7.938232C28.842128-7.938232 28.794308-7.938232 28.686711-7.890411C28.017222-7.603487 27.443374-7.567621 27.132539-7.567621C26.343498-7.567621 25.781605-7.806725 25.554457-7.902366C25.470771-7.938232 25.434905-7.938232 25.434905-7.938232C25.339264-7.938232 25.339264-7.866501 25.339264-7.675218V-4.124533C25.339264-3.90934 25.339264-3.837609 25.482726-3.837609C25.542502-3.837609 25.554457-3.849564 25.674009-3.993026C26.008753-4.483188 26.570646-4.770112 27.168405-4.770112C27.802029-4.770112 28.112863-4.184309 28.208504-3.981071C28.411742-3.514819 28.423697-2.929016 28.423697-2.47472S28.423697-1.338979 28.088953-.800996C27.825939-.37061 27.359687-.071731 26.83366-.071731C26.044619-.071731 25.267533-.609714 25.05234-1.482441C25.112116-1.458531 25.183847-1.446575 25.243623-1.446575C25.44686-1.446575 25.76965-1.566127 25.76965-1.972603C25.76965-2.307347 25.542502-2.49863 25.243623-2.49863C25.02843-2.49863 24.717595-2.391034 24.717595-1.924782C24.717595-.908593 25.530547 .251059 26.85757 .251059C28.208504 .251059 29.392066-.884682 29.392066-2.402989Z'/>
</g>
</svg>
</dd>
<dt>
8760 hours per year
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='49.086799pt' height='8.320797pt' style='vertical-align: -0.251059pt' viewBox='.645579 -8.069738 49.086799 8.320797'>
<title>= 24 \cdot 365</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.685971-2.008468H17.422958C17.387092-1.80523 17.291451-1.147696 17.171899-.956413C17.088213-.848817 16.406768-.848817 16.048113-.848817H13.836407C14.159197-1.123786 14.888462-1.888917 15.199296-2.175841C17.016482-3.849564 17.685971-4.471233 17.685971-5.654795C17.685971-7.029639 16.598051-7.950187 15.211252-7.950187S13.011501-6.766625 13.011501-5.738481C13.011501-5.128767 13.537528-5.128767 13.573394-5.128767C13.824452-5.128767 14.135287-5.308095 14.135287-5.69066C14.135287-6.025405 13.908138-6.252553 13.573394-6.252553C13.465797-6.252553 13.441887-6.252553 13.406021-6.240598C13.633169-7.053549 14.278749-7.603487 15.055834-7.603487C16.072024-7.603487 16.693693-6.75467 16.693693-5.654795C16.693693-4.638605 16.107889-3.753923 15.426445-2.988792L13.011501-.286924V0H17.375137L17.685971-2.008468Z'/>
<path d='M23.802032-1.996513V-2.343213H22.59456V-7.782814C22.59456-8.009963 22.59456-8.069738 22.427188-8.069738C22.331547-8.069738 22.295681-8.069738 22.20004-7.926276L18.601534-2.343213V-1.996513H21.745744V-.908593C21.745744-.466252 21.721833-.3467 20.849106-.3467H20.610003V0C20.884971-.02391 21.82943-.02391 22.164174-.02391S23.455333-.02391 23.730301 0V-.3467H23.491198C22.630426-.3467 22.59456-.466252 22.59456-.908593V-1.996513H23.802032ZM21.805519-2.343213H18.900413L21.805519-6.850311V-2.343213Z'/>
<path d='M29.083848-2.988792C29.083848-3.335492 28.796924-3.622416 28.450224-3.622416S27.8166-3.335492 27.8166-2.988792S28.103524-2.355168 28.450224-2.355168S29.083848-2.642092 29.083848-2.988792Z'/>
<path d='M38.121924-2.044334C38.121924-3.144209 37.237242-4.004981 36.089546-4.208219C37.129646-4.507098 37.799135-5.379826 37.799135-6.312329C37.799135-7.256787 36.818811-7.950187 35.65916-7.950187C34.463643-7.950187 33.578961-7.220922 33.578961-6.348194C33.578961-5.869988 33.949571-5.774346 34.128898-5.774346C34.379957-5.774346 34.666881-5.953674 34.666881-6.312329C34.666881-6.694894 34.379957-6.862267 34.116943-6.862267C34.045212-6.862267 34.021302-6.862267 33.985436-6.850311C34.439733-7.663263 35.563518-7.663263 35.623294-7.663263C36.017815-7.663263 36.794901-7.483935 36.794901-6.312329C36.794901-6.085181 36.759035-5.415691 36.412335-4.901619C36.05368-4.375592 35.647205-4.339726 35.324415-4.327771L34.96576-4.291905C34.762522-4.27995 34.714702-4.267995 34.714702-4.160399C34.714702-4.040847 34.774477-4.040847 34.98967-4.040847H35.539608C36.555797-4.040847 37.010094-3.203985 37.010094-2.056289C37.010094-.490162 36.197142-.071731 35.611339-.071731C35.037491-.071731 34.057167-.3467 33.710467-1.135741C34.093033-1.075965 34.439733-1.291158 34.439733-1.721544C34.439733-2.068244 34.188674-2.307347 33.853929-2.307347C33.567005-2.307347 33.256171-2.139975 33.256171-1.685679C33.256171-.621669 34.320181 .251059 35.647205 .251059C37.06987 .251059 38.121924-.836862 38.121924-2.044334Z'/>
<path d='M43.974972-2.438854C43.974972-4.028892 42.863141-5.092902 41.667624-5.092902C40.603614-5.092902 40.209094-4.172354 40.089542-3.837609V-4.160399C40.089542-7.185056 41.560028-7.663263 42.205607-7.663263C42.635993-7.663263 43.066379-7.531756 43.293527-7.173101C43.150065-7.173101 42.695769-7.173101 42.695769-6.682939C42.695769-6.419925 42.875096-6.192777 43.185931-6.192777C43.48481-6.192777 43.688048-6.372105 43.688048-6.718804C43.688048-7.340473 43.233751-7.950187 42.193652-7.950187C40.6873-7.950187 39.109218-6.40797 39.109218-3.777833C39.109218-.490162 40.543838 .251059 41.560028 .251059C42.863141 .251059 43.974972-.884682 43.974972-2.438854ZM42.994648-2.450809C42.994648-1.841096 42.994648-1.303113 42.7675-.848817C42.468621-.274969 42.038234-.071731 41.560028-.071731C40.806852-.071731 40.448197-.74122 40.340601-.992279C40.233004-1.303113 40.113452-1.888917 40.113452-2.725778C40.113452-3.670237 40.543838-4.853798 41.619804-4.853798C42.277338-4.853798 42.624038-4.411457 42.803365-4.004981C42.994648-3.56264 42.994648-2.964882 42.994648-2.450809Z'/>
<path d='M49.732378-2.402989C49.732378-3.825654 48.775964-5.009215 47.520672-5.009215C46.839227-5.009215 46.3132-4.710336 46.002365-4.375592V-6.850311C46.516437-6.682939 46.934868-6.670984 47.066375-6.670984C48.417309-6.670984 49.278081-7.663263 49.278081-7.830635C49.278081-7.878456 49.254171-7.938232 49.18244-7.938232C49.18244-7.938232 49.134619-7.938232 49.027023-7.890411C48.357533-7.603487 47.783685-7.567621 47.472851-7.567621C46.68381-7.567621 46.121917-7.806725 45.894769-7.902366C45.811082-7.938232 45.775217-7.938232 45.775217-7.938232C45.679576-7.938232 45.679576-7.866501 45.679576-7.675218V-4.124533C45.679576-3.90934 45.679576-3.837609 45.823038-3.837609C45.882814-3.837609 45.894769-3.849564 46.01432-3.993026C46.349065-4.483188 46.910958-4.770112 47.508716-4.770112C48.14234-4.770112 48.453175-4.184309 48.548816-3.981071C48.752054-3.514819 48.764009-2.929016 48.764009-2.47472S48.764009-1.338979 48.429264-.800996C48.166251-.37061 47.699999-.071731 47.173972-.071731C46.384931-.071731 45.607845-.609714 45.392652-1.482441C45.452427-1.458531 45.524158-1.446575 45.583934-1.446575C45.787172-1.446575 46.109962-1.566127 46.109962-1.972603C46.109962-2.307347 45.882814-2.49863 45.583934-2.49863C45.368741-2.49863 45.057907-2.391034 45.057907-1.924782C45.057907-.908593 45.870858 .251059 47.197882 .251059C48.548816 .251059 49.732378-.884682 49.732378-2.402989Z'/>
</g>
</svg>
</dd>
<dt>
525,600 minutes per year
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='55.035487pt' height='8.332752pt' style='vertical-align: -0.251058pt' viewBox='.645579 -8.081694 55.035487 8.332752'>
<title>= 60 \cdot 8760</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.781613-2.438854C17.781613-4.028892 16.669782-5.092902 15.474265-5.092902C14.410255-5.092902 14.015735-4.172354 13.896183-3.837609V-4.160399C13.896183-7.185056 15.366669-7.663263 16.012248-7.663263C16.442634-7.663263 16.87302-7.531756 17.100168-7.173101C16.956706-7.173101 16.50241-7.173101 16.50241-6.682939C16.50241-6.419925 16.681737-6.192777 16.992572-6.192777C17.291451-6.192777 17.494689-6.372105 17.494689-6.718804C17.494689-7.340473 17.040392-7.950187 16.000293-7.950187C14.493942-7.950187 12.915859-6.40797 12.915859-3.777833C12.915859-.490162 14.35048 .251059 15.366669 .251059C16.669782 .251059 17.781613-.884682 17.781613-2.438854ZM16.801289-2.450809C16.801289-1.841096 16.801289-1.303113 16.574141-.848817C16.275262-.274969 15.844876-.071731 15.366669-.071731C14.613493-.071731 14.254838-.74122 14.147242-.992279C14.039645-1.303113 13.920094-1.888917 13.920094-2.725778C13.920094-3.670237 14.35048-4.853798 15.426445-4.853798C16.083979-4.853798 16.430679-4.411457 16.610006-4.004981C16.801289-3.56264 16.801289-2.964882 16.801289-2.450809Z'/>
<path d='M23.63466-3.825654C23.63466-4.817933 23.574884-5.786301 23.144498-6.694894C22.654336-7.687173 21.793564-7.950187 21.207761-7.950187C20.514361-7.950187 19.665544-7.603487 19.223203-6.611208C18.888458-5.858032 18.768907-5.116812 18.768907-3.825654C18.768907-2.666002 18.852593-1.793275 19.282979-.944458C19.74923-.035866 20.574137 .251059 21.195806 .251059C22.235905 .251059 22.833664-.37061 23.180364-1.06401C23.61075-1.960648 23.63466-3.132254 23.63466-3.825654ZM22.726067-3.969116C22.726067-3.16812 22.726067-2.259527 22.59456-1.530262C22.367412-.215193 21.614237 .011955 21.195806 .011955C20.81324 .011955 20.036154-.203238 19.809006-1.506351C19.677499-2.223661 19.677499-3.132254 19.677499-3.969116C19.677499-4.94944 19.677499-5.834122 19.868782-6.539477C20.07202-7.340473 20.681734-7.711083 21.195806-7.711083C21.650102-7.711083 22.343502-7.436115 22.57065-6.40797C22.726067-5.726526 22.726067-4.782067 22.726067-3.969116Z'/>
<path d='M29.083848-2.988792C29.083848-3.335492 28.796924-3.622416 28.450224-3.622416S27.8166-3.335492 27.8166-2.988792S28.103524-2.355168 28.450224-2.355168S29.083848-2.642092 29.083848-2.988792Z'/>
<path d='M38.121924-1.984558C38.121924-3.203985 37.261152-3.741968 36.328649-4.315816C36.926408-4.638605 37.799135-5.188543 37.799135-6.192777C37.799135-7.232877 36.794901-7.950187 35.695025-7.950187C34.511464-7.950187 33.578961-7.07746 33.578961-5.989539C33.578961-5.583064 33.698512-5.176588 34.033257-4.770112C34.164764-4.614695 34.176719-4.60274 35.013581-4.016936C33.853929-3.478954 33.256171-2.677958 33.256171-1.80523C33.256171-.537983 34.463643 .251059 35.68307 .251059C37.010094 .251059 38.121924-.729265 38.121924-1.984558ZM37.308973-6.180822C37.308973-5.451557 36.782946-4.865753 36.089546-4.483188L34.702746-5.391781C34.547329-5.499377 34.069122-5.810212 34.069122-6.396015C34.069122-7.173101 34.882074-7.663263 35.68307-7.663263C36.543842-7.663263 37.308973-7.041594 37.308973-6.180822ZM37.571987-1.601993C37.571987-.6934 36.651439-.071731 35.695025-.071731C34.678836-.071731 33.806109-.812951 33.806109-1.80523C33.806109-2.737733 34.487553-3.490909 35.264639-3.849564L36.711215-2.905106C37.022049-2.701868 37.571987-2.331258 37.571987-1.601993Z'/>
<path d='M44.297761-7.424159V-7.699128H41.416566C39.96999-7.699128 39.94608-7.854545 39.898259-8.081694H39.635246L39.264635-5.69066H39.527649C39.563515-5.905853 39.671111-6.647073 39.826528-6.77858C39.92217-6.850311 40.818807-6.850311 40.98618-6.850311H43.520675L42.253428-5.033126C41.930638-4.566874 40.723166-2.606227 40.723166-.358655C40.723166-.227148 40.723166 .251059 41.213328 .251059C41.715445 .251059 41.715445-.215193 41.715445-.37061V-.968369C41.715445-2.749689 42.002369-4.136488 42.564262-4.937484L44.297761-7.424159Z'/>
<path d='M49.828019-2.438854C49.828019-4.028892 48.716188-5.092902 47.520672-5.092902C46.456662-5.092902 46.062141-4.172354 45.942589-3.837609V-4.160399C45.942589-7.185056 47.413075-7.663263 48.058654-7.663263C48.48904-7.663263 48.919426-7.531756 49.146574-7.173101C49.003112-7.173101 48.548816-7.173101 48.548816-6.682939C48.548816-6.419925 48.728144-6.192777 49.038978-6.192777C49.337857-6.192777 49.541095-6.372105 49.541095-6.718804C49.541095-7.340473 49.086799-7.950187 48.046699-7.950187C46.540348-7.950187 44.962266-6.40797 44.962266-3.777833C44.962266-.490162 46.396886 .251059 47.413075 .251059C48.716188 .251059 49.828019-.884682 49.828019-2.438854ZM48.847695-2.450809C48.847695-1.841096 48.847695-1.303113 48.620547-.848817C48.321668-.274969 47.891282-.071731 47.413075-.071731C46.659899-.071731 46.301244-.74122 46.193648-.992279C46.086051-1.303113 45.9665-1.888917 45.9665-2.725778C45.9665-3.670237 46.396886-4.853798 47.472851-4.853798C48.130385-4.853798 48.477085-4.411457 48.656413-4.004981C48.847695-3.56264 48.847695-2.964882 48.847695-2.450809Z'/>
<path d='M55.681066-3.825654C55.681066-4.817933 55.62129-5.786301 55.190904-6.694894C54.700742-7.687173 53.83997-7.950187 53.254167-7.950187C52.560767-7.950187 51.71195-7.603487 51.269609-6.611208C50.934864-5.858032 50.815313-5.116812 50.815313-3.825654C50.815313-2.666002 50.898999-1.793275 51.329385-.944458C51.795637-.035866 52.620543 .251059 53.242212 .251059C54.282312 .251059 54.88007-.37061 55.22677-1.06401C55.657156-1.960648 55.681066-3.132254 55.681066-3.825654ZM54.772473-3.969116C54.772473-3.16812 54.772473-2.259527 54.640967-1.530262C54.413818-.215193 53.660643 .011955 53.242212 .011955C52.859647 .011955 52.082561-.203238 51.855412-1.506351C51.723906-2.223661 51.723906-3.132254 51.723906-3.969116C51.723906-4.94944 51.723906-5.834122 51.915188-6.539477C52.118426-7.340473 52.72814-7.711083 53.242212-7.711083C53.696508-7.711083 54.389908-7.436115 54.617056-6.40797C54.772473-5.726526 54.772473-4.782067 54.772473-3.969116Z'/>
</g>
</svg>
</dd>
<dt>
31,536,000 seconds per year
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='71.985741pt' height='10.257534pt' style='vertical-align: -2.307347pt' viewBox='.645579 -7.950187 71.985741 10.257534'>
<title>= 60 \cdot 525,600</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.781613-2.438854C17.781613-4.028892 16.669782-5.092902 15.474265-5.092902C14.410255-5.092902 14.015735-4.172354 13.896183-3.837609V-4.160399C13.896183-7.185056 15.366669-7.663263 16.012248-7.663263C16.442634-7.663263 16.87302-7.531756 17.100168-7.173101C16.956706-7.173101 16.50241-7.173101 16.50241-6.682939C16.50241-6.419925 16.681737-6.192777 16.992572-6.192777C17.291451-6.192777 17.494689-6.372105 17.494689-6.718804C17.494689-7.340473 17.040392-7.950187 16.000293-7.950187C14.493942-7.950187 12.915859-6.40797 12.915859-3.777833C12.915859-.490162 14.35048 .251059 15.366669 .251059C16.669782 .251059 17.781613-.884682 17.781613-2.438854ZM16.801289-2.450809C16.801289-1.841096 16.801289-1.303113 16.574141-.848817C16.275262-.274969 15.844876-.071731 15.366669-.071731C14.613493-.071731 14.254838-.74122 14.147242-.992279C14.039645-1.303113 13.920094-1.888917 13.920094-2.725778C13.920094-3.670237 14.35048-4.853798 15.426445-4.853798C16.083979-4.853798 16.430679-4.411457 16.610006-4.004981C16.801289-3.56264 16.801289-2.964882 16.801289-2.450809Z'/>
<path d='M23.63466-3.825654C23.63466-4.817933 23.574884-5.786301 23.144498-6.694894C22.654336-7.687173 21.793564-7.950187 21.207761-7.950187C20.514361-7.950187 19.665544-7.603487 19.223203-6.611208C18.888458-5.858032 18.768907-5.116812 18.768907-3.825654C18.768907-2.666002 18.852593-1.793275 19.282979-.944458C19.74923-.035866 20.574137 .251059 21.195806 .251059C22.235905 .251059 22.833664-.37061 23.180364-1.06401C23.61075-1.960648 23.63466-3.132254 23.63466-3.825654ZM22.726067-3.969116C22.726067-3.16812 22.726067-2.259527 22.59456-1.530262C22.367412-.215193 21.614237 .011955 21.195806 .011955C20.81324 .011955 20.036154-.203238 19.809006-1.506351C19.677499-2.223661 19.677499-3.132254 19.677499-3.969116C19.677499-4.94944 19.677499-5.834122 19.868782-6.539477C20.07202-7.340473 20.681734-7.711083 21.195806-7.711083C21.650102-7.711083 22.343502-7.436115 22.57065-6.40797C22.726067-5.726526 22.726067-4.782067 22.726067-3.969116Z'/>
<path d='M29.083848-2.988792C29.083848-3.335492 28.796924-3.622416 28.450224-3.622416S27.8166-3.335492 27.8166-2.988792S28.103524-2.355168 28.450224-2.355168S29.083848-2.642092 29.083848-2.988792Z'/>
<path d='M38.026283-2.402989C38.026283-3.825654 37.06987-5.009215 35.814577-5.009215C35.133132-5.009215 34.607105-4.710336 34.296271-4.375592V-6.850311C34.810343-6.682939 35.228774-6.670984 35.360281-6.670984C36.711215-6.670984 37.571987-7.663263 37.571987-7.830635C37.571987-7.878456 37.548076-7.938232 37.476345-7.938232C37.476345-7.938232 37.428525-7.938232 37.320928-7.890411C36.651439-7.603487 36.077591-7.567621 35.766756-7.567621C34.977715-7.567621 34.415822-7.806725 34.188674-7.902366C34.104988-7.938232 34.069122-7.938232 34.069122-7.938232C33.973481-7.938232 33.973481-7.866501 33.973481-7.675218V-4.124533C33.973481-3.90934 33.973481-3.837609 34.116943-3.837609C34.176719-3.837609 34.188674-3.849564 34.308226-3.993026C34.642971-4.483188 35.204863-4.770112 35.802622-4.770112C36.436246-4.770112 36.74708-4.184309 36.842721-3.981071C37.045959-3.514819 37.057915-2.929016 37.057915-2.47472S37.057915-1.338979 36.72317-.800996C36.460156-.37061 35.993905-.071731 35.467877-.071731C34.678836-.071731 33.90175-.609714 33.686557-1.482441C33.746333-1.458531 33.818064-1.446575 33.87784-1.446575C34.081078-1.446575 34.403867-1.566127 34.403867-1.972603C34.403867-2.307347 34.176719-2.49863 33.87784-2.49863C33.662647-2.49863 33.351812-2.391034 33.351812-1.924782C33.351812-.908593 34.164764 .251059 35.491787 .251059C36.842721 .251059 38.026283-.884682 38.026283-2.402989Z'/>
<path d='M43.87933-2.008468H43.616317C43.580451-1.80523 43.48481-1.147696 43.365258-.956413C43.281572-.848817 42.600127-.848817 42.241472-.848817H40.029766C40.352556-1.123786 41.081821-1.888917 41.392655-2.175841C43.209841-3.849564 43.87933-4.471233 43.87933-5.654795C43.87933-7.029639 42.79141-7.950187 41.404611-7.950187S39.20486-6.766625 39.20486-5.738481C39.20486-5.128767 39.730887-5.128767 39.766753-5.128767C40.017811-5.128767 40.328645-5.308095 40.328645-5.69066C40.328645-6.025405 40.101497-6.252553 39.766753-6.252553C39.659156-6.252553 39.635246-6.252553 39.59938-6.240598C39.826528-7.053549 40.472107-7.603487 41.249193-7.603487C42.265383-7.603487 42.887051-6.75467 42.887051-5.654795C42.887051-4.638605 42.301248-3.753923 41.619804-2.988792L39.20486-.286924V0H43.568496L43.87933-2.008468Z'/>
<path d='M49.732378-2.402989C49.732378-3.825654 48.775964-5.009215 47.520672-5.009215C46.839227-5.009215 46.3132-4.710336 46.002365-4.375592V-6.850311C46.516437-6.682939 46.934868-6.670984 47.066375-6.670984C48.417309-6.670984 49.278081-7.663263 49.278081-7.830635C49.278081-7.878456 49.254171-7.938232 49.18244-7.938232C49.18244-7.938232 49.134619-7.938232 49.027023-7.890411C48.357533-7.603487 47.783685-7.567621 47.472851-7.567621C46.68381-7.567621 46.121917-7.806725 45.894769-7.902366C45.811082-7.938232 45.775217-7.938232 45.775217-7.938232C45.679576-7.938232 45.679576-7.866501 45.679576-7.675218V-4.124533C45.679576-3.90934 45.679576-3.837609 45.823038-3.837609C45.882814-3.837609 45.894769-3.849564 46.01432-3.993026C46.349065-4.483188 46.910958-4.770112 47.508716-4.770112C48.14234-4.770112 48.453175-4.184309 48.548816-3.981071C48.752054-3.514819 48.764009-2.929016 48.764009-2.47472S48.764009-1.338979 48.429264-.800996C48.166251-.37061 47.699999-.071731 47.173972-.071731C46.384931-.071731 45.607845-.609714 45.392652-1.482441C45.452427-1.458531 45.524158-1.446575 45.583934-1.446575C45.787172-1.446575 46.109962-1.566127 46.109962-1.972603C46.109962-2.307347 45.882814-2.49863 45.583934-2.49863C45.368741-2.49863 45.057907-2.391034 45.057907-1.924782C45.057907-.908593 45.870858 .251059 47.197882 .251059C48.548816 .251059 49.732378-.884682 49.732378-2.402989Z'/>
<path d='M52.656409 .047821C52.656409-.645579 52.429261-1.159651 51.939099-1.159651C51.556533-1.159651 51.365251-.848817 51.365251-.585803S51.544578 0 51.951054 0C52.106471 0 52.237978-.047821 52.345574-.155417C52.369485-.179328 52.393395-.179328 52.393395-.179328S52.417305-.011955 52.417305 .047821C52.417305 .442341 52.345574 1.219427 51.652175 1.996513C51.520668 2.139975 51.520668 2.187796 51.520668 2.187796C51.520668 2.247572 51.580444 2.307347 51.640219 2.307347C51.735861 2.307347 52.656409 1.422665 52.656409 .047821Z'/>
<path d='M60.925225-2.438854C60.925225-4.028892 59.813394-5.092902 58.617878-5.092902C57.553868-5.092902 57.159347-4.172354 57.039795-3.837609V-4.160399C57.039795-7.185056 58.510281-7.663263 59.15586-7.663263C59.586246-7.663263 60.016632-7.531756 60.243781-7.173101C60.100319-7.173101 59.646022-7.173101 59.646022-6.682939C59.646022-6.419925 59.82535-6.192777 60.136184-6.192777C60.435063-6.192777 60.638301-6.372105 60.638301-6.718804C60.638301-7.340473 60.184005-7.950187 59.143905-7.950187C57.637554-7.950187 56.059472-6.40797 56.059472-3.777833C56.059472-.490162 57.494092 .251059 58.510281 .251059C59.813394 .251059 60.925225-.884682 60.925225-2.438854ZM59.944901-2.450809C59.944901-1.841096 59.944901-1.303113 59.717753-.848817C59.418874-.274969 58.988488-.071731 58.510281-.071731C57.757106-.071731 57.398451-.74122 57.290854-.992279C57.183257-1.303113 57.063706-1.888917 57.063706-2.725778C57.063706-3.670237 57.494092-4.853798 58.570057-4.853798C59.227591-4.853798 59.574291-4.411457 59.753619-4.004981C59.944901-3.56264 59.944901-2.964882 59.944901-2.450809Z'/>
<path d='M66.778272-3.825654C66.778272-4.817933 66.718497-5.786301 66.28811-6.694894C65.797949-7.687173 64.937176-7.950187 64.351373-7.950187C63.657973-7.950187 62.809157-7.603487 62.366815-6.611208C62.032071-5.858032 61.912519-5.116812 61.912519-3.825654C61.912519-2.666002 61.996205-1.793275 62.426591-.944458C62.892843-.035866 63.717749 .251059 64.339418 .251059C65.379518 .251059 65.977276-.37061 66.323976-1.06401C66.754362-1.960648 66.778272-3.132254 66.778272-3.825654ZM65.86968-3.969116C65.86968-3.16812 65.86968-2.259527 65.738173-1.530262C65.511025-.215193 64.757849 .011955 64.339418 .011955C63.956853 .011955 63.179767-.203238 62.952619-1.506351C62.821112-2.223661 62.821112-3.132254 62.821112-3.969116C62.821112-4.94944 62.821112-5.834122 63.012394-6.539477C63.215632-7.340473 63.825346-7.711083 64.339418-7.711083C64.793714-7.711083 65.487114-7.436115 65.714262-6.40797C65.86968-5.726526 65.86968-4.782067 65.86968-3.969116Z'/>
<path d='M72.63132-3.825654C72.63132-4.817933 72.571544-5.786301 72.141158-6.694894C71.650996-7.687173 70.790224-7.950187 70.20442-7.950187C69.511021-7.950187 68.662204-7.603487 68.219863-6.611208C67.885118-5.858032 67.765566-5.116812 67.765566-3.825654C67.765566-2.666002 67.849252-1.793275 68.279638-.944458C68.74589-.035866 69.570797 .251059 70.192465 .251059C71.232565 .251059 71.830323-.37061 72.177023-1.06401C72.607409-1.960648 72.63132-3.132254 72.63132-3.825654ZM71.722727-3.969116C71.722727-3.16812 71.722727-2.259527 71.59122-1.530262C71.364072-.215193 70.610896 .011955 70.192465 .011955C69.8099 .011955 69.032814-.203238 68.805666-1.506351C68.674159-2.223661 68.674159-3.132254 68.674159-3.969116C68.674159-4.94944 68.674159-5.834122 68.865442-6.539477C69.06868-7.340473 69.678393-7.711083 70.192465-7.711083C70.646762-7.711083 71.340161-7.436115 71.56731-6.40797C71.722727-5.726526 71.722727-4.782067 71.722727-3.969116Z'/>
</g>
</svg>
</dd>
</dl>
<p>Given a liner expansion of the <code>INTERESTING_EVENT</code> sequence, by twenty each
second, the value would grow by 630,720,000 each year.</p>
<dl class="long">
<dt>
630,720,000 events per year
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='88.935994pt' height='10.257534pt' style='vertical-align: -2.307347pt' viewBox='.645579 -7.950187 88.935994 10.257534'>
<title>= 31,536,000 \cdot 20</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.781613-2.044334C17.781613-3.144209 16.89693-4.004981 15.749234-4.208219C16.789334-4.507098 17.458823-5.379826 17.458823-6.312329C17.458823-7.256787 16.478499-7.950187 15.318848-7.950187C14.123331-7.950187 13.238649-7.220922 13.238649-6.348194C13.238649-5.869988 13.609259-5.774346 13.788587-5.774346C14.039645-5.774346 14.326569-5.953674 14.326569-6.312329C14.326569-6.694894 14.039645-6.862267 13.776631-6.862267C13.7049-6.862267 13.68099-6.862267 13.645125-6.850311C14.099421-7.663263 15.223207-7.663263 15.282983-7.663263C15.677503-7.663263 16.454589-7.483935 16.454589-6.312329C16.454589-6.085181 16.418724-5.415691 16.072024-4.901619C15.713369-4.375592 15.306893-4.339726 14.984103-4.327771L14.625448-4.291905C14.422211-4.27995 14.37439-4.267995 14.37439-4.160399C14.37439-4.040847 14.434166-4.040847 14.649359-4.040847H15.199296C16.215486-4.040847 16.669782-3.203985 16.669782-2.056289C16.669782-.490162 15.856831-.071731 15.271028-.071731C14.697179-.071731 13.716856-.3467 13.370156-1.135741C13.752721-1.075965 14.099421-1.291158 14.099421-1.721544C14.099421-2.068244 13.848362-2.307347 13.513618-2.307347C13.226694-2.307347 12.915859-2.139975 12.915859-1.685679C12.915859-.621669 13.979869 .251059 15.306893 .251059C16.729558 .251059 17.781613-.836862 17.781613-2.044334Z'/>
<path d='M23.180364 0V-.3467H22.809753C21.757699-.3467 21.721833-.490162 21.721833-.920548V-7.663263C21.721833-7.938232 21.721833-7.950187 21.48273-7.950187C21.195806-7.627397 20.598047-7.185056 19.366665-7.185056V-6.838356C19.641634-6.838356 20.239392-6.838356 20.896927-7.149191V-.920548C20.896927-.490162 20.861061-.3467 19.809006-.3467H19.438396V0C19.761186-.02391 20.920837-.02391 21.315357-.02391S22.857574-.02391 23.180364 0Z'/>
<path d='M26.46305 .047821C26.46305-.645579 26.235902-1.159651 25.74574-1.159651C25.363174-1.159651 25.171892-.848817 25.171892-.585803S25.351219 0 25.757695 0C25.913112 0 26.044619-.047821 26.152215-.155417C26.176126-.179328 26.200036-.179328 26.200036-.179328S26.223946-.011955 26.223946 .047821C26.223946 .442341 26.152215 1.219427 25.458816 1.996513C25.327309 2.139975 25.327309 2.187796 25.327309 2.187796C25.327309 2.247572 25.387085 2.307347 25.44686 2.307347C25.542502 2.307347 26.46305 1.422665 26.46305 .047821Z'/>
<path d='M34.636225-2.402989C34.636225-3.825654 33.679811-5.009215 32.424519-5.009215C31.743074-5.009215 31.217047-4.710336 30.906212-4.375592V-6.850311C31.420285-6.682939 31.838716-6.670984 31.970222-6.670984C33.321156-6.670984 34.181928-7.663263 34.181928-7.830635C34.181928-7.878456 34.158018-7.938232 34.086287-7.938232C34.086287-7.938232 34.038466-7.938232 33.93087-7.890411C33.261381-7.603487 32.687532-7.567621 32.376698-7.567621C31.587657-7.567621 31.025764-7.806725 30.798616-7.902366C30.71493-7.938232 30.679064-7.938232 30.679064-7.938232C30.583423-7.938232 30.583423-7.866501 30.583423-7.675218V-4.124533C30.583423-3.90934 30.583423-3.837609 30.726885-3.837609C30.786661-3.837609 30.798616-3.849564 30.918168-3.993026C31.252912-4.483188 31.814805-4.770112 32.412564-4.770112C33.046187-4.770112 33.357022-4.184309 33.452663-3.981071C33.655901-3.514819 33.667856-2.929016 33.667856-2.47472S33.667856-1.338979 33.333112-.800996C33.070098-.37061 32.603846-.071731 32.077819-.071731C31.288778-.071731 30.511692-.609714 30.296499-1.482441C30.356275-1.458531 30.428006-1.446575 30.487782-1.446575C30.691019-1.446575 31.013809-1.566127 31.013809-1.972603C31.013809-2.307347 30.786661-2.49863 30.487782-2.49863C30.272588-2.49863 29.961754-2.391034 29.961754-1.924782C29.961754-.908593 30.774706 .251059 32.101729 .251059C33.452663 .251059 34.636225-.884682 34.636225-2.402989Z'/>
<path d='M40.584913-2.044334C40.584913-3.144209 39.700231-4.004981 38.552535-4.208219C39.592634-4.507098 40.262124-5.379826 40.262124-6.312329C40.262124-7.256787 39.2818-7.950187 38.122149-7.950187C36.926632-7.950187 36.04195-7.220922 36.04195-6.348194C36.04195-5.869988 36.41256-5.774346 36.591887-5.774346C36.842946-5.774346 37.12987-5.953674 37.12987-6.312329C37.12987-6.694894 36.842946-6.862267 36.579932-6.862267C36.508201-6.862267 36.484291-6.862267 36.448425-6.850311C36.902722-7.663263 38.026507-7.663263 38.086283-7.663263C38.480804-7.663263 39.25789-7.483935 39.25789-6.312329C39.25789-6.085181 39.222024-5.415691 38.875324-4.901619C38.516669-4.375592 38.110194-4.339726 37.787404-4.327771L37.428749-4.291905C37.225511-4.27995 37.177691-4.267995 37.177691-4.160399C37.177691-4.040847 37.237466-4.040847 37.452659-4.040847H38.002597C39.018786-4.040847 39.473083-3.203985 39.473083-2.056289C39.473083-.490162 38.660131-.071731 38.074328-.071731C37.50048-.071731 36.520156-.3467 36.173456-1.135741C36.556022-1.075965 36.902722-1.291158 36.902722-1.721544C36.902722-2.068244 36.651663-2.307347 36.316918-2.307347C36.029994-2.307347 35.71916-2.139975 35.71916-1.685679C35.71916-.621669 36.78317 .251059 38.110194 .251059C39.532859 .251059 40.584913-.836862 40.584913-2.044334Z'/>
<path d='M46.437961-2.438854C46.437961-4.028892 45.32613-5.092902 44.130613-5.092902C43.066603-5.092902 42.672083-4.172354 42.552531-3.837609V-4.160399C42.552531-7.185056 44.023017-7.663263 44.668596-7.663263C45.098982-7.663263 45.529368-7.531756 45.756516-7.173101C45.613054-7.173101 45.158758-7.173101 45.158758-6.682939C45.158758-6.419925 45.338085-6.192777 45.64892-6.192777C45.947799-6.192777 46.151037-6.372105 46.151037-6.718804C46.151037-7.340473 45.69674-7.950187 44.656641-7.950187C43.150289-7.950187 41.572207-6.40797 41.572207-3.777833C41.572207-.490162 43.006827 .251059 44.023017 .251059C45.32613 .251059 46.437961-.884682 46.437961-2.438854ZM45.457637-2.450809C45.457637-1.841096 45.457637-1.303113 45.230489-.848817C44.93161-.274969 44.501223-.071731 44.023017-.071731C43.269841-.071731 42.911186-.74122 42.80359-.992279C42.695993-1.303113 42.576441-1.888917 42.576441-2.725778C42.576441-3.670237 43.006827-4.853798 44.082793-4.853798C44.740327-4.853798 45.087027-4.411457 45.266354-4.004981C45.457637-3.56264 45.457637-2.964882 45.457637-2.450809Z'/>
<path d='M49.26635 .047821C49.26635-.645579 49.039202-1.159651 48.54904-1.159651C48.166475-1.159651 47.975192-.848817 47.975192-.585803S48.15452 0 48.560996 0C48.716413 0 48.84792-.047821 48.955516-.155417C48.979426-.179328 49.003337-.179328 49.003337-.179328S49.027247-.011955 49.027247 .047821C49.027247 .442341 48.955516 1.219427 48.262116 1.996513C48.130609 2.139975 48.130609 2.187796 48.130609 2.187796C48.130609 2.247572 48.190385 2.307347 48.250161 2.307347C48.345802 2.307347 49.26635 1.422665 49.26635 .047821Z'/>
<path d='M57.535167-3.825654C57.535167-4.817933 57.475391-5.786301 57.045005-6.694894C56.554843-7.687173 55.694071-7.950187 55.108268-7.950187C54.414868-7.950187 53.566051-7.603487 53.12371-6.611208C52.788965-5.858032 52.669413-5.116812 52.669413-3.825654C52.669413-2.666002 52.7531-1.793275 53.183486-.944458C53.649737-.035866 54.474644 .251059 55.096313 .251059C56.136412 .251059 56.734171-.37061 57.08087-1.06401C57.511256-1.960648 57.535167-3.132254 57.535167-3.825654ZM56.626574-3.969116C56.626574-3.16812 56.626574-2.259527 56.495067-1.530262C56.267919-.215193 55.514743 .011955 55.096313 .011955C54.713747 .011955 53.936661-.203238 53.709513-1.506351C53.578006-2.223661 53.578006-3.132254 53.578006-3.969116C53.578006-4.94944 53.578006-5.834122 53.769289-6.539477C53.972527-7.340473 54.58224-7.711083 55.096313-7.711083C55.550609-7.711083 56.244009-7.436115 56.471157-6.40797C56.626574-5.726526 56.626574-4.782067 56.626574-3.969116Z'/>
<path d='M63.388214-3.825654C63.388214-4.817933 63.328438-5.786301 62.898052-6.694894C62.40789-7.687173 61.547118-7.950187 60.961315-7.950187C60.267915-7.950187 59.419098-7.603487 58.976757-6.611208C58.642012-5.858032 58.522461-5.116812 58.522461-3.825654C58.522461-2.666002 58.606147-1.793275 59.036533-.944458C59.502784-.035866 60.327691 .251059 60.94936 .251059C61.989459 .251059 62.587218-.37061 62.933918-1.06401C63.364304-1.960648 63.388214-3.132254 63.388214-3.825654ZM62.479621-3.969116C62.479621-3.16812 62.479621-2.259527 62.348114-1.530262C62.120966-.215193 61.367791 .011955 60.94936 .011955C60.566794 .011955 59.789708-.203238 59.56256-1.506351C59.431053-2.223661 59.431053-3.132254 59.431053-3.969116C59.431053-4.94944 59.431053-5.834122 59.622336-6.539477C59.825574-7.340473 60.435288-7.711083 60.94936-7.711083C61.403656-7.711083 62.097056-7.436115 62.324204-6.40797C62.479621-5.726526 62.479621-4.782067 62.479621-3.969116Z'/>
<path d='M69.241261-3.825654C69.241261-4.817933 69.181486-5.786301 68.751099-6.694894C68.260938-7.687173 67.400165-7.950187 66.814362-7.950187C66.120962-7.950187 65.272146-7.603487 64.829804-6.611208C64.49506-5.858032 64.375508-5.116812 64.375508-3.825654C64.375508-2.666002 64.459194-1.793275 64.88958-.944458C65.355832-.035866 66.180738 .251059 66.802407 .251059C67.842507 .251059 68.440265-.37061 68.786965-1.06401C69.217351-1.960648 69.241261-3.132254 69.241261-3.825654ZM68.332669-3.969116C68.332669-3.16812 68.332669-2.259527 68.201162-1.530262C67.974014-.215193 67.220838 .011955 66.802407 .011955C66.419842 .011955 65.642756-.203238 65.415608-1.506351C65.284101-2.223661 65.284101-3.132254 65.284101-3.969116C65.284101-4.94944 65.284101-5.834122 65.475383-6.539477C65.678621-7.340473 66.288335-7.711083 66.802407-7.711083C67.256703-7.711083 67.950103-7.436115 68.177251-6.40797C68.332669-5.726526 68.332669-4.782067 68.332669-3.969116Z'/>
<path d='M74.690449-2.988792C74.690449-3.335492 74.403525-3.622416 74.056825-3.622416S73.423201-3.335492 73.423201-2.988792S73.710125-2.355168 74.056825-2.355168S74.690449-2.642092 74.690449-2.988792Z'/>
<path d='M83.632884-2.008468H83.369871C83.334005-1.80523 83.238364-1.147696 83.118812-.956413C83.035126-.848817 82.353681-.848817 81.995026-.848817H79.78332C80.10611-1.123786 80.835375-1.888917 81.146209-2.175841C82.963395-3.849564 83.632884-4.471233 83.632884-5.654795C83.632884-7.029639 82.544964-7.950187 81.158165-7.950187S78.958414-6.766625 78.958414-5.738481C78.958414-5.128767 79.484441-5.128767 79.520307-5.128767C79.771365-5.128767 80.082199-5.308095 80.082199-5.69066C80.082199-6.025405 79.855051-6.252553 79.520307-6.252553C79.41271-6.252553 79.3888-6.252553 79.352934-6.240598C79.580082-7.053549 80.225661-7.603487 81.002747-7.603487C82.018937-7.603487 82.640605-6.75467 82.640605-5.654795C82.640605-4.638605 82.054802-3.753923 81.373358-2.988792L78.958414-.286924V0H83.32205L83.632884-2.008468Z'/>
<path d='M89.581573-3.825654C89.581573-4.817933 89.521797-5.786301 89.091411-6.694894C88.601249-7.687173 87.740477-7.950187 87.154674-7.950187C86.461274-7.950187 85.612457-7.603487 85.170116-6.611208C84.835371-5.858032 84.71582-5.116812 84.71582-3.825654C84.71582-2.666002 84.799506-1.793275 85.229892-.944458C85.696143-.035866 86.52105 .251059 87.142719 .251059C88.182818 .251059 88.780577-.37061 89.127277-1.06401C89.557663-1.960648 89.581573-3.132254 89.581573-3.825654ZM88.67298-3.969116C88.67298-3.16812 88.67298-2.259527 88.541473-1.530262C88.314325-.215193 87.56115 .011955 87.142719 .011955C86.760153 .011955 85.983067-.203238 85.755919-1.506351C85.624412-2.223661 85.624412-3.132254 85.624412-3.969116C85.624412-4.94944 85.624412-5.834122 85.815695-6.539477C86.018933-7.340473 86.628646-7.711083 87.142719-7.711083C87.597015-7.711083 88.290415-7.436115 88.517563-6.40797C88.67298-5.726526 88.67298-4.782067 88.67298-3.969116Z'/>
</g>
</svg>
</dd>
</dl>
<p>In four years that would grow to <strong>2,524,608,000</strong>.</p>
<dl class="long">
<dt>
2,522,880,000 events in four years
</dt>
<dd>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='89.103366pt' height='10.389041pt' style='vertical-align: -2.307347pt' viewBox='.645579 -8.081694 89.103366 10.389041'>
<title>= 630,720,000 \cdot 4</title>
<defs/>
<g >
<path d='M8.452304-4.088667C8.452304-4.315816 8.249066-4.315816 8.069738-4.315816H1.028144C.860772-4.315816 .645579-4.315816 .645579-4.100623C.645579-3.873474 .848817-3.873474 1.028144-3.873474H8.069738C8.237111-3.873474 8.452304-3.873474 8.452304-4.088667ZM8.452304-1.865006C8.452304-2.092154 8.249066-2.092154 8.069738-2.092154H1.028144C.860772-2.092154 .645579-2.092154 .645579-1.876961C.645579-1.649813 .848817-1.649813 1.028144-1.649813H8.069738C8.237111-1.649813 8.452304-1.649813 8.452304-1.865006Z'/>
<path d='M17.781613-2.438854C17.781613-4.028892 16.669782-5.092902 15.474265-5.092902C14.410255-5.092902 14.015735-4.172354 13.896183-3.837609V-4.160399C13.896183-7.185056 15.366669-7.663263 16.012248-7.663263C16.442634-7.663263 16.87302-7.531756 17.100168-7.173101C16.956706-7.173101 16.50241-7.173101 16.50241-6.682939C16.50241-6.419925 16.681737-6.192777 16.992572-6.192777C17.291451-6.192777 17.494689-6.372105 17.494689-6.718804C17.494689-7.340473 17.040392-7.950187 16.000293-7.950187C14.493942-7.950187 12.915859-6.40797 12.915859-3.777833C12.915859-.490162 14.35048 .251059 15.366669 .251059C16.669782 .251059 17.781613-.884682 17.781613-2.438854ZM16.801289-2.450809C16.801289-1.841096 16.801289-1.303113 16.574141-.848817C16.275262-.274969 15.844876-.071731 15.366669-.071731C14.613493-.071731 14.254838-.74122 14.147242-.992279C14.039645-1.303113 13.920094-1.888917 13.920094-2.725778C13.920094-3.670237 14.35048-4.853798 15.426445-4.853798C16.083979-4.853798 16.430679-4.411457 16.610006-4.004981C16.801289-3.56264 16.801289-2.964882 16.801289-2.450809Z'/>
<path d='M23.63466-2.044334C23.63466-3.144209 22.749978-4.004981 21.602281-4.208219C22.642381-4.507098 23.311871-5.379826 23.311871-6.312329C23.311871-7.256787 22.331547-7.950187 21.171895-7.950187C19.976379-7.950187 19.091696-7.220922 19.091696-6.348194C19.091696-5.869988 19.462306-5.774346 19.641634-5.774346C19.892692-5.774346 20.179616-5.953674 20.179616-6.312329C20.179616-6.694894 19.892692-6.862267 19.629679-6.862267C19.557948-6.862267 19.534037-6.862267 19.498172-6.850311C19.952468-7.663263 21.076254-7.663263 21.13603-7.663263C21.53055-7.663263 22.307636-7.483935 22.307636-6.312329C22.307636-6.085181 22.271771-5.415691 21.925071-4.901619C21.566416-4.375592 21.15994-4.339726 20.837151-4.327771L20.478496-4.291905C20.275258-4.27995 20.227437-4.267995 20.227437-4.160399C20.227437-4.040847 20.287213-4.040847 20.502406-4.040847H21.052344C22.068533-4.040847 22.522829-3.203985 22.522829-2.056289C22.522829-.490162 21.709878-.071731 21.124075-.071731C20.550227-.071731 19.569903-.3467 19.223203-1.135741C19.605768-1.075965 19.952468-1.291158 19.952468-1.721544C19.952468-2.068244 19.70141-2.307347 19.366665-2.307347C19.079741-2.307347 18.768907-2.139975 18.768907-1.685679C18.768907-.621669 19.832917 .251059 21.15994 .251059C22.582605 .251059 23.63466-.836862 23.63466-2.044334Z'/>
<path d='M29.487707-3.825654C29.487707-4.817933 29.427931-5.786301 28.997545-6.694894C28.507384-7.687173 27.646611-7.950187 27.060808-7.950187C26.367408-7.950187 25.518592-7.603487 25.07625-6.611208C24.741506-5.858032 24.621954-5.116812 24.621954-3.825654C24.621954-2.666002 24.70564-1.793275 25.136026-.944458C25.602278-.035866 26.427184 .251059 27.048853 .251059C28.088953 .251059 28.686711-.37061 29.033411-1.06401C29.463797-1.960648 29.487707-3.132254 29.487707-3.825654ZM28.579115-3.969116C28.579115-3.16812 28.579115-2.259527 28.447608-1.530262C28.22046-.215193 27.467284 .011955 27.048853 .011955C26.666288 .011955 25.889202-.203238 25.662054-1.506351C25.530547-2.223661 25.530547-3.132254 25.530547-3.969116C25.530547-4.94944 25.530547-5.834122 25.721829-6.539477C25.925067-7.340473 26.534781-7.711083 27.048853-7.711083C27.503149-7.711083 28.196549-7.436115 28.423697-6.40797C28.579115-5.726526 28.579115-4.782067 28.579115-3.969116Z'/>
<path d='M32.316097 .047821C32.316097-.645579 32.088949-1.159651 31.598787-1.159651C31.216222-1.159651 31.024939-.848817 31.024939-.585803S31.204266 0 31.610742 0C31.766159 0 31.897666-.047821 32.005263-.155417C32.029173-.179328 32.053083-.179328 32.053083-.179328S32.076994-.011955 32.076994 .047821C32.076994 .442341 32.005263 1.219427 31.311863 1.996513C31.180356 2.139975 31.180356 2.187796 31.180356 2.187796C31.180356 2.247572 31.240132 2.307347 31.299908 2.307347C31.395549 2.307347 32.316097 1.422665 32.316097 .047821Z'/>
<path d='M40.907703-7.424159V-7.699128H38.026507C36.579932-7.699128 36.556022-7.854545 36.508201-8.081694H36.245187L35.874577-5.69066H36.137591C36.173456-5.905853 36.281053-6.647073 36.43647-6.77858C36.532111-6.850311 37.428749-6.850311 37.596121-6.850311H40.130617L38.863369-5.033126C38.54058-4.566874 37.333108-2.606227 37.333108-.358655C37.333108-.227148 37.333108 .251059 37.82327 .251059C38.325387 .251059 38.325387-.215193 38.325387-.37061V-.968369C38.325387-2.749689 38.612311-4.136488 39.174204-4.937484L40.907703-7.424159Z'/>
<path d='M46.342319-2.008468H46.079306C46.04344-1.80523 45.947799-1.147696 45.828247-.956413C45.744561-.848817 45.063116-.848817 44.704461-.848817H42.492755C42.815545-1.123786 43.54481-1.888917 43.855644-2.175841C45.67283-3.849564 46.342319-4.471233 46.342319-5.654795C46.342319-7.029639 45.254399-7.950187 43.8676-7.950187S41.667849-6.766625 41.667849-5.738481C41.667849-5.128767 42.193876-5.128767 42.229742-5.128767C42.4808-5.128767 42.791634-5.308095 42.791634-5.69066C42.791634-6.025405 42.564486-6.252553 42.229742-6.252553C42.122145-6.252553 42.098235-6.252553 42.062369-6.240598C42.289517-7.053549 42.935096-7.603487 43.712182-7.603487C44.728372-7.603487 45.35004-6.75467 45.35004-5.654795C45.35004-4.638605 44.764237-3.753923 44.082793-2.988792L41.667849-.286924V0H46.031485L46.342319-2.008468Z'/>
<path d='M52.291008-3.825654C52.291008-4.817933 52.231232-5.786301 51.800846-6.694894C51.310684-7.687173 50.449912-7.950187 49.864109-7.950187C49.170709-7.950187 48.321892-7.603487 47.879551-6.611208C47.544806-5.858032 47.425255-5.116812 47.425255-3.825654C47.425255-2.666002 47.508941-1.793275 47.939327-.944458C48.405578-.035866 49.230485 .251059 49.852154 .251059C50.892253 .251059 51.490012-.37061 51.836712-1.06401C52.267098-1.960648 52.291008-3.132254 52.291008-3.825654ZM51.382415-3.969116C51.382415-3.16812 51.382415-2.259527 51.250908-1.530262C51.02376-.215193 50.270585 .011955 49.852154 .011955C49.469588 .011955 48.692502-.203238 48.465354-1.506351C48.333847-2.223661 48.333847-3.132254 48.333847-3.969116C48.333847-4.94944 48.333847-5.834122 48.52513-6.539477C48.728368-7.340473 49.338081-7.711083 49.852154-7.711083C50.30645-7.711083 50.99985-7.436115 51.226998-6.40797C51.382415-5.726526 51.382415-4.782067 51.382415-3.969116Z'/>
<path d='M55.119398 .047821C55.119398-.645579 54.892249-1.159651 54.402088-1.159651C54.019522-1.159651 53.82824-.848817 53.82824-.585803S54.007567 0 54.414043 0C54.56946 0 54.700967-.047821 54.808563-.155417C54.832474-.179328 54.856384-.179328 54.856384-.179328S54.880294-.011955 54.880294 .047821C54.880294 .442341 54.808563 1.219427 54.115164 1.996513C53.983657 2.139975 53.983657 2.187796 53.983657 2.187796C53.983657 2.247572 54.043433 2.307347 54.103208 2.307347C54.19885 2.307347 55.119398 1.422665 55.119398 .047821Z'/>
<path d='M63.388214-3.825654C63.388214-4.817933 63.328438-5.786301 62.898052-6.694894C62.40789-7.687173 61.547118-7.950187 60.961315-7.950187C60.267915-7.950187 59.419098-7.603487 58.976757-6.611208C58.642012-5.858032 58.522461-5.116812 58.522461-3.825654C58.522461-2.666002 58.606147-1.793275 59.036533-.944458C59.502784-.035866 60.327691 .251059 60.94936 .251059C61.989459 .251059 62.587218-.37061 62.933918-1.06401C63.364304-1.960648 63.388214-3.132254 63.388214-3.825654ZM62.479621-3.969116C62.479621-3.16812 62.479621-2.259527 62.348114-1.530262C62.120966-.215193 61.367791 .011955 60.94936 .011955C60.566794 .011955 59.789708-.203238 59.56256-1.506351C59.431053-2.223661 59.431053-3.132254 59.431053-3.969116C59.431053-4.94944 59.431053-5.834122 59.622336-6.539477C59.825574-7.340473 60.435288-7.711083 60.94936-7.711083C61.403656-7.711083 62.097056-7.436115 62.324204-6.40797C62.479621-5.726526 62.479621-4.782067 62.479621-3.969116Z'/>
<path d='M69.241261-3.825654C69.241261-4.817933 69.181486-5.786301 68.751099-6.694894C68.260938-7.687173 67.400165-7.950187 66.814362-7.950187C66.120962-7.950187 65.272146-7.603487 64.829804-6.611208C64.49506-5.858032 64.375508-5.116812 64.375508-3.825654C64.375508-2.666002 64.459194-1.793275 64.88958-.944458C65.355832-.035866 66.180738 .251059 66.802407 .251059C67.842507 .251059 68.440265-.37061 68.786965-1.06401C69.217351-1.960648 69.241261-3.132254 69.241261-3.825654ZM68.332669-3.969116C68.332669-3.16812 68.332669-2.259527 68.201162-1.530262C67.974014-.215193 67.220838 .011955 66.802407 .011955C66.419842 .011955 65.642756-.203238 65.415608-1.506351C65.284101-2.223661 65.284101-3.132254 65.284101-3.969116C65.284101-4.94944 65.284101-5.834122 65.475383-6.539477C65.678621-7.340473 66.288335-7.711083 66.802407-7.711083C67.256703-7.711083 67.950103-7.436115 68.177251-6.40797C68.332669-5.726526 68.332669-4.782067 68.332669-3.969116Z'/>
<path d='M75.094309-3.825654C75.094309-4.817933 75.034533-5.786301 74.604147-6.694894C74.113985-7.687173 73.253213-7.950187 72.667409-7.950187C71.97401-7.950187 71.125193-7.603487 70.682852-6.611208C70.348107-5.858032 70.228555-5.116812 70.228555-3.825654C70.228555-2.666002 70.312241-1.793275 70.742627-.944458C71.208879-.035866 72.033786 .251059 72.655454 .251059C73.695554 .251059 74.293312-.37061 74.640012-1.06401C75.070398-1.960648 75.094309-3.132254 75.094309-3.825654ZM74.185716-3.969116C74.185716-3.16812 74.185716-2.259527 74.054209-1.530262C73.827061-.215193 73.073885 .011955 72.655454 .011955C72.272889 .011955 71.495803-.203238 71.268655-1.506351C71.137148-2.223661 71.137148-3.132254 71.137148-3.969116C71.137148-4.94944 71.137148-5.834122 71.328431-6.539477C71.531669-7.340473 72.141382-7.711083 72.655454-7.711083C73.109751-7.711083 73.80315-7.436115 74.030299-6.40797C74.185716-5.726526 74.185716-4.782067 74.185716-3.969116Z'/>
<path d='M80.543496-2.988792C80.543496-3.335492 80.256572-3.622416 79.909872-3.622416S79.276248-3.335492 79.276248-2.988792S79.563173-2.355168 79.909872-2.355168S80.543496-2.642092 80.543496-2.988792Z'/>
<path d='M89.748945-1.996513V-2.343213H88.541473V-7.782814C88.541473-8.009963 88.541473-8.069738 88.374101-8.069738C88.27846-8.069738 88.242594-8.069738 88.146953-7.926276L84.548447-2.343213V-1.996513H87.692656V-.908593C87.692656-.466252 87.668746-.3467 86.796019-.3467H86.556915V0C86.831884-.02391 87.776343-.02391 88.111087-.02391S89.402245-.02391 89.677214 0V-.3467H89.438111C88.577339-.3467 88.541473-.466252 88.541473-.908593V-1.996513H89.748945ZM87.752432-2.343213H84.847326L87.752432-6.850311V-2.343213Z'/>
</g>
</svg>
</dd>
</dl>
<p>The <code>MAX_VALUE</code> for <code>java.lang.Integer</code> is <strong>2,147,483,647</strong>.</p>
<p>The example is contrived and unlikely but also recall that automatically
incremented keys do not always grow linearly, and twenty events per second is
conservative for a web server… (Insert your own <em>web scale</em> humor here.) But
even with those constraints the key grows beyond the capacity of
<code>java.lang.Integer</code> in less that four years. Four years are enough time to
forget about the capacity constraint built into the example application.</p>
<p>You might forget how these simple number types work and think:</p>
<blockquote>
<p>No problem, statistics or other processes are running, constantly computing
metrics against <code>Events</code> and some computations use the key value… Surely an
exception will be thrown as soon as the Integer overflows.</p>
</blockquote>
<p><strong>This is where you would be <em>wrong</em></strong>.</p>
<p>Division will throw an <code>ArithmeticException</code> on <em>division by zero</em>, but a sum,
for example, will quietly continue on an <em>overflow</em>. Let me repeat that…
<strong>The sum will return an incorrect value on overflow, but it will <em>not</em> throw a
runtime exception!</strong> This is serious problem. The application will quietly
continue to run, but the mathematical operations on the value will be
incorrect. This should be a real <strong><em>“What!?”</em></strong> moment.</p>
<h2 id="twos-complement">Two’s complement</h2>
<p>The <code>JVM</code> stores an <code>int</code> as a <em>two’s complement</em> binary (the core of
<code>java.lang.Integer</code> and <code>scala.Int</code>), and thus it is often referred to as a
<em>two’s complement</em> type.</p>
<p>Specifically, the JVM uses a 32-bit signed two’s complement integer for <code>int</code>.
The most significant bit is used to designate the sign of the number. The max
value for <code>int</code> is 2,147,483,647, and would thus be represented<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> like <code>0111 1111 1111 1111 1111 1111 1111 1111</code>.</p>
<h3 id="simple-sum">Simple sum</h3>
<p>First lets simply add 1 to 2,147,483,646.</p>
<figure>
<figcaption>
2,147,483,646 + 1.
</figcaption>
<pre><code>
  0111 1111 1111 1111 1111 1111 1111 1110
+ 0000 0000 0000 0000 0000 0000 0000 0001
-------------------------------------------
  0111 1111 1111 1111 1111 1111 1111 1111
</code></pre>
</figure>
<p>The result is what we expect, <code>0111 1111 1111 1111 1111 1111 1111 1111</code>, or
2,147,483,647 in decimal.</p>
<h3 id="negative-values">Negative values</h3>
<p>The JVM <code>int</code> is signed, that is to say both positive and negative values can
be stored as an <code>int</code>.</p>
<p>Using the MSB (most significant bit) to designate sign makes it possible to
store negative values using the same placeholders and arithmetic. A negative
is represented with the MSB set to <code>1</code>. To convert -2,147,483,647 to a two’s
complement binary for <code>int</code>, we must find the complement of each bit then add
one to the result.</p>
<ol>
<li><p>Find the complement of each bit of <code>0111 1111 1111 1111 1111 1111 1111 1111</code>.<br />
<code>1000 0000 0000 0000 0000 0000 0000 0000</code></p></li>
<li><p>Add one</p></li>
</ol>
<figure class>
<figcaption>
</figcaption>
<pre><code>
  1000 0000 0000 0000 0000 0000 0000 0000
+ 0000 0000 0000 0000 0000 0000 0000 0001
-------------------------------------------
  1000 0000 0000 0000 0000 0000 0000 0001 
</code></pre>
</figure>
<p>The minimum value would be the value with the greatest magnitude and the
opposite sign. The 32 bit, negative, two’s complement number with the greatest
magnitude would be where the sign bit is set to <code>1</code> and all the other bits are
set to <code>0</code>, i.e.. <code>1000 0000 0000 0000 0000 0000 0000 0000</code>. This means the
min value<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> is -2,147,483,648 in decimal.</p>
<h3 id="bad-arithmetic-without-error">Bad arithmetic without error</h3>
<p>Let’s see what happens when we overflow by adding one to 2,147,483,647.</p>
<figure>
<figcaption>
2,147,483,647 + 1.
</figcaption>
<p>A carry bit needed…</p>
<pre><code>
                                       <sup>1</sup>                                 
  0111 1111 1111 1111 1111 1111 1111 1111
+ 0000 0000 0000 0000 0000 0000 0000 0001
-------------------------------------------
                                        0
</code></pre>
<p>and so on…</p>
<pre><code>
  <sup>1</sup>  
  0111 1111 1111 1111 1111 1111 1111 1111
+ 0000 0000 0000 0000 0000 0000 0000 0001
-------------------------------------------
  1000 0000 0000 0000 0000 0000 0000 0000
</code></pre>
</figure>
<p><strong>Wait!</strong> We have seen this one before, it is <strong>-2,147,483,648</strong>! So in this
case the result is mathematically incorrect, but a valid <code>int</code>!</p>
<p>You can try out Scala code snips in the online REPL
<a href="http://www.simplyscala.com/">here</a>, and Java in the online REPL
<a href="http://www.javarepl.com/console.html">here</a>. The following return
<code>-2147483648</code>.</p>
<dl>
<dt>Scala</dt>
<dd>
<code>Int.MaxValue + 1</code>
</dd>
<dt>Java</dt>
<dd>
<code>Integer.MAX_VALUE + 1</code>
</dd>
</dl>
<h2 id="biginteger-java.math.biginteger-to-the-rescue">BigInteger (<code>java.math.BigInteger</code>) to the rescue?</h2>
<p>Clearly when arithmetic is needed, or when it is <em>possible</em> to overflow a
field, one should use something safe like BigInteger over its primitive
counterpart. Since one can never know for certain how a field will be used,
selecting a safe type should be the default.</p>
<p>If one can be sure that arithmetic will never be performed on a field, and
benchmarking shows that using a primitive is needed, then maybe it is worth the
risk.</p>
<h3 id="primitive-type">Primitive Type</h3>
<dl>
<dt>Pros</dt>
<dd>
Simple quick arithmetic.
</dd>
<dd>
Fixed memory allocation size.
</dd>
<dd>
Symbol operators. ( <code>+ - * /</code>)
</dd>
<dt>Cons</dt>
<dd>
<em>Arithmetic can fail without error!</em>
</dd>
</dl>
<h3 id="biginteger-java.math.biginteger">BigInteger (<code>java.math.BigInteger</code>)</h3>
<dl>
<dt>Pros</dt>
<dd>
<em>Correct arithmetic</em>
</dd>
<dt>Cons</dt>
<dd>
Can not use symbol operators; must use <code>add</code>, <code>subtract</code>, <code>multiply</code>, and <code>divide</code> methods.
</dd>
<dd>
Arithmetic <em>could</em> be slower.
</dd>
<dd>
Higher memory allocation requirements because more information is stored and capacity is dynamic.
</dd>
</dl>
<h3 id="bigint-scala.math.bigint">BigInt (<code>scala.math.BigInt</code>)</h3>
<p>If you live in the Scala world you have better options, such as
<code>scala.math.BigInt</code>. It can be thought of a Scala’s <code>BigInteger</code>. In Scala,
characters such as <code>+ - * /</code> can be used as method names, so this makes using
<code>scala.math.BigInt</code> a pleasant experience.</p>
<h2 id="spire">Spire</h2>
<p>Finally, when talking about handling numbers in Scala, we need to talk about
<a href="https://github.com/non/spire">spire</a>. Spire makes working with numbers a
beautiful experience.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">//spire example</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> Inspired <span class="kw">extends</span> App {</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">import</span> spire.syntax.literals.si._</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">val</span> y = big<span class="st">&quot;2 147 483 647&quot;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">println</span>(s<span class="st">&quot;y, using spire string interpolation = $${y + 1}&quot;</span>)</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Look at how clear and simple it is to create a <code>BigInt</code> using
<a href="https://github.com/non/spire">spire</a> string interpolation. Using spaces makes
it easier to identify the place values for each digit and results in source
that is simpler to read. Spire supports additional number types, type classes
and more. Let’s take
<a href="https://github.com/non/spire/blob/master/GUIDE.md#safelong">SafeLong</a> for
example. It works as a nice replacement for <code>BigInt</code>. While it provides
accurate arithmetic, independant of value, it performs better than <code>BigInt</code> for
values inside the <code>java.lang.Long</code> range.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<h2 id="conclusion">Conclusion</h2>
<p>A two’s complement type like <code>int</code> should be considered an optimization choice
for Scala and Java software development, and not a default. Its performance
comes at a cost and that cost is silent failure. The default choice for a
whole number field should be something like <code>BigInt</code> or <code>SafeLong</code> because they
ensure correct arithmetic without regard to the size of the operands. This is
made far more pleasant in Scala, especially when using a library like
<a href="https://github.com/non/spire">spire</a>.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>I show the left most bit as the most significant bit because it makes it
simple to see the arithmetic.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Yes, the minimum and maximum values are asymmetrical, the minimum is
<strong>-2,147,483,648</strong> and the maximum is <strong>2,147,483,647</strong>.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p><svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='105.583854pt' height='12.089371pt' style='vertical-align: -2.450810pt' viewBox='.992279 -9.638561 105.583854 12.089371'>
<title>-2^{63} \text{ through } 2^{63} - 1</title>
<defs/>
<g >
<path d='M8.296887-2.988792C8.296887-3.227895 8.069738-3.227895 7.902366-3.227895H1.3868C1.219427-3.227895 .992279-3.227895 .992279-2.988792S1.219427-2.749689 1.3868-2.749689H7.902366C8.069738-2.749689 8.296887-2.749689 8.296887-2.988792Z'/>
<path d='M14.558771-2.008468H14.295757C14.259892-1.80523 14.16425-1.147696 14.044699-.956413C13.961013-.848817 13.279568-.848817 12.920913-.848817H10.709207C11.031996-1.123786 11.761262-1.888917 12.072096-2.175841C13.889282-3.849564 14.558771-4.471233 14.558771-5.654795C14.558771-7.029639 13.470851-7.950187 12.084051-7.950187S9.8843-6.766625 9.8843-5.738481C9.8843-5.128767 10.410328-5.128767 10.446193-5.128767C10.697252-5.128767 11.008086-5.308095 11.008086-5.69066C11.008086-6.025405 10.780938-6.252553 10.446193-6.252553C10.338597-6.252553 10.314686-6.252553 10.278821-6.240598C10.505969-7.053549 11.151548-7.603487 11.928634-7.603487C12.944823-7.603487 13.566492-6.75467 13.566492-5.654795C13.566492-4.638605 12.980689-3.753923 12.299244-2.988792L9.8843-.286924V0H14.247937L14.558771-2.008468Z'/>
<path d='M19.025019-5.956369C19.025019-7.000454 18.235978-7.733704 17.351295-7.733704C16.777447-7.733704 16.434732-7.367079 16.25142-6.976544C16.25142-7.638063 16.307211-8.219881 16.594135-8.706058C16.833238-9.104564 17.239714-9.431338 17.741831-9.431338C17.901233-9.431338 18.267858-9.407428 18.451171-9.128474C18.092516-9.112534 18.060635-8.84155 18.060635-8.753879C18.060635-8.514775 18.243948-8.379283 18.43523-8.379283C18.578692-8.379283 18.809826-8.466955 18.809826-8.769819C18.809826-9.248026 18.451171-9.638561 17.733861-9.638561C16.626015-9.638561 15.502229-8.586506 15.502229-6.864962C15.502229-4.705062 16.506463-4.171064 17.279564-4.171064C17.66213-4.171064 18.076575-4.274676 18.43523-4.617391C18.754035-4.928225 19.025019-5.26297 19.025019-5.956369ZM18.275828-5.96434C18.275828-5.557864 18.275828-5.207179 18.116426-4.920255C17.909203-4.55363 17.630249-4.410168 17.279564-4.410168C16.857148-4.410168 16.594135-4.705062 16.474583-4.928225C16.29127-5.28688 16.27533-5.828848 16.27533-6.131712C16.27533-6.920753 16.705716-7.510541 17.319415-7.510541C17.71792-7.510541 17.957024-7.303318 18.108456-7.024364C18.275828-6.72947 18.275828-6.370815 18.275828-5.96434Z'/>
<path d='M23.259141-5.701326C23.259141-6.362845 22.733113-6.968574 21.920162-7.143916C22.549801-7.367079 23.020037-7.909047 23.020037-8.546656S22.302727-9.638561 21.473836-9.638561C20.621034-9.638561 19.975455-9.176295 19.975455-8.570566C19.975455-8.275672 20.174707-8.14815 20.38193-8.14815C20.629004-8.14815 20.788406-8.323493 20.788406-8.554626C20.788406-8.84952 20.533362-8.961102 20.35802-8.969072C20.692765-9.407428 21.306463-9.431338 21.449925-9.431338C21.657148-9.431338 22.262877-9.367577 22.262877-8.546656C22.262877-7.988748 22.031744-7.654003 21.920162-7.526482C21.681059-7.279408 21.497746-7.263468 21.011569-7.231587C20.860137-7.223617 20.796376-7.215647 20.796376-7.112036C20.796376-7.000454 20.868107-7.000454 21.003599-7.000454H21.402105C22.031744-7.000454 22.430249-6.538188 22.430249-5.701326C22.430249-4.705062 21.864371-4.410168 21.441955-4.410168C21.003599-4.410168 20.405841-4.56957 20.126887-4.991986C20.413811-4.991986 20.613064-5.175298 20.613064-5.438312C20.613064-5.693356 20.429751-5.876668 20.174707-5.876668C19.959514-5.876668 19.736351-5.741176 19.736351-5.422372C19.736351-4.665211 20.549303-4.171064 21.457895-4.171064C22.51792-4.171064 23.259141-4.904315 23.259141-5.701326Z'/>
<path d='M31.917283-1.482441V-2.163885H31.65427V-1.506351C31.65427-.645579 31.30757-.143462 30.841318-.143462C30.028367-.143462 30.028367-1.255293 30.028367-1.458531V-4.805978H31.714046V-5.152677H30.028367V-7.352428H29.765353C29.753398-6.228643 29.323012-5.080946 28.235092-5.045081V-4.805978H29.251281V-1.482441C29.251281-.155417 30.135963 .119552 30.769587 .119552C31.522763 .119552 31.917283-.621669 31.917283-1.482441Z'/>
<path d='M38.80081 0V-.3467C38.203052-.3467 37.904172-.3467 37.892217-.705355V-2.905106C37.892217-4.016936 37.892217-4.351681 37.617248-4.734247C37.270548-5.200498 36.708656-5.272229 36.30218-5.272229C35.274035-5.272229 34.795829-4.495143 34.628456-4.124533H34.616501V-8.296887L32.954733-8.16538V-7.81868C33.767684-7.81868 33.863326-7.734994 33.863326-7.149191V-.884682C33.863326-.3467 33.731819-.3467 32.954733-.3467V0C33.265567-.02391 33.911146-.02391 34.245891-.02391C34.592591-.02391 35.23817-.02391 35.549004 0V-.3467C34.783874-.3467 34.640412-.3467 34.640412-.884682V-3.108344C34.640412-4.363636 35.465318-5.033126 36.206539-5.033126S37.115131-4.423412 37.115131-3.694147V-.884682C37.115131-.3467 36.983624-.3467 36.206539-.3467V0C36.517373-.02391 37.162952-.02391 37.497697-.02391C37.844397-.02391 38.489976-.02391 38.80081 0Z'/>
<path d='M43.295949-4.578829C43.295949-4.937484 42.97316-5.272229 42.459088-5.272229C41.442898-5.272229 41.096198-4.172354 41.024467-3.945205H41.012512V-5.272229L39.41052-5.140722V-4.794022C40.223471-4.794022 40.319112-4.710336 40.319112-4.124533V-.884682C40.319112-.3467 40.187606-.3467 39.41052-.3467V0C39.745264-.02391 40.402799-.02391 40.761454-.02391C41.084243-.02391 41.93306-.02391 42.208029 0V-.3467H41.968926C41.096198-.3467 41.072288-.478207 41.072288-.908593V-2.785554C41.072288-3.945205 41.550495-5.033126 42.471043-5.033126C42.566684-5.033126 42.590594-5.033126 42.638415-5.021171C42.542774-4.97335 42.351491-4.901619 42.351491-4.578829C42.351491-4.23213 42.62646-4.100623 42.817743-4.100623C43.056846-4.100623 43.295949-4.25604 43.295949-4.578829Z'/>
<path d='M49.115466-2.558406C49.115466-4.100623 47.943859-5.332005 46.55706-5.332005C45.12244-5.332005 43.986699-4.064757 43.986699-2.558406C43.986699-1.028144 45.182216 .119552 46.545105 .119552C47.955815 .119552 49.115466-1.052055 49.115466-2.558406ZM48.206873-2.666002C48.206873-2.247572 48.206873-1.506351 47.896039-.944458C47.561294-.37061 47.011356-.143462 46.55706-.143462C46.114719-.143462 45.576736-.334745 45.230036-.920548C44.907247-1.458531 44.895292-2.163885 44.895292-2.666002C44.895292-3.120299 44.895292-3.849564 45.265902-4.387547C45.600646-4.901619 46.126674-5.092902 46.545105-5.092902C47.011356-5.092902 47.513473-4.877709 47.836263-4.411457C48.206873-3.861519 48.206873-3.108344 48.206873-2.666002Z'/>
<path d='M55.709734 0V-.3467C54.896782-.3467 54.801141-.430386 54.801141-1.016189V-5.272229L53.115462-5.140722V-4.794022C53.928413-4.794022 54.024055-4.710336 54.024055-4.124533V-1.984558C54.024055-.968369 53.486072-.119552 52.589435-.119552C51.609111-.119552 51.549335-.681445 51.549335-1.315068V-5.272229L49.863656-5.140722V-4.794022C50.772249-4.794022 50.772249-4.758157 50.772249-3.694147V-1.900872C50.772249-1.159651 50.772249-.729265 51.130904-.334745C51.417828-.02391 51.90799 .119552 52.517704 .119552C52.720942 .119552 53.103507 .119552 53.509983-.227148C53.856682-.502117 54.047965-.956413 54.047965-.956413V.119552L55.709734 0Z'/>
<path d='M61.663403-4.853798C61.663403-5.068991 61.496031-5.403736 61.0776-5.403736C60.455931-5.403736 59.98968-5.021171 59.822307-4.841843C59.463652-5.116812 59.045222-5.272229 58.590925-5.272229C57.51496-5.272229 56.713964-4.459278 56.713964-3.53873C56.713964-2.857285 57.132395-2.414944 57.251946-2.307347C57.108484-2.12802 56.893291-1.78132 56.893291-1.315068C56.893291-.621669 57.311722-.32279 57.407364-.263014C56.857426-.107597 56.307488 .32279 56.307488 .944458C56.307488 1.769365 57.431274 2.450809 58.90176 2.450809C60.324425 2.450809 61.507986 1.817186 61.507986 .920548C61.507986 .621669 61.4243-.083686 60.70699-.454296C60.097276-.765131 59.499518-.765131 58.471373-.765131C57.742108-.765131 57.658422-.765131 57.443229-.992279C57.323677-1.111831 57.216081-1.338979 57.216081-1.590037C57.216081-1.793275 57.287812-1.996513 57.407364-2.163885C57.969256-1.793275 58.447463-1.793275 58.57897-1.793275C59.654935-1.793275 60.455931-2.606227 60.455931-3.526775C60.455931-3.849564 60.36029-4.303861 59.977725-4.686426C60.443976-5.164633 61.005869-5.164633 61.065645-5.164633C61.113466-5.164633 61.173241-5.164633 61.221062-5.140722C61.10151-5.092902 61.041735-4.97335 61.041735-4.841843C61.041735-4.674471 61.161286-4.531009 61.352569-4.531009C61.44821-4.531009 61.663403-4.590785 61.663403-4.853798ZM59.631025-3.53873C59.631025-3.323537 59.631025-2.833375 59.427787-2.510585C59.200639-2.163885 58.841984-2.044334 58.590925-2.044334C57.53887-2.044334 57.53887-3.251806 57.53887-3.526775C57.53887-3.741968 57.53887-4.23213 57.742108-4.554919C57.969256-4.901619 58.327911-5.021171 58.57897-5.021171C59.631025-5.021171 59.631025-3.813699 59.631025-3.53873ZM60.922183 .932503C60.922183 1.637858 60.01359 2.199751 58.913715 2.199751C57.766019 2.199751 56.893291 1.613948 56.893291 .932503C56.893291 .836862 56.917202 .37061 57.371498 .059776C57.634512-.107597 57.742108-.107597 58.57897-.107597C59.571249-.107597 60.922183-.107597 60.922183 .932503Z'/>
<path d='M68.066388 0V-.3467C67.46863-.3467 67.169751-.3467 67.157796-.705355V-2.905106C67.157796-4.016936 67.157796-4.351681 66.882827-4.734247C66.536127-5.200498 65.974234-5.272229 65.567758-5.272229C64.539614-5.272229 64.061407-4.495143 63.894035-4.124533H63.88208V-8.296887L62.220311-8.16538V-7.81868C63.033263-7.81868 63.128904-7.734994 63.128904-7.149191V-.884682C63.128904-.3467 62.997397-.3467 62.220311-.3467V0C62.531146-.02391 63.176725-.02391 63.511469-.02391C63.858169-.02391 64.503748-.02391 64.814583 0V-.3467C64.049452-.3467 63.90599-.3467 63.90599-.884682V-3.108344C63.90599-4.363636 64.730896-5.033126 65.472117-5.033126S66.38071-4.423412 66.38071-3.694147V-.884682C66.38071-.3467 66.249203-.3467 65.472117-.3467V0C65.782951-.02391 66.42853-.02391 66.763275-.02391C67.109975-.02391 67.755554-.02391 68.066388 0Z'/>
<path d='M77.503541-2.008468H77.240527C77.204662-1.80523 77.10902-1.147696 76.989469-.956413C76.905783-.848817 76.224338-.848817 75.865683-.848817H73.653977C73.976766-1.123786 74.706032-1.888917 75.016866-2.175841C76.834052-3.849564 77.503541-4.471233 77.503541-5.654795C77.503541-7.029639 76.415621-7.950187 75.028821-7.950187S72.82907-6.766625 72.82907-5.738481C72.82907-5.128767 73.355098-5.128767 73.390963-5.128767C73.642022-5.128767 73.952856-5.308095 73.952856-5.69066C73.952856-6.025405 73.725708-6.252553 73.390963-6.252553C73.283367-6.252553 73.259456-6.252553 73.223591-6.240598C73.450739-7.053549 74.096318-7.603487 74.873404-7.603487C75.889593-7.603487 76.511262-6.75467 76.511262-5.654795C76.511262-4.638605 75.925459-3.753923 75.244014-2.988792L72.82907-.286924V0H77.192707L77.503541-2.008468Z'/>
<path d='M81.969789-5.956369C81.969789-7.000454 81.180748-7.733704 80.296065-7.733704C79.722217-7.733704 79.379502-7.367079 79.19619-6.976544C79.19619-7.638063 79.25198-8.219881 79.538905-8.706058C79.778008-9.104564 80.184484-9.431338 80.686601-9.431338C80.846003-9.431338 81.212628-9.407428 81.395941-9.128474C81.037286-9.112534 81.005405-8.84155 81.005405-8.753879C81.005405-8.514775 81.188718-8.379283 81.38-8.379283C81.523462-8.379283 81.754596-8.466955 81.754596-8.769819C81.754596-9.248026 81.395941-9.638561 80.678631-9.638561C79.570785-9.638561 78.446999-8.586506 78.446999-6.864962C78.446999-4.705062 79.451233-4.171064 80.224334-4.171064C80.6069-4.171064 81.021345-4.274676 81.38-4.617391C81.698805-4.928225 81.969789-5.26297 81.969789-5.956369ZM81.220598-5.96434C81.220598-5.557864 81.220598-5.207179 81.061196-4.920255C80.853973-4.55363 80.575019-4.410168 80.224334-4.410168C79.801918-4.410168 79.538905-4.705062 79.419353-4.928225C79.23604-5.28688 79.2201-5.828848 79.2201-6.131712C79.2201-6.920753 79.650486-7.510541 80.264185-7.510541C80.66269-7.510541 80.901794-7.303318 81.053226-7.024364C81.220598-6.72947 81.220598-6.370815 81.220598-5.96434Z'/>
<path d='M86.203911-5.701326C86.203911-6.362845 85.677883-6.968574 84.864932-7.143916C85.494571-7.367079 85.964807-7.909047 85.964807-8.546656S85.247497-9.638561 84.418606-9.638561C83.565804-9.638561 82.920225-9.176295 82.920225-8.570566C82.920225-8.275672 83.119477-8.14815 83.3267-8.14815C83.573774-8.14815 83.733176-8.323493 83.733176-8.554626C83.733176-8.84952 83.478132-8.961102 83.30279-8.969072C83.637535-9.407428 84.251233-9.431338 84.394695-9.431338C84.601918-9.431338 85.207647-9.367577 85.207647-8.546656C85.207647-7.988748 84.976513-7.654003 84.864932-7.526482C84.625829-7.279408 84.442516-7.263468 83.956339-7.231587C83.804907-7.223617 83.741146-7.215647 83.741146-7.112036C83.741146-7.000454 83.812877-7.000454 83.948369-7.000454H84.346875C84.976513-7.000454 85.375019-6.538188 85.375019-5.701326C85.375019-4.705062 84.809141-4.410168 84.386725-4.410168C83.948369-4.410168 83.350611-4.56957 83.071657-4.991986C83.358581-4.991986 83.557834-5.175298 83.557834-5.438312C83.557834-5.693356 83.374521-5.876668 83.119477-5.876668C82.904284-5.876668 82.681121-5.741176 82.681121-5.422372C82.681121-4.665211 83.494073-4.171064 84.402665-4.171064C85.46269-4.171064 86.203911-4.904315 86.203911-5.701326Z'/>
<path d='M98.01624-2.988792C98.01624-3.227895 97.789092-3.227895 97.62172-3.227895H91.106153C90.938781-3.227895 90.711633-3.227895 90.711633-2.988792S90.938781-2.749689 91.106153-2.749689H97.62172C97.789092-2.749689 98.01624-2.749689 98.01624-2.988792Z'/>
<path d='M106.576133 0V-.3467H106.205523C105.153468-.3467 105.117603-.490162 105.117603-.920548V-7.663263C105.117603-7.938232 105.117603-7.950187 104.878499-7.950187C104.591575-7.627397 103.993817-7.185056 102.762435-7.185056V-6.838356C103.037403-6.838356 103.635162-6.838356 104.292696-7.149191V-.920548C104.292696-.490162 104.256831-.3467 103.204776-.3467H102.834166V0C103.156955-.02391 104.316606-.02391 104.711127-.02391S106.253344-.02391 106.576133 0Z'/>
</g>
</svg>.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Fri, 23 May 2014 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/scala-notes-number-madness/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>Scala Notes: Getting Started</title>
    <link>https://growingliberty.com/blog/scala-notes-getting-started/index.html</link>
    <description><![CDATA[<p>This is the first in a series of very short articles I am calling
<a href="/blog/categories/scala-notes/">scala-notes</a> where I will share my notes and or my
favorite links about Scala related topics. Hopefully this will prove to be a
motivator for me to mine the giant stack of paper notes I have written about
scala… In any case I hope this exercise proves useful for somebody.</p>
<h2 id="getting-started-with-scala">Getting Started with Scala</h2>
<p>When you get started with a language you need a <!--more--> “Hello, World”.
(This example works if you <a href="http://www.scala-lang.org/download/">install
Scala</a>, rather than using it from <code>SBT</code>.)
So here is one:</p>
<pre><code> $$ vi HelloWorld.scala</code></pre>
<div class="sourceCode" id="cb2"><pre class="sourceCode scala"><code class="sourceCode scala"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> HelloWorld <span class="kw">extends</span> App {</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">println</span>(<span class="st">&quot;Hello, world!&quot;</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<pre><code> $$ scalac HelloWorld.scala
 $$ scala HelloWorld
  Hello, world!</code></pre>
<h3 id="what-is-scala">What is Scala?</h3>
<p>The official answer is <a href="http://www.scala-lang.org/what-is-scala.html">here</a>,
but to me it is simply an object-functional programming language on the JVM.
The more interesting part is the functional part, but because it also supports
object oriented design on the JVM, it makes for a simpler transition from Java
than say moving directly to <a href="http://haskell.org/">Haskell</a>. If you are a Java
programmer <a href="/blog/why-java-programmers-should-avoid-scala/">maybe you should avoid scala</a>? Don’t say I
didn’t warn you. ;-)</p>
<h3 id="functional">Functional</h3>
<p>Here are some functional programming links (mostly videos). Some relate to scala more than others.</p>
<ul>
<li><a href="http://lambda-the-ultimate.org/node/1976">Great link for many other links</a></li>
</ul>
<h4 id="videos">Videos</h4>
<ul>
<li><p><a href="http://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-Programming-Fundamentals">Erik Meijer <strong><em>Functional Programming
Fundamentals</em></strong></a>
Thirteen lectures.</p></li>
<li><p><a href="http://channel9.msdn.com/Tags/erik+meijer">Erik Meijer</a> Many useful videos.</p></li>
<li><p><a href="http://channel9.msdn.com/Tags/brian+beckman">Brian Beckman</a> Many useful videos.</p></li>
<li><p><a href="http://www.youtube.com/playlist?list=PLE741AD926AA152C4">UCB SICP lectures playlist</a></p></li>
<li><p><a href="http://vimeo.com/68331937">Bodil Stokke: <strong><em>What Every Hipster Should Know About Functional
Programming</em></strong></a> A fun look at some functional
programming terms.</p></li>
<li><p><a href="https://www.youtube.com/watch?v=JeK979aqqqc&amp;index=3&amp;list=PLXb9Fevl5bxDUy7Zt7rFD3XWCaoRLTDPd">Functional Thinking with Neal
Ford</a>
A good introduction to the kind of thinking used in Functional Programming.
Includes examples in various programming languages (not just Scala). Gets
especially pragmatic at about 31:00.</p></li>
</ul>
<h4 id="books">Books</h4>
<ul>
<li><p><a href="http://manning.com/bjarnason" title="Functional Programming in Scala"><strong><em>Functional Programming in Scala</em></strong> by Paul Chiusano and Rúnar
Bjarnason</a>
This is an outstanding book. It can be treated as a course in Scala by going
through the exercises in each chapter.</p></li>
<li><p><a href="http://mitpress.mit.edu/sicp/" title="SICP: Structure and Interpretation of Computer Programs">SICP: <strong><em>Structure and Interpretation of Computer Programs</em></strong>, by Abelson,
Sussman, and Sussman</a> Read or re-read this one. No,
seriously, do it right now. You will be glad you did.</p></li>
</ul>
<h3 id="general-scala">General Scala</h3>
<h4 id="links">Links</h4>
<ul>
<li><p><a href="http://docs.scala-lang.org/tutorials/tour/tour-of-scala.html"><strong><em>A Tour of
Scala</em></strong></a> A
nice tutorial.</p></li>
<li><p><a href="http://twitter.github.io/scala_school/"><strong><em>Scala School!</em></strong> <em>From ∅ to Distributed
Service</em></a> Twitter’s excellent
tutorial.</p></li>
<li><p><a href="http://docs.scala-lang.org/glossary/">A Glossary of Scala and Functional Programming terms taken from the
<strong><em>Programming in Scala</em></strong> book</a></p></li>
<li><p><a href="http://brenocon.com/scalacheat/"><strong><em>Cheat Sheet for Scala Syntax</em></strong></a> or
<a href="http://docs.scala-lang.org/cheatsheets"><strong><em>Cheatsheet</em></strong> at scala-lang.org</a>
The version at <a href="http://docs.scala-lang.org/cheatsheets">scala-lang.org</a> is a
copy of Brendan O’Connor’s <em>Cheat Sheet for Scala Syntax</em>.</p></li>
<li><p><a href="https://github.com/lrytz/progfun-wiki/blob/gh-pages/CheatSheet.md">progfun wiki
cheatsheet</a>
This originated from the <a href="https://www.coursera.org/course/progfun">Functional Programming Principles in
Scala</a> class. I can’t recommend the
class enough.</p></li>
<li><p><a href="https://github.com/sjuvekar/reactive-programming-scala/blob/master/ReactiveCheatSheet.md">Reactive
cheetsheet</a>
This originated from the <a href="https://www.coursera.org/course/reactive">Principles of Reactive
Programming</a> class. Really great
class.</p></li>
<li><p><a href="http://stackoverflow.com/tags/scala/info">Scala information from
stackoverflow.com</a> Good stuff
here. Some overlap but that is fine.</p></li>
<li><p><a href="http://docs.scala-lang.org/style/"><strong><em>Scala style guide</em></strong></a> Be aware that
some of these style decisions will save you headaches. One example is the
<a href="http://docs.scala-lang.org/style/nested-blocks.html#curly_braces">curly
brace</a>
alignment. It has been difficult to change my brace style to fit the
recommendation but it is better than dealing with parsing problems.</p></li>
<li><p><a href="https://groups.google.com/forum/#!forum/scala-user"><strong><em>scala user</em></strong> google
group</a></p></li>
</ul>
<h4 id="books-1">Books</h4>
<ul>
<li><p><a href="http://www.scala-lang.org/docu/files/ScalaByExample.pdf"><strong><em>Scala by Example</em></strong> by Martin
Odersky</a> Useful
book. This link to a PDF version.</p></li>
<li><p><a href="http://www.artima.com/pins1ed/"><strong><em>Programming in Scala, First Edition</em></strong> by Martin Odersky, Lex Spoon, and
Bill Venners</a> The link is to the first
edition which is made freely available online.</p></li>
<li><p><a href="http://typesafe.com/resources/book/scala-for-the-impatient"><strong><em>Scala for the Impatient</em></strong> by Cay
Horstmann</a> The
link is to a freely available subset of the book in PDF format.</p></li>
<li><p><a href="http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf"><strong><em>The Scala Language Specification</em></strong> Scala
Reference</a>
I consider this the Scala Reference rather than a true <em>specification</em>
regardless of the title.</p></li>
</ul>
<p>If you have some favorite links for <em>getting started with Scala</em>, then please
share them in a comment.</p>]]></description>
    <pubDate>Wed, 05 Mar 2014 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/scala-notes-getting-started/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>Why Java programmers should avoid Scala</title>
    <link>https://growingliberty.com/blog/why-java-programmers-should-avoid-scala/index.html</link>
    <description><![CDATA[<p>I have been writing Java professionally since 1997 and while the JVM (Java
Virtual Machine) continues to dominate enterprise development, that is not all
that has kept me using it. I have always liked Java.</p>
<p>A while ago I was chatting about how I found some aspects of Haskell and Go
really <!--more--> interesting, when <a href="http://twitter.com/BeepDog">BeepDog</a>
mentioned Scala. Well, at the time I felt I had no <em>need</em> of Scala because</p>
<blockquote>
<p>If I wanted to use the JVM I would use Java, and if I did not want to use the
JVM I could use Go, Haskell, or whatever other language best fit the needs of
the project.</p>
</blockquote>
<p>But then I did not <em>know</em> Scala. An EPFL Coursera class, <a href="https://www.coursera.org/course/progfun">Functional
Programming Principles in Scala</a>
opened and being out of excuses, I took the class. I was so impressed that I
took the next one, <a href="https://www.coursera.org/course/reactive">Principles of Reactive
Programming</a>, too. There is no
fitting exclamation, or emoticon to describe the experience.</p>
<p>I can’t list all the advantages of using Scala on the JVM, because I keep
finding new ones. Here are a few just to get things started.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<ul>
<li><p>An improved, static type system</p></li>
<li><p>Native support for Functional Programming</p></li>
<li><p>Native support for Object Oriented Programming</p></li>
<li><p>Clever concurrency solutions</p></li>
<li><p>A more concise and expressive syntax</p></li>
<li><p>Runs on the JVM fully interoperable with Java.</p></li>
</ul>
<blockquote>
<p>Scala classes can call Java methods, create Java objects, inherit from Java
classes and implement Java interfaces. </br>
<em>Scala Language Specification, version 2.8</em></p>
</blockquote>
<p>The above advantages and more makes Scala the pragmatic choice for productive,
maintainable, <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>, and
performant code on the JVM platform.</p>
<p>So with all those advantages, why avoid it? Because something happens when you
learn Scala…</p>
<p>I continue to experience situations where I find some aspect of the Scala
syntax or some framing of a problem awkward only to have an epiphany. The
result of the epiphany is an astonishing change in my way of thinking. Avoid
Scala because once you learn it you will be forever changed and will never
again approach problems the same way. Scala is improving, and promising
languages appear all the time. Who knows where the journey will end.</p>
<p>If you are content with using the JVM just as you do now then please stick with
Java, but stay away from Scala. ;-)</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>There are many more, simply search the web… Many people even explain
<em>why</em> these characteristics are advantages, I will save the space.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Wed, 22 Jan 2014 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/why-java-programmers-should-avoid-scala/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>Machine Virtualization as a Development Tool: Part 2</title>
    <link>https://growingliberty.com/blog/machine-virtualization-as-a-development-tool-part-2/index.html</link>
    <description><![CDATA[<h2 id="prologue">Prologue</h2>
<p>This is the second of a two article series about using machine virtualization
as a development tool. It focuses on the question of <strong><em>how</em></strong>. The first
article is found
<a href="/blog/machine-virtualization-as-a-development-tool-part-1/">here</a> and focuses
on the question of <strong><em>what</em></strong>.</p>
<h2 id="using-vms">Using VMs</h2>
<p>It is time now to get to the specifics of using a VM solution, in this
case<span></span><!--more--> VirtualBox.</p>
<h4 id="guest-additions">Guest Additions</h4>
<p>Guest Additions are vendor specific add-ons that permit some useful features of
VirtualBox. The Guest Additions should be installed into the guest OS when
creating a base VM. See the VirtualBox
<a href="https://www.virtualbox.org/manual/ch04.html" title="Guest Addtions for Virtualbox">documentation</a> for details.</p>
<h4 id="shared-folders">Shared Folders</h4>
<p>One of the important features that Guest Additions permits is a <a href="https://www.virtualbox.org/manual/ch04.html#sharedfolders" title="Shared Folders for VirtualBox">shared
folder</a>. A shared folder permits the sharing of a host
directory to the guest VM. This is a nice way to <em>deploy code</em> or otherwise
share content with the VM. If content in a shared folder is stateful, such as
code, then it should be managed by a version control system, such as
<a href="http://git-scm.com">git</a>.</p>
<h4 id="snapshots">Snapshots</h4>
<p>A <a href="https://www.virtualbox.org/manual/ch01.html#snapshots" title="snapshots">snapshot</a>
saves the state of a VM such that when the snapshot is restored the VM
continues exactly where it left off. When a VM is started back at a point in
time of a snapshot, remounted network drives and shared folders may have
different contents than when the snapshot was made because the content is
sourced externally to the VM. This is in contrast to virtual drives which by
default will be restored bit for bit.</p>
<p>Snapshots are useful for a developer to test a new release or to rollback a
<em>site</em> to an older state to work on a bug-fix. For example, one might be
working on a new release of an application, only to have an emergency bug-fix
take precedence over work on the new release. It is then a simple task to
snapshot the VM to save the state for the new release, then restore a clone of
the VM as it existed for the code experiencing the bug, right along with
checking out the matching code from one’s
<a href="https://en.wikipedia.org/wiki/Software_configuration_management" title="Software Configuration Management">SCM</a>, like git. Then when the bug is fixed a similar
process is performed to resume work on the new release. This ensures that not
only does the code match production, but the other aspects of the host match as
well such as the database<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, web server settings, etc.</p>
<p>Taking a snapshot is not a big deal so when in doubt, take one. Always take a
snapshot to capture current state before restoring a snapshot. Beyond that, it
is a good idea to take a snapshot before making a time consuming change to the
VM, and with each <em>code promotion</em>.</p>
<p>It is wise to shut-down the VM prior to taking a snapshot because when one
takes a snapshot of a running VM the memory state of the machine is also stored
in the snapshot. This extra data is only needed if it is important to restore
the snapshot to the <em>running</em> state, and it can occupy as much disk space as
the memory defined for the VM.</p>
<p>When making a snapshot, VirtualBox provides a field that can be used to label
the snapshot. A description field is also provided. Be sure to use the
description field to include any information that is needed to fully restore
the state of the snapshot. For example, include the git tag<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> needed to
revert contents of a shared folder.</p>
<p>In the following example, the snapshot is labeled to show that it was taken
prior to doing some database maintenance. The description field contains the
git data needed to restore a shared folder to the correct condition of the
snapshot. The command <code>git log --decorate --oneline -1</code> is a handy way to get
the latest commit information, but ideally one should be creating an annotated
tag to go with the snapshot. An annotated tag could be labeled the same way as
the snapshot, thus clarifying the snapshot to tag relationship from examination
of both the code and the list of snapshots.</p>
<figure>
<img src="/images/posts/vm-snapshot.png" title="VM-Snapshot" alt="vm-snapshot" />
<figcaption aria-hidden="true">vm-snapshot</figcaption>
</figure>
<p>The power of a snapshot is the ability to capture a point in time. However, to
be able to make full use of the <em>point in time</em>, we may use snapshots with
clones.</p>
<h4 id="clones">Clones</h4>
<p>As one would expect,
<a href="https://www.virtualbox.org/manual/ch01.html#clone" title="cloning">cloning</a> a VM is
making a copy of a VM. The source for a clone can be a VM’s current state or a
particular snapshot.</p>
<p>Let’s consider the following where one is working on a web development project
where git is being used to manage the stateful content of a shared folder:</p>
<blockquote>
<p>A critical bug is found in production. We must roll-back to a snapshot to
work a bug then later resume the current state…</p>
</blockquote>
<p>There are two ways to handle this:</p>
<h5 id="use-snapshots">Use snapshots</h5>
<ol>
<li><p>Shutdown the VM so we do not preserve the VM run-time data.</p></li>
<li><p>Stash content of shared folder.</p>
<pre><code> $$ git stash save &quot;Working on customer lookup when ticket ID 113245 was received&quot;</code></pre></li>
<li><p>Capture the full stash information for use in the snapshot description.</p>
<pre><code> $$ git stash list
 stash@{0}: On dev: Working on customer lookup when ticket ID 113245 was received</code></pre></li>
<li><p>Take a new snapshot of the current state so we have a place to return to when the bug is fixed.
Include the stash information in the snapshot description.</p></li>
<li><p>Restore the VM to the snapshot required to fix the bug. (In this case the snapshot created for the v1.0.1 code promotion.)</p></li>
<li><p>Restore the shared folder to the correct place<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> for fixing the bug.</p>
<pre><code> $$ git checkout -b b1.0.1-113245 tags/v1.0.1 </code></pre></li>
<li><p>Fix the bug…</p></li>
<li><p>Restore the VM to the snapshot made with our stash comment.</p></li>
<li><p>Restore the shared folder to the state that corresponds to the snapshot we just restored.</p>
<pre><code> $$ git checkout dev
 $$ git stash list
 stash@{0}: On dev: renaming serialized files
 stash@{1}: On dev: Working on customer lookup when ticket ID 113245 was received
 $$ git stash pop stash@{1}</code></pre></li>
</ol>
<h5 id="use-snapshots-with-a-clone">Use snapshots with a clone</h5>
<p>What if a co-worker can take on the bug fix while you continue to work on your
current <a href="https://en.wikipedia.org/wiki/Sprint_%28scrum%29#Sprint" title="scrum sprint">sprint</a>? If that is the case, then we can simplify the process down to
creating a clone VM for the co-worker.</p>
<ol>
<li><p>Select the correct snapshot from the snapshots list. (In this case the snapshot created for the v1.0.1 code promotion.)</p></li>
<li><p>Right-click the snapshot and select clone, or click clone button (pictured as a sheep).</p></li>
<li><p>Name the clone including the source VM name, snapshot name and the ticket ID 113245.</p></li>
<li><p>If your co-worker uses the same network as you, then click the <strong>Reinitialize the MAC address of all network cards</strong>.
Note that you may need to boot into the VM and update network settings to reflect the new MAC addresses.</p></li>
<li><p>Select a <strong>full clone</strong> rather than a <strong>linked clone</strong>, so that the clone can be operated independently.</p></li>
<li><p>When prompted for the what parts of the snapshot tree to clone, select <strong>Current Machine State</strong>. It is confusing but <strong>Current Machine State</strong>
is the current state of the VM at the point in time of the snapshot you selected. This can result in a smaller VM because no other states,
and their requisite differencing disk images, need to be incorporated into the clone.</p></li>
</ol>
<h4 id="headless">Headless</h4>
<p>Once a VM is fully setup with SSH and the other tools I need, I find that the
GUI simply gets in the way. There are two easy ways to start a VM without
loading its console or its Graphic User Interface (GUI).</p>
<ol>
<li>Hold down the <code>shift</code> key when starting a VM from the GUI VirtualBox Manager.</li>
<li>Start a VM from the command line with <code>VBoxHeadless --startvm &lt;uuid|name&gt;</code>.</li>
</ol>
<h2 id="maximize-return-on-virtualization-investment">Maximize return on virtualization investment</h2>
<p>When using VM software, as with any tool, to be useful it must save more time
and headaches than it causes. There are a few things one can do to maximize
return on one’s time investment.</p>
<h3 id="separate-source-code-management-from-vm-management-and-identify-intersections">Separate source code management from VM management and identify intersections</h3>
<p>Keep source code and source code management on the host machine. Share code or
deployments with the VM guests by way of shared folders, do not store such
things on a VM’s virtual disk. This eliminates unnecessary dependencies on
guest VMs by confining code management to the host machine. This does not
preclude the use of remote git repositories. It simply ensures that the host is
handling those dependencies.</p>
<p>Identify intersections of state between guest VMs and managed code. This means
identifying important milestones in code state with SCM tags, such as a git
annotated tag. Also identify important milestones in VM state with snapshots.
Be clear that each time a tag is needed for the source code, a snapshot should
be made in the VM, and vice versa. Keep snapshot descriptions updated with tags
that correspond to the intersections of state between the VM and the code. See
<a href="#snapshots">Snapshots</a> above.</p>
<h3 id="use-pre-built-base-vms.">Use pre-built base VMs.</h3>
<p>It is my experience that the most time consuming aspect of using VM software is
creating the base VM. That said, creating a base VM from scratch is no more
complicated than installing an OS on a real machine, and once you have done it
once, I find it simpler than dealing with a real machine. A nice short-cut is
to use a pre-built base VM, then simply customize it if needed. The ideal place
to get a VM would be from whomever created the VM for your production
environment, if a VM is used in your production environment. Pre-built VM
images are sometimes called <em>virtual appliances</em>. Even though there are many VM
software technologies, a format exists called OVF (Open Virtualization Format)
that can be used to make a VM image saved in this format more compatible across
different VM software providers. This is supposed to make it possible, for
example, to use a VM created for VMWare on VirtualBox. VirtualBox has an
import mechanism to let one make use of these OVF VMs.</p>
<p>The following are two places with useful VMs.</p>
<ul>
<li><strong>Oracle:</strong> <a href="http://www.oracle.com/technetwork/community/developer-vm/index.html">developer-vm</a></li>
<li><strong>VMWare:</strong> <a href="https://solutionexchange.vmware.com/store/category_groups/virtual-appliances">virtual-appliances</a></li>
</ul>
<p>The place I find the most useful is <a href="http://www.vagrantbox.es">vagrantbox.es</a>,
but to properly use those images we need another tool called
<a href="#use-vagrant" title="Use Vagrant">Vagrant</a>.</p>
<h3 id="use-vagrant">Use Vagrant</h3>
<p>Use <a href="http://www.vagrantup.com/">Vagrant</a> to simplify and accelerate creating
your own base VMs. Once setup, it is possible to create a new VM, with a single
<code>vagrant up</code> command. The Vagrant build process is automated and controlled by
a written configuration, thus making Vagrant VMs reliable, predictable and
consistent.</p>
<p>I use Vagrant with <a href="https://puppetlabs.com/puppet/what-is-puppet/">Puppet</a> to
simplify and unify the provisioning tasks. The following example shows how to
use Puppet to ensure that git is installed in the guest VM. Notice that the
command does not identify a particular OS or distribution specific package
manger, like <a href="http://rpm.org">rpm</a> or <a href="http://yum.baseurl.org">yum</a>. Part of
the power of Puppet is that it can keep these specifics out of the
configuration and out of the way.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>package <span class="op">{</span> <span class="vs">&#39;git&#39;</span><span class="wa">:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">ensure</span> <span class="op">=&gt;</span> installed,</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<p>This lets one focus more on addressing the needs for a VM, and less on how
those needs must be achieved for a particular OS/distribution.</p>
<p>I created a
<a href="http://localhost:4000/blog/2013/07/03/machine-virtualization-as-a-development-tool">Habari</a>
development VM for <a href="http://growingliberty.com">GrowingLiberty.com</a> using
Vagrant. This implementation can be found in github at the following URL.</p>
<p><a href="https://github.com/mmynsted/vagrant-centos-php">github.com/mmynsted/vagrant-centos-php</a></p>
<p>The details are documented in the
<a href="https://github.com/mmynsted/vagrant-centos-php/blob/master/README.md">Readme.md</a>.
This implementation uses a base Vagrant box from
<a href="http://www.vagrantbox.es">vagrantbox.es</a>, showing that one can further
simplify provisioning a base VM by using a pre-built Vagrant base box.</p>
<p>My preference is to use Vagrant to create a base VM, then clone it to a new VM
that is no longer dependent on Vagrant. This way I am free to continue to
improve my Vagrant implementation without adversely affecting actively used
VMs. The example above shows how one could use Puppet as part of the original
provisioning and then use traditional shell commands from the new clone. Puppet
is still installed so one can interact with the VM in the way that seems most
natural.</p>
<p>The Vagrant and Puppet combination enables one to quickly translate a VM build
investment to new and changing needs.</p>
<h2 id="conclusion">Conclusion</h2>
<p>A virtual machine is a software based abstraction of a physical machine. This
abstraction permits reduced maintenance time, improved testing, and making
better use of both remote and local machine resources. Using a local VM can
become a seamless part of one’s development process, can help one be better
organized, and more productive.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Database state would only be saved if the database was served from inside
the same VM or if external, one managed its state much like managing state
for source code delivered through a shared folder.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Be sure to use an <a href="http://git-scm.com/book/en/Git-Basics-Tagging#Annotated-Tags">annotated git
tag</a> so the
full information is captured.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>Creating a new branch b1.0.1-113245 from tag <code>v1.0.1</code> on the <code>dev</code>
branch.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Tue, 13 Aug 2013 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/machine-virtualization-as-a-development-tool-part-2/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>
<item>
    <title>Machine Virtualization as a Development Tool: Part 1</title>
    <link>https://growingliberty.com/blog/machine-virtualization-as-a-development-tool-part-1/index.html</link>
    <description><![CDATA[<h2 id="prologue">Prologue</h2>
<p>The use of Virtual Machines for web development is becoming ubiquitous, and with good reason.</p>
<p>This is the first of a two article series about using machine virtualization as
a development tool. It focuses on the question of <strong><em>what</em></strong>. The second
article is found
<a href="/blog/machine-virtualization-as-a-development-tool-part-2/">here</a> and focuses
on the question of <strong><em>how</em></strong>.</p>
<h2 id="what-are-virtual-machines-for-a-software-developer">What are Virtual Machines for a software developer?</h2>
<p>A <a href="https://en.wikipedia.org/wiki/Virtual_machine">Virtual Machine</a> (VM) is a
software based abstraction of a physical machine. This abstraction makes it
possible to <span></span><!--more--> manage and control access to the actual
hardware. Hardware, that does not physically exist, can be emulated.</p>
<h3 id="here-is-how-i-recall-the-explosion-in-use-of-virtual-machines">Here is how I recall the explosion in use of Virtual Machines…</h3>
<p>When I first became a professional software developer I worked for IBM. The
first VM I used for development was VM/CMS. It was a remote, centrally managed
VM, and a sensible abstraction away from big iron mainframes with big
consequences if something went wrong.</p>
<p>It was not too long until the PC revolution changed the way applications were
used, written and delivered. The 3270 terminal (or terminal emulator) was
largely replaced with the web browser and Client-Server applications. It was
around that time that I displayed a picture on my office wall of a proud man
standing in a giant warehouse stacked with PC servers. His arms were spread so
one could get a feel of scale; a tiny man standing in such a giant warehouse
with an incalculable number of servers. The picture was from a book where the
man described his successful journey to replace a mainframe with PC servers.
This was IBM, so I am sure the message I should have gained from the book was
something like <strong><em>“Wow look at all the hardware that people would buy, and all
the services they would need, to support their desire to join this PC
revolution!”</em></strong></p>
<p>There is something to be said for the decentralization of application
development accelerating innovation, but what I saw in the picture was
<strong><em>“Maintenance nightmare!”</em></strong></p>
<p>If I recall correctly, the move from centrally managed mainframes to cheap
distributed PC infrastructure, this PC revolution, and its requisite services,
were quite profitable for IBM. There must be some irony there.</p>
<p>It was a while later before PC architecture servers, with enough surplus power
to support virtualization, became cost effective. Until that time the big boys
(think IBM, HP, Sun, and many others) continued to offer expensive, but
powerful machines with hardware based virtualization (type 1
<a href="https://en.wikipedia.org/wiki/Hypervisor">hypervisor</a>), while the PC guys
began to learn the true costs of maintaining so many physical machines.</p>
<p>What do you do if you want the benefits of virtualization but your hardware
(architecture) does not meet the <a href="https://en.wikipedia.org/wiki/Popek_and_Goldberg_virtualization_requirements" title="Popek and Goldberg virtualization requirements at wikipedia">Popek and Goldberg virtualization
requirements</a>? Well, you
write a software <a href="https://en.wikipedia.org/wiki/Hypervisor">hypervisor</a> (type 2
hypervisor) like VMWare, and change the world. This kind of VM software made
it possible to emulate a number of PC servers on a larger host, with room to
scale up as needs grew. Surplus power could then be traded for better
maintainability, reliability, predictability and separation.</p>
<p>All that brings us to today where VMs (Virtual Machines) are used throughout
the lifecycle of application development and deployment, especially for web
applications where PC hardware is still largely ubiquitous.</p>
<p>There are a variety of good VM solutions, but for the sake of simplicity I will
focus the rest of this article on one, VirtualBox. VirtualBox is currently free
and can be found <a href="https://www.virtualbox.org">here</a>.</p>
<h2 id="what-can-it-do-for-me">What can it do for me?</h2>
<p>OK, that is all well and good for system administrators and infrastructure
planners, but what can it do for me as a developer?</p>
<h3 id="reduce-maintenance-time">Reduce maintenance time</h3>
<p>Changing a network card or adding RAM to a virtual machine is as simple as
changing a setting. This is true whether the host is a remotely maintained
server, or your laptop. Virtual Machines are portable, so if the physical
hardware is acting up, the VM can be moved to another host until the original
is repaired or replaced. One could even continue to work on a clone while
software is being upgraded on an original VM. Need a development server and all
existing servers are at capacity? No problem, simply fire up a new VM.</p>
<p>It is quicker and easier to update a VM in concert with a closely matching
production machine, than it is to update a number of physical test machines,
developer laptops, workstations, etc. This is not simply a matter of scale,
updating a single image rather than a number of physical boxes, but also a
matter of compatibility. The compatibility becomes important if it permits one
to apply the same changes to production and test VMs with tools such as Puppet,
with predictable results.</p>
<p>Reduced maintenance and provisioning time result in increases of developer
productivity, even if the developer never deals with the maintenance or
provisioning him or her self.</p>
<h3 id="improve-testing">Improve testing</h3>
<p>There are characteristics of VMs that are useful for testing. VM images are
software, so they only need to consume resources when they are needed, unlike
their physical counterparts. This makes it cheap to keep many test images.
Because VMs are portable and can be copied and cloned, it is simple to make
them available to whomever needs them, even to many people simultaneously.</p>
<h4 id="undo-changes-with-roll-back">Undo changes with roll-back</h4>
<p>VMs make it quick and safe to test dramatic environmental changes. This is
because changes can be completely undone with a simple roll-back.</p>
<p>I recall a third party software upgrade that resulted in the <em>upgraded</em> server
becoming completely unusable. Performing an un-install would have still left
the server damaged. A roll-back restored the server to the state exactly as it
was prior to the upgrade. I can not imagine the nightmare had this server not
been a VM.</p>
<h4 id="better-match">Better match</h4>
<p>Testing is more efficient when all factors, other than those being tested, are
consistent and thus eliminated from consideration. This way when differences
are observed they can be expected to be the result of the factors being tested.
Nobody wants to experience a problem in <em>production</em> that could not be found in
<em>test</em>, but when these environments are different, and the differences are not
the factors being tested, such problems can happen.</p>
<p>It is possible for one to create a VM that more closely matches <em>production</em>
(also likely a VM) than it would be to configure one’s laptop, workstation, or
even a physical test machine to do the same. This is in part because a laptop
or workstation is designed to meet different needs than for example, a
dedicated web server.</p>
<p>An example might be that one’s development workstation runs
<a href="https://www.archlinux.org" title="archlinux">archlinux</a> and one’s hosting provider,
or a company <em>production</em> environment, uses <code>Centos 6</code>. To address the
discrepancy, one could create a <code>Centos 6</code> base VM that closely matches
production. In some cases such a VM can be derived from the actual VM used in
production.</p>
<p>At this point I should mention that many developers use an IDE (Integrated
Development Environment) both for writing code and for local testing. I avoid
IDEs. To me, they divert one’s attention from learning the language and
development tools, to learning the IDE. I find that I get better results by
writing a script, an editor macro or by re-examining what I am doing, than I do
from using an IDE shortcut.</p>
<p>I worked with a developer who experienced a really frustrating and intractable
<em>code</em> problem. We found that the problem was not with his code but was simply
a flaw in the way his IDE executed it. The problem did not, and could not,
exist anywhere else.</p>
<p>I bring this up because I find that running code, especially tests, in an IDE
exacerbates the problems of run-time differences between a local development
and production environment. If you are hell-bent on using an IDE, I suspect
you could configure it to use a local VM for testing, etc. After all,
development tools should conform to the needs of the developer, not the other
way around.</p>
<h3 id="make-better-use-of-your-local-machine">Make better use of your local machine</h3>
<p>Many developers are familiar using VMs as part of a remote, company development
server pool, but few use VMs locally. VM solutions work well on local machines
too. Independent contractors have been taking advantage of virtual machines for
years. Visit a new client and create a fresh VM. That VM can then be
customized to the client and saved for the next time the client calls.
Meanwhile, the host machine is kept safe from constant alteration. This also
works well when one encounters a client running a different OS. Have a Mac or
Linux laptop and the customer runs Windows or FreeBSD? No problem, just use a
VM of whatever is needed.</p>
<p>The second article in this series will focus on how to use machine
virtualization as a development tool.</p>]]></description>
    <pubDate>Sat, 03 Aug 2013 00:00:00 UT</pubDate>
    <guid>https://growingliberty.com/blog/machine-virtualization-as-a-development-tool-part-1/index.html</guid>
    <dc:creator>Growing Liberty LLC</dc:creator>
</item>

    </channel>
</rss>
