<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>elijah.run</title>
    <subtitle>A blog about tech, media, and art</subtitle>
    <link rel="self" type="application/atom+xml" href="https://elijah.run/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://elijah.run"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-28T00:00:00+00:00</updated>
    <id>https://elijah.run/atom.xml</id>
    <entry xml:lang="en">
        <title>What&#x27;s Good #17</title>
        <published>2026-02-28T00:00:00+00:00</published>
        <updated>2026-02-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2026/02/"/>
        <id>https://elijah.run/whats-good/2026/02/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2026/02/">&lt;h1 id=&quot;indika&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1373960&#x2F;&quot;&gt;Indika&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;indika.jpg&quot; alt=&quot;indika.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Oh my god.
Fuck yeah dude.
Video games rock.
Ok I guess we&#x27;re just going to casually play a game that changes how we think of games &lt;em&gt;every month&lt;&#x2F;em&gt; now?&lt;&#x2F;p&gt;
&lt;p&gt;Indika is beautiful, going for a mostly photo-real style to help deliver the grounded story telling it&#x27;s going for.
That story, of course, is that you are a nun who is having a mental breakdown and all the other nuns hate you so they give you a more or less impossible task that you totally abandon.
It is hilarious, thought provoking, and well produced in every way.&lt;&#x2F;p&gt;
&lt;p&gt;My favorite detail of the game is noticing how things are constantly getting... slightly... bigger... until they&#x27;re like... impossible.&lt;&#x2F;p&gt;
&lt;p&gt;Also the level with the rotated mirror rooms blew my fucking mind.
I literally had to put my Deck down and put my brain back together.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s like 4 hours.
Just play it.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;solitaire-s&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1988540&quot;&gt;Solitaire(s)&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;zachtronics-solitaire.jpg&quot; alt=&quot;zachtronics-solitaire.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Through a bunch of coincidental timings I found myself feeling very lonely in January.
I was traveling for work where I wasn&#x27;t super friendly with my co-workers, a few friends were moving on and I would see them far less, my other friends were busy or focusing on other relationships, you know how it goes.&lt;&#x2F;p&gt;
&lt;p&gt;So somewhat ironically at first, I downloaded the Microsoft Solitaire app for Android and got really into it.
I&#x27;m not any good at Solitaire (I&#x27;m not good at most videogames, so that&#x27;s not much of a statement), but I do enjoy the different types and how they train your brain to play the game out a few steps.
Klondike, Spider, FreeCell, Pyramid, TriPeaks, they all force you to approach the problem of &quot;stack cards good&quot; in different ways.&lt;&#x2F;p&gt;
&lt;p&gt;Then I remembered Zachtronics has a Solitaire Collection and I bought it &lt;em&gt;full price&lt;&#x2F;em&gt; because I was pretty sure this was going to be even better than boring old Solitaire.&lt;&#x2F;p&gt;
&lt;p&gt;And it was!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sawayama Solitaire (Last Call BBS), which is basically just even harder Klondike (I&#x27;m not sure why this is rated the easiest, it kicks my ass every time)&lt;&#x2F;li&gt;
&lt;li&gt;Sigmar&#x27;s Garden (Opus Magnum) is the most unique not involving cards at all!&lt;&#x2F;li&gt;
&lt;li&gt;Proletariat&#x27;s Patience (Exa Punks) is fair and I like that the gameplay is a metaphor!&lt;&#x2F;li&gt;
&lt;li&gt;Cribbage Solitaire (Mobius Front &#x27;83) is the most inventive of the standard card deck games and is &lt;em&gt;so difficult&lt;&#x2F;em&gt;. It doesn&#x27;t help that I&#x27;m also bad at Cribbage.&lt;&#x2F;li&gt;
&lt;li&gt;Cluj Solitaire (Molek Syntez) is my favorite for it&#x27;s minimalism in visuals and audio design.&lt;&#x2F;li&gt;
&lt;li&gt;Kabufuda Solitaire (Eliza) really forces me to look at patterns and pay closer attention than I usually do in a card game.&lt;&#x2F;li&gt;
&lt;li&gt;Shenzhen solitaire (Shenzhen I&#x2F;O) is OK but for some reason hasn&#x27;t grabbed me.&lt;&#x2F;li&gt;
&lt;li&gt;Fortune&#x27;s Foundation scares me. It is brutally difficult.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I appreciate the genre of Solitaire a lot more now and will probably continue to invest time into a previously overlooked genre.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;strange-pictures&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;9780063433090&quot;&gt;Strange Pictures&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;strange-pictures.jpg&quot; alt=&quot;strange-pictures.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This spooky mystery was an xmas gift that I went into totally blind.
The cover page was enticing but I really didn&#x27;t know what to expect.&lt;&#x2F;p&gt;
&lt;p&gt;Each chapter tells the story of a mystery which , spoiler, are all connected.
It offers a good balance between short stories, each chapter it it&#x27;s own mystery, and the over-arching narrative, trying to figure out the throughline.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;orange-world-and-other-stories&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;9780525656135&quot;&gt;Orange World and Other Stories&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;orange-world.jpeg&quot; alt=&quot;orange-world.jpeg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am starting to realize that I love magical realism.&lt;&#x2F;p&gt;
&lt;p&gt;I grew up thinking of myself as a sci-fi kid, but the more I read stories that more or less ditch the tech in favor of magic -- set in the modern day -- the more I think &quot;dang that&#x27;s cool I want more of that&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Specifically keep thinking about the Storm Rustler.
A beautiful story of an old man obsessed with proving he still has it in him to raise one more story to wreck havoc on the world.
And yes, all of that is literal and makes perfect sense in the context of the story.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;shell-game&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.shellgame.co&#x2F;&quot;&gt;Shell Game&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;shell-game-s1.jpg&quot; alt=&quot;shell-game-s1.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Shell Game is a podcast about a human, Evan Ratliff, taking AI hype at face value and putting it to the test.
I can send an AI to go to a meeting and take my place?
Challenge excepted.
AI is going to take all of our jobs and there will be a 1 person unicorn startup?
Let&#x27;s get cracking.&lt;&#x2F;p&gt;
&lt;p&gt;He pushes technology, and frankly social situations, beyond what you or I would be comfortable with, and juuuust up to their breaking points.
It results in a very informative show about what AI and and cannot do, and super entertaining too.&lt;&#x2F;p&gt;
&lt;p&gt;Shell game is an interesting podcast in 2026 because as you listen to it you can &lt;em&gt;feel&lt;&#x2F;em&gt; it getting dated.
He&#x27;s building things that have been solved dozens of ways by even more companies but he&#x27;s doing it &lt;em&gt;before&lt;&#x2F;em&gt; they are.
It&#x27;ll be a wild podcast to listen to once the Generative AI boom&#x2F;bust has settled as a snapshot into the questions we were asking and the ways we were trying to use this tech while it was being developed.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;in-this-economy-how-money-and-markets-really-work-audiobook&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;9780593727874&quot;&gt;In This Economy? How Money and Markets Really Work&lt;&#x2F;a&gt; (Audiobook)&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2026&#x2F;02&#x2F;in-this-economy.jpg&quot; alt=&quot;in-this-economy.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am a fan of Kyla Scanlon from TikTok and YouTube.
She has a great way of talking about Economics that meshes well with my own opinions -- which basically boil down to &quot;the system is broken, but the solution is human focused policies, not to burn it all down.&quot;
She understands how economics works (duh, she is very smart) but is very good at consistently tying that back to how the economy is people and how it should be for people and why it is failing to fulfill that need.&lt;&#x2F;p&gt;
&lt;p&gt;Was this a fun book to listen to?
Not really, but it was way better than the economics textbooks I&#x27;ve read so definitely a good resource if this topic is of interest.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Solitaire</title>
        <published>2026-02-25T00:00:00+00:00</published>
        <updated>2026-02-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/solitaire/"/>
        <id>https://elijah.run/backlog/solitaire/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/solitaire/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;backlog&#x2F;solitaire&#x2F;zachtronics-solitaire.jpg&quot; alt=&quot;zachtronics-solitaire.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Through a bunch of coincidental timings I found myself feeling very lonely in January.
I was traveling for work where I wasn&#x27;t super friendly with my co-workers, a few friends were moving on and I would see them far less, my other friends were busy or focusing on other relationships, you know how it goes.&lt;&#x2F;p&gt;
&lt;p&gt;So somewhat ironically at first, I downloaded the Microsoft Solitaire app for Android and got really into it.
I&#x27;m not any good at Solitaire (I&#x27;m not good at most videogames, so that&#x27;s not much of a statement), but I do enjoy the different types and how they train your brain to play the game out a few steps.
Klondike, Spider, FreeCell, Pyramid, TriPeaks, they all force you to approach the problem of &quot;stack cards good&quot; in different ways.&lt;&#x2F;p&gt;
&lt;p&gt;Then I remembered Zachtronics has a &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1988540&quot;&gt;Solitaire Collection&lt;&#x2F;a&gt; and I bought it &lt;em&gt;full price&lt;&#x2F;em&gt; because I was pretty sure this was going to be even better than boring old Solitaire.&lt;&#x2F;p&gt;
&lt;p&gt;And it was!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sawayama Solitaire (Last Call BBS), which is basically just even harder Klondike (I&#x27;m not sure why this is rated the easiest, it kicks my ass every time)&lt;&#x2F;li&gt;
&lt;li&gt;Sigmar&#x27;s Garden (Opus Magnum) is the most unique not involving cards at all!&lt;&#x2F;li&gt;
&lt;li&gt;Proletariat&#x27;s Patience (Exa Punks) is fair and I like that the gameplay is a metaphor!&lt;&#x2F;li&gt;
&lt;li&gt;Cribbage Solitaire (Mobius Front &#x27;83) is the most inventive of the standard card deck games and is &lt;em&gt;so difficult&lt;&#x2F;em&gt;. It doesn&#x27;t help that I&#x27;m also bad at Cribbage.&lt;&#x2F;li&gt;
&lt;li&gt;Cluj Solitaire (Molek Syntez) is my favorite for it&#x27;s minimalism in visuals and audio design.&lt;&#x2F;li&gt;
&lt;li&gt;Kabufuda Solitaire (Eliza) really forces me to look at patterns and pay closer attention than I usually do in a card game.&lt;&#x2F;li&gt;
&lt;li&gt;Shenzhen solitaire (Shenzhen I&#x2F;O) is OK but for some reason hasn&#x27;t grabbed me.&lt;&#x2F;li&gt;
&lt;li&gt;Fortune&#x27;s Foundation scares me. It is brutally difficult.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I appreciate the genre of Solitaire a lot more now and will probably continue to invest time into a previously overlooked genre.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>In This Economy?: How Money &amp; Markets Really Work by Kyla Scanlon (Audiobook)</title>
        <published>2026-02-20T00:00:00+00:00</published>
        <updated>2026-02-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/in-this-economy/"/>
        <id>https://elijah.run/backlog/in-this-economy/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/in-this-economy/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;backlog&#x2F;in-this-economy&#x2F;in-this-economy.jpg&quot; alt=&quot;in-this-economy.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Kyla Scanlon shows up regularly in my video feeds, across both TikTok and YouTube, so when I saw she wrote a book -- thanks to a Hank Green interview -- I requested it from my Library on Libby.
I was pleasently surprised to see that she read the book, which as a personality I trust I appreciated her giving voice to her words; it lended an air of credibility.&lt;&#x2F;p&gt;
&lt;p&gt;The economics in the book are solid, at least to a normie economics nerd like myself.
I appreciate that, similar to the Marketplace radio show&#x2F;podcast a running theme of &quot;The Stock Market is not The Economy, People are the Economy&quot;, focusing on how the economy fails people but how it can serve people better.&lt;&#x2F;p&gt;
&lt;p&gt;Over all I think it&#x27;s a sold introduction to economics for folks looking to get into the topic.
It is a little dense compared to other pop-sci-type books, but much much much lighter than actual economics textbooks.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Shell game</title>
        <published>2026-02-20T00:00:00+00:00</published>
        <updated>2026-02-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/shell-game/"/>
        <id>https://elijah.run/backlog/shell-game/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/shell-game/">&lt;p&gt;Shell Game is a podcast about things that aren&#x27;t what they seem, which in both cases are AI agents acting like real human people.
The show is funny and shocking with the hosts willingness to push things just a bit further than most people would for the sake of journalist rigor.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;backlog&#x2F;shell-game&#x2F;shell-game-s1.jpg&quot; alt=&quot;shell-game-s1.jpg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I think everybody should listen to this podcast.
It does a perfect job of describing the AI landscape &lt;em&gt;as it is&lt;&#x2F;em&gt; with all of it&#x27;s strengths and limitations without any of the hype that clouds the conversation.
If you keep hearing about AI and think it&#x27;ll steal your job or fizzle out (or somewhere between those extremes) check this out, it will ground you I promise.&lt;&#x2F;p&gt;
&lt;p&gt;In Season 1 the host, Evan Ratliff, creates an AI &quot;clone&quot; of his voice and wires it up to receive phone calls.
He then plays the most chaotic neutral game ever: let the bot talk to customer service folks.
He escalates the game from there to scammers, work meetings, friends and family, and the entire time he&#x27;s sharing these calls in podcast form of &lt;em&gt;his&lt;&#x2F;em&gt; voice but &lt;em&gt;not him&lt;&#x2F;em&gt; so you have to really listen to figure out if this is the robot Evan (it usually is) or real Evan.&lt;&#x2F;p&gt;
&lt;p&gt;One fun side-effect of listening to this show is that I am better at identifying the &quot;tells&quot; of a robo-voice.
Even if it sounds convincing and has responsive converstaions, the latency and &quot;what a weird way to say a normal thing&quot; word choice is a dead giveaway.
Of course tech is changing and my keen sense of what a robot sounds like will probably be out of date in like... a week.&lt;&#x2F;p&gt;
&lt;p&gt;The other side effect is that I have started to sound like the robot voice &lt;em&gt;just a little bit&lt;&#x2F;em&gt;.
It&#x27;s like when you listen to an audiobook and start to think in the reader&#x27;s voice; that happens to you too right?
Right?&lt;&#x2F;p&gt;
&lt;p&gt;I have finished Season 1.
I will update this post when I complete Season 2.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Indika (2024)</title>
        <published>2026-02-09T00:00:00+00:00</published>
        <updated>2026-02-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/indika/"/>
        <id>https://elijah.run/backlog/indika/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/indika/">&lt;p&gt;Indika is a hard game to describe because on paper, it&#x27;s a game about a nun failing to deliver a letter and having a reckoning with god... but that&#x27;s missing like 95% of what makes Indika a great game.&lt;&#x2F;p&gt;
&lt;p&gt;The stunning visuals make the mental breaks that Indika experiences hit so much harder than a more impressionist art style would impact; one of the few times that &quot;good graphics&quot; actually is worth necessary for a game.&lt;&#x2F;p&gt;
&lt;p&gt;The game is very... gamey.
From the 8-bit mini-games breaking up each act, to the omni-present points in the top left of the game -- the only UI element visible for most of the game, to the chip-tune music playing most of the game.
For a game about a nun, this feels like a &quot;gamers game&quot;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Orange World and Other Stories (Karen Russell, 2019)</title>
        <published>2026-02-08T00:00:00+00:00</published>
        <updated>2026-02-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/orange-world/"/>
        <id>https://elijah.run/backlog/orange-world/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/orange-world/">&lt;p&gt;Orange World is a series of... mystical realism(?) short stories.&lt;&#x2F;p&gt;
&lt;p&gt;I listened to the audio-book of Orange World and thought it was exceptional.
The voice actors for each story played their characters very well, enhancing the experience.&lt;&#x2F;p&gt;
&lt;p&gt;A few stories I enjoyed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Bog Girl, about a boy&#x27;s first love in a world where people are &lt;em&gt;way too ok&lt;&#x2F;em&gt; with necrophilia.&lt;&#x2F;li&gt;
&lt;li&gt;A story about a tornado rustler raising his last storm.&lt;&#x2F;li&gt;
&lt;li&gt;A woman in post-flood south-eastern USA who can echo-locate like a bat.&lt;&#x2F;li&gt;
&lt;li&gt;A demon blackmailing a new mother into giving it breast milk like a little freak.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I haven&#x27;t read much of her work, but based on this I&#x27;d say Karen Russell is a great author.
I&#x27;m excited to read more of her stuff.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Strange Pictures (Uketsu, 2022)</title>
        <published>2026-02-02T00:00:00+00:00</published>
        <updated>2026-02-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/strange-pictures/"/>
        <id>https://elijah.run/backlog/strange-pictures/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/strange-pictures/">&lt;p&gt;I don&#x27;t read much psycological horror&#x2F;thriller but this was a gift and I figured why not.&lt;&#x2F;p&gt;
&lt;p&gt;What I liked about this was the feeling of putting the pieces together yourself between stories to connect the dots.
It made me feel like a real detective!
Even if it was definitely feeding you that narrative...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What If...? (2021 - 2024)</title>
        <published>2026-01-31T00:00:00+00:00</published>
        <updated>2026-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/what-if/"/>
        <id>https://elijah.run/backlog/what-if/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/what-if/">&lt;p&gt;I watched Seasons 2 and 3 of What If while rowing this month.
It&#x27;s a super silly show with very low stakes and a pretty good and consistent pace, making it easy to row to.&lt;&#x2F;p&gt;
&lt;p&gt;I do wish it kept going after season 3.
I could basically watch this show forever, in the same way I can watch &lt;em&gt;content&lt;&#x2F;em&gt; like TikTok forever.
It scratches an itch, it&#x27;s fun to watch, but honeslty I couldn&#x27;t tell you what happened in any of the episodes...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #16 (January 2026)</title>
        <published>2026-01-31T00:00:00+00:00</published>
        <updated>2026-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2026/01/"/>
        <id>https://elijah.run/whats-good/2026/01/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2026/01/">&lt;h1 id=&quot;portugal-work-trip&quot;&gt;Portugal Work Trip&lt;&#x2F;h1&gt;
&lt;p&gt;The company I work for, which employs around 300 people, organized a company-wide gathering at Portugal for the first week of January this year.
The company truly is global and remote so Portugal was just as good a place as any for visas and cost reasons.&lt;&#x2F;p&gt;
&lt;p&gt;The trip was fun and I enjoyed visiting Portugal.
We went on a bike tour on the waterfront, toured a castle&#x27;s grounds, and I fucked off for a few hours to take pictures at the Zoo.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not the trip I would have organized, and I ended up getting the flu on my way home, but it&#x27;s always nice to see a new part of the world.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pluribus&quot;&gt;Pluribus&lt;&#x2F;h1&gt;
&lt;p&gt;During the flights to and from that work trip I watched &lt;a href=&quot;&#x2F;backlog&#x2F;pluribus&quot;&gt;Pluribus&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you like sci-fi, think hive-minds are an interesting narrative device, and&#x2F;or you are interested in the impact of LLMs on society, Pluribus is worth watching.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;dispatch&quot;&gt;Dispatch&lt;&#x2F;h1&gt;
&lt;p&gt;I also played &lt;a href=&quot;&#x2F;backlog&#x2F;dispatch&quot;&gt;Dispatch&lt;&#x2F;a&gt; on my Steam Deck during those flights, which I really enjoyed.&lt;&#x2F;p&gt;
&lt;p&gt;The characters are really fun, the world is rich, and the gameplay is a huge pain the ass -- I was so bad at it.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-if&quot;&gt;What If...?&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;backlog&#x2F;what-if&quot;&gt;What If...?&lt;&#x2F;a&gt; was my rowing show this month.
The 30 minute episodes were easy to follow, exciting, and zero stakes -- perfect for a quick row.
A great &quot;turn your brain off&quot; show.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-beginner-s-guide&quot;&gt;The Beginner&#x27;s Guide&lt;&#x2F;h1&gt;
&lt;p&gt;I played &lt;a href=&quot;&#x2F;backlog&#x2F;the-beginners-guide&quot;&gt;The Beginner&#x27;s Guide&lt;&#x2F;a&gt; on the recommendation of &lt;a href=&quot;https:&#x2F;&#x2F;jacobgeller.com&#x2F;&quot;&gt;Jacob Geller&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some games change how I think of games, what a game can be even, and this is one of those.
Games can be an idea, part of a conversation, less than perfect.&lt;&#x2F;p&gt;
&lt;p&gt;Of course for ideas you want to like... sell, you probably want that level of polish (that the game as a whole has), but the vignettes within the game are all very focused, very minimal, and yet totally functional.&lt;&#x2F;p&gt;
&lt;p&gt;This is probably not the intended takeaway from the game, but I don&#x27;t care.
I feel invigorated by the revelation that I can just make a game that says one thing and fucks off.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;spirited-away-imax&quot;&gt;Spirited Away (IMAX)&lt;&#x2F;h1&gt;
&lt;p&gt;OMSI hosts a &lt;a href=&quot;https:&#x2F;&#x2F;omsi.edu&#x2F;exhibits&#x2F;studio-ghibli-film-festival&#x2F;&quot;&gt;Studio Ghibli Film Festival&lt;&#x2F;a&gt; every year where they screen many Ghibli films on their big screen.&lt;&#x2F;p&gt;
&lt;p&gt;Spirited Away is by far my favorite Ghibli film, although I&#x27;ve only seen probably 1&#x2F;3 of their entire catalogue, so I was excited to see it on a big screen for the first time.
The film is beautiful and if you live in Portland you should see &lt;em&gt;any&lt;&#x2F;em&gt; Ghibli movie at OMSI.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-tale-of-the-princess-kaguya&quot;&gt;The Tale of The Princess Kaguya&lt;&#x2F;h1&gt;
&lt;p&gt;This was a suggestion by Chris Appelhans, one of the directors of K-Pop Daemon Hunters, from &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;e7L-ka-MsEE?t=162&quot;&gt;Animators React&lt;&#x2F;a&gt;.
I am slowly making my way though all of the Ghibli movies and I hadn&#x27;t seen this one yet.&lt;&#x2F;p&gt;
&lt;p&gt;I really enjoyed the art style, and the story was... nice.
I like movies that don&#x27;t have a forced happy ending and this worked for me.&lt;&#x2F;p&gt;
&lt;p&gt;I also think it&#x27;s a great toddler movie because it is very low stimulation.
Surprisingly good before-bed movie, although 2 hours was pushing my toddler&#x27;s attention span -- even for movies.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;zoloft-generic-version&quot;&gt;Zoloft (Generic Version)&lt;&#x2F;h1&gt;
&lt;p&gt;This is going to get personal, feel free to skip this section if you don&#x27;t want to hear about depression.&lt;&#x2F;p&gt;
&lt;p&gt;For a few months now I have been operating at a sleep deficit, causing a growing anxiety, short-temperedness, and feelings of depression.
I am able to functionally take care of my kids, work, exercise, and even do my hobbies, but just barely.
I feel like I am always on the edge of losing my grip on things, like something will slip out of my grasp and I will have to sacrifice something core to myself to continue another day.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately with two little kids there is not much I can really do to fix the root cause, at least not for a few years.&lt;&#x2F;p&gt;
&lt;p&gt;My wife took SSRIs for her post-partum depression and it worked very well.
She convinced me to talk to my therapist and doctor about trying it out, so I did.&lt;&#x2F;p&gt;
&lt;p&gt;I was initially concerned that anti-depressants would &quot;change me&quot;.
Either make me hollow, or happy but fake, or a robot, or some other black mirror plot-line.
Thankfully I was wrong.&lt;&#x2F;p&gt;
&lt;p&gt;For me, the experience of taking this drug has been feeling like myself from a few months ago when I could get plenty of sleep.
I am in a better mood, less anxious, more able to crack jokes and play with my kids.
I don&#x27;t feel perfect, but I am able to weather this storm life is throwing at me without being a woeful curmudgeon.
I still don&#x27;t have enough time in the day to do all the things I want on top of my obligations, but I am at peace with that, which is just as good for now.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Beginner&#x27;s Guide (2015)</title>
        <published>2026-01-29T00:00:00+00:00</published>
        <updated>2026-01-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/the-beginners-guide/"/>
        <id>https://elijah.run/backlog/the-beginners-guide/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/the-beginners-guide/">&lt;p&gt;I think this was a Jacob Geller recommendation.
That guy has such great taste.&lt;&#x2F;p&gt;
&lt;p&gt;The Beginner&#x27;s Guide is a ~90 minute game exploring creativity, obsession, and burnout among other things.&lt;&#x2F;p&gt;
&lt;p&gt;It also subtly shifted what I now think a game can be.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s easy when you grow up playing polished, AA or AAA games, and even polished indie games, to think that every game needs to check a bunch of boxes.
It needs at least consistent art, writing, a menu with settings, a huge laundry list of features just to be &quot;a game&quot;.
While The Beginner&#x27;s Guide has all of those things, the mini-games within the game do not, and yet they are totally playable.&lt;&#x2F;p&gt;
&lt;p&gt;I feel freed to create... really rough games.
Games that just drop you in, execute on one very narrow idea, and end.
I&#x27;m excited to run with that and get the creative juices flowing.&lt;&#x2F;p&gt;
&lt;p&gt;As an aspiring game designer that is a very exciting idea.
Just make a game that delivers on the idea, you don&#x27;t need to make a product.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Pluribus (2025)</title>
        <published>2026-01-09T00:00:00+00:00</published>
        <updated>2026-01-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/pluribus/"/>
        <id>https://elijah.run/backlog/pluribus/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/pluribus/">&lt;p&gt;During some travel in early January I downloaded and watched Pluribus knowing very little about the show, just that it was made by Vince Gilligan which is enough to get me on board.&lt;&#x2F;p&gt;
&lt;p&gt;I really enjoyed the deep dive into what it would be like to &quot;live with a hive mind&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I also really enjoyed the tact that the story had in it&#x27;s critique of LLMs, although I think those critiques go beyond LLMs which I appreciate.&lt;&#x2F;p&gt;
&lt;p&gt;Once scene in which a culture is erased in a very clinical fashion was really interesting and brilliant writing.&lt;&#x2F;p&gt;
&lt;p&gt;The show is written in such a way that a lot of it can be seen as critiques of modern problems, like LLMs, but &quot;in the fiction&quot; enough that in 10 or 20 years I think it&#x27;ll be worth re-watching as those same devices will likely feel like comments on new modern problems.
Good writing.
Good story telling.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dispatch (2025)</title>
        <published>2026-01-04T00:00:00+00:00</published>
        <updated>2026-01-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/dispatch/"/>
        <id>https://elijah.run/backlog/dispatch/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/dispatch/">&lt;p&gt;I was a fan of the TellTale &quot;The Walking Dead&quot; game whenever that came out.
I initially ignored Dispatch though because honestly I just have enough games to play.
Thankfully, a friend of mine played and really enjoyed Dispatch so I was pressured by my FOMO to play too.&lt;&#x2F;p&gt;
&lt;p&gt;The characters are great, the voice acting is fun, and the &quot;gameplay&quot; parts are really challenging (for me).&lt;&#x2F;p&gt;
&lt;p&gt;The biggest endorsement I can give is that if a sequel is announced I will pre-order it.
I never pre-order games.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Boys (2019-2016)</title>
        <published>2026-01-01T00:00:00+00:00</published>
        <updated>2026-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/the-boys/"/>
        <id>https://elijah.run/backlog/the-boys/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/the-boys/">&lt;blockquote&gt;
&lt;p&gt;I started this backlog project mid-way into watching The Boys, so this will only go over seasons 3, 4, and 5.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;season-3-2022&quot;&gt;Season 3 (2022)&lt;&#x2F;h1&gt;
&lt;p&gt;I really like the show (so far).
The visuals are insane, the characters get themselves into crazy shit that is unlike anything I&#x27;ve seen on screen before.
My only gripe is that main characters have a hard time dying so I never worry about the consequences for what&#x27;s happening.
Sitcom logic is a-ok, but it makes the evolving story feel more stagnant that I would have liked.&lt;&#x2F;p&gt;
&lt;p&gt;Solder-boy the stand-in for &quot;classic patriotism&quot; in contrast with modern (Homelander) patriotism works well.&lt;&#x2F;p&gt;
&lt;p&gt;Homelander not only surviving but coming out somehow &lt;em&gt;better&lt;&#x2F;em&gt; after all the heinous shit he does this season is a great Trump allegory and honestly I am really dreading (in a good way) the stuff he&#x27;s going to get away with the next two seasons.&lt;&#x2F;p&gt;
&lt;!-- # Season 4 (2024) --&gt;
&lt;!-- # Season 5 (2026) --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Entropy Centre</title>
        <published>2025-12-31T00:00:00+00:00</published>
        <updated>2025-12-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/entropy-center/"/>
        <id>https://elijah.run/backlog/entropy-center/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/entropy-center/">&lt;p&gt;I have mixed feelings about Entropy Centre.&lt;&#x2F;p&gt;
&lt;p&gt;On the one hand it does scratch the &quot;Portal&quot; itch very well, copying and then building on top of the Portal series with test chambers, cubes, and a gun that doesn&#x27;t shoot bullets.&lt;&#x2F;p&gt;
&lt;p&gt;Buuuuut puzzles do not have The Sauce.
They aren&#x27;t &lt;em&gt;atrocious&lt;&#x2F;em&gt; but they&#x27;re not nearly as fulfilling as I would have liked, oscillating between too easy and &quot;wtf?&quot;.
Puzzle design is difficult and while these are passable and get the job done demonstrating the mechanics, it&#x27;s certainly not on par with my memory of first playing Portal&#x2F;Portal 2.&lt;&#x2F;p&gt;
&lt;p&gt;The game uses the tropes and design of Portal to get the player up to speed quickly on some interesting puzzle mechanics, but does not in my opinion live up to Portal in most ways.
The writing, the physics, the mechanics, the secrets -- the polish and execution is &lt;em&gt;solid&lt;&#x2F;em&gt; but not Valve-level.&lt;&#x2F;p&gt;
&lt;p&gt;All that said it is very impressive that this was largely written, designed, and implemented by one person (Daniel Stubbington)!&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re looking for Portal 3, this isn&#x27;t it, but it&#x27;s a good placeholder.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #15 (December 2025)</title>
        <published>2025-12-31T00:00:00+00:00</published>
        <updated>2025-12-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/12/"/>
        <id>https://elijah.run/whats-good/2025/12/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/12/">&lt;p&gt;Between the holidays and some personal struggles this month I wasn&#x27;t able to &lt;em&gt;finish&lt;&#x2F;em&gt; as many things as I would like, so I don&#x27;t have as much to share as I would have liked.
Next month though I should check off a few half-finished projects so we&#x27;ll start the year off with a bang.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;priestdaddy&quot;&gt;Priestdaddy&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;12&#x2F;priestdaddy.jpg&quot; alt=&quot;Priestdaddy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I read this on the repeated recomendation of Jacob Geller, one of my favorite creators on the internet who I gladly support on Patreon.
A beautiful narrative autobiography written by a poet, meaning the pros are so goddamn vivid and imaginative I had to stop and take a breather every few pages just to process what I had read.
I laughed, I cried, a had a think.
Good book.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h1&gt;
&lt;p&gt;This is it!
We&#x27;re done watching all of the Godzilla movies!&lt;&#x2F;p&gt;
&lt;p&gt;I am so happy to have done this project and to have shared it with some friends.
I have enjoyed watching not just Godzilla evolve over 70+ years but seeing &lt;em&gt;movies&lt;&#x2F;em&gt; evolve over that time too.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll write a dedicated post about Godzilla before too long, so let&#x27;s wrap this up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-king-of-the-monsters&quot;&gt;Godzilla: King of the Monsters&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;12&#x2F;godzilla-king-of-the-monsters.png&quot; alt=&quot;Godzilla: King of the Monsters&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Continuing where Godzilla (2014) this movie rocks.
It&#x27;s got &lt;em&gt;tons&lt;&#x2F;em&gt; of monsters even digging deep for kaiju like Rodan!?
What a legend.&lt;&#x2F;p&gt;
&lt;p&gt;The writing isn&#x27;t perfect, but as far as CGI spectacle movies go this is incredible.&lt;&#x2F;p&gt;
&lt;p&gt;Note: I think this gets a bad reputation because American audiences don&#x27;t like the story structure -- but my hot-take is that this &lt;em&gt;perfectly&lt;&#x2F;em&gt; updates the &lt;em&gt;classic&lt;&#x2F;em&gt; Godzilla formula for a 201X audience and the old movies just also kinda sucked.
In a lovable way of course.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-kong&quot;&gt;Godzilla vs Kong&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;12&#x2F;godzilla-vs-kong.png&quot; alt=&quot;Godzilla vs Kong&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not entirely sure why Godzilla gets top billing in this movie because it is &lt;em&gt;clearly&lt;&#x2F;em&gt; a Kong film.
He&#x27;s the main character and most of the story beats follow him.
Which is fine, but you know... my boy is GZ, let&#x27;s give him equal screen-time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-minus-one&quot;&gt;Godzilla Minus One&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;12&#x2F;godzilla-minus-one.jpeg&quot; alt=&quot;Godzilla Minus One&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A wonderful modern echo of the classic 60&#x27;s era Godzillas, calling back to many tropes like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A scientist has a long-shot idea for how to kill Godzilla that is only taken seriously after literally nothing else works.&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla is finally defeated when Japan builds some crazy long-shot industrial thing.&lt;&#x2F;li&gt;
&lt;li&gt;There is a &quot;boat guy&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If I were to re-watch the pantheon of Godzilla movies I would probably watch this after watching some of the 50&#x27;s&#x2F;60&#x27;s era films before they got too silly.
That seems to be the era most of the references&#x2F;echos are from, but I watched them so long ago at this point most of it went over my head.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-x-kong-the-new-empire&quot;&gt;Godzilla x Kong: The New Empire&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;12&#x2F;godzilla-x-kong-the-new-empire.jpg&quot; alt=&quot;Godzilla x Kong: The New Empire&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;em&gt;really&lt;&#x2F;em&gt; wished we had ended with Minus One, but I guess we gotta end it with the actual latest entry, not just the one I &lt;em&gt;wish&lt;&#x2F;em&gt; was the latest.&lt;&#x2F;p&gt;
&lt;p&gt;Godzilla x Kong really is Godzilla vs Kong 2.
A very similar cast of (human) characters with a bunch of new monsters that to my knowledge are &lt;em&gt;not&lt;&#x2F;em&gt; in any prior&#x2F;older Godzilla flicks.&lt;&#x2F;p&gt;
&lt;p&gt;Similar to the current (?) run of American Godzilla films, it&#x27;s a totally passable spectacle film but doesn&#x27;t hold a candle to what Japan is doing with it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Media Mono-Tasking</title>
        <published>2025-12-25T00:00:00+00:00</published>
        <updated>2025-12-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/media-monotasking/"/>
        <id>https://elijah.run/blog/media-monotasking/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/media-monotasking/">&lt;p&gt;I, like many people in 2025, have a looooong list of games, movies, tv, and books that I want to enjoy sometime between now and death.&lt;&#x2F;p&gt;
&lt;p&gt;Some tools I have created to deal with this problem include a &lt;a href=&quot;&#x2F;backlog&#x2F;&quot;&gt;backlog&lt;&#x2F;a&gt;, and a &lt;a href=&quot;&#x2F;whats-good&#x2F;&quot;&gt;monthly reflection on what I enjoyed&lt;&#x2F;a&gt;.
These both help me focus; I either finish a piece of media or I give up entirely.
None of this &quot;Oh I started five books and two shows and a dozen games this month&quot; no: either finish what you started, or basnish it to the shadow realm; there is too much good stuff to drag a bunch of half finish &lt;em&gt;stuff&lt;&#x2F;em&gt; around too.&lt;&#x2F;p&gt;
&lt;p&gt;Between work, taking care of the kids, walking the dog, keeping the house tidy, eating, sleeping, keeping up with friends, and exercising I have ~1-2 hours of &quot;me time&quot; per day to spend on &lt;em&gt;whatever&lt;&#x2F;em&gt;.
In the past I woud mindlessly scroll for &lt;em&gt;hours&lt;&#x2F;em&gt; after work and on the weekends, but I had to &lt;a href=&quot;&#x2F;whats-good&#x2F;2024&#x2F;10&#x2F;#tech-screenzen&quot;&gt;lock that shit down&lt;&#x2F;a&gt; pretty quick after having a kid; life&#x27;s too short to waste perfectly good free time.&lt;&#x2F;p&gt;
&lt;p&gt;Ok here&#x27;s the thing: between What&#x27;s Good and The Backlog I feel &lt;em&gt;ok&lt;&#x2F;em&gt; about my media focus, but I think I can do better.
I still find myself starting games I never finish, starting a book on the 1st of the month that&#x27;s barely half way done by the end, and mindlessly scrolling the one app I didn&#x27;t lock down yet-- am I really scrolling Libby?&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-proposal&quot;&gt;The Proposal&lt;&#x2F;h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Do One Thing at a Time.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If you start reading a book, watching a show, listening to a podcast, &lt;em&gt;whatever&lt;&#x2F;em&gt;, that&#x27;s the only media you consume until you either complete it or abandon that forever.&lt;&#x2F;p&gt;
&lt;p&gt;Not one &lt;strong&gt;book&lt;&#x2F;strong&gt; at a time, or one &lt;strong&gt;movie&lt;&#x2F;strong&gt; at a time, but one &lt;em&gt;thing&lt;&#x2F;em&gt; at a time, across all media.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Start a movie? You cannot stop half way through and listen to a podcast while you do dishes.&lt;&#x2F;li&gt;
&lt;li&gt;Start a videogame? Git gud or you&#x27;re gonna get really bored.&lt;&#x2F;li&gt;
&lt;li&gt;Start reading a book? Get cozy af because you&#x27;re locked in.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Of course you can go about your life eating and sleeping and working, but the only &lt;em&gt;media&lt;&#x2F;em&gt; you can consume is &lt;em&gt;the thing&lt;&#x2F;em&gt; until it is done or you call it quits.&lt;&#x2F;p&gt;
&lt;p&gt;Done is subjective, but you get the idea.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Roll credits on a movie.&lt;&#x2F;li&gt;
&lt;li&gt;Finish the last chapter in a book.&lt;&#x2F;li&gt;
&lt;li&gt;Finish a season of television.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;it-s-not-quite-that-simple&quot;&gt;It&#x27;s not quite that simple&lt;&#x2F;h2&gt;
&lt;p&gt;I mean you totally could just do that, but you&#x27;d spend a lot of time driving in silence because you started playing Elden Ring and it&#x27;s good but you&#x27;re &lt;em&gt;really bad&lt;&#x2F;em&gt; at souls-likes.&lt;&#x2F;p&gt;
&lt;p&gt;And honestly truly doing one thing at a time is like the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Jain_vegetarianism&quot;&gt;Jain vegetarianism&lt;&#x2F;a&gt; of media diets, it&#x27;s the most intense version.&lt;&#x2F;p&gt;
&lt;p&gt;I propose, and will personally strive, for a more moderate version which is going to use the following categories to guide our media decisions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Active Media: (Videogames) media that requires your participation.
&lt;ul&gt;
&lt;li&gt;Solving puzzles, shooting zombies, stuff like that.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Active Visual Media: (Books) media that requires your attention.
&lt;ul&gt;
&lt;li&gt;You don&#x27;t need to solve puzzles, but you do need to flip pages.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Passive Visual Media: (Movies&#x2F;TV&#x2F;Videos) benefits from attention.
&lt;ul&gt;
&lt;li&gt;The media will move on without you, but you should be keeping up.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Passive Media: (Music&#x2F;Podcasts&#x2F;Audiobooks) you can put it on in the background.
&lt;ul&gt;
&lt;li&gt;This is &quot;Doing the Dishes&quot; stuff.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;media-monotasking&#x2F;flow-diagram.jpg&quot; alt=&quot;A diagram showing the decision tree of what media to consume when&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;m going to call these &quot;Media Moods&quot; because &quot;Media Situations&quot; feels clunky.
You totally &lt;em&gt;can&lt;&#x2F;em&gt; do these based on mood, it&#x27;s just simpler to describe situations that limit what you &lt;em&gt;can&lt;&#x2F;em&gt; do rather than the more fuzzy &lt;em&gt;what you want to do&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For each of these moods I would pick a single piece of media to engage with.
Any time you are in that mood, you are reading&#x2F;watching&#x2F;listening to that thing, until that thing is done.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;While I am rowing I finish a movie (passive visual) I started yesterday.&lt;&#x2F;li&gt;
&lt;li&gt;Later I am cleaning up the house, so I finish a podcast (passive) I stared that morning.&lt;&#x2F;li&gt;
&lt;li&gt;In the evening I play a puzzle game (active) I have been working on for a few days.&lt;&#x2F;li&gt;
&lt;li&gt;Until I decide my brain is tired and I want to do something else, so I read this month&#x27;s book (active visual).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes, I am drawing an arbitrary line between &quot;Active&quot; and &quot;Active Visual&quot; for convenience; you could totally merge those to simplify things even further.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This means that you have &lt;em&gt;some&lt;&#x2F;em&gt; choice of media based on your circumstances, but there is still a prescriptive framework around what you &lt;em&gt;should&lt;&#x2F;em&gt; be doing media-wise to avoid getting easily distracted.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-is-not-for-everybody&quot;&gt;This is not for everybody&lt;&#x2F;h2&gt;
&lt;p&gt;It goes without saying, this is a framework for burning down a backlog.
Even more so, it is for people who have very little time to burn that backlog, and they need to squeeze every minute out of their days to make any progress on that project.&lt;&#x2F;p&gt;
&lt;p&gt;If you don&#x27;t have a backlog, or you already have a healthy way of handling your backlog, this is probably not for you.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also not compatible with like... roommates.
You should definitely make an exception to whatever your media backlog dictates if it means having a good time with friends and&#x2F;or family.
Don&#x27;t be weird about it please.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-is-a-thing-i-am-trying&quot;&gt;This is a thing I am trying&lt;&#x2F;h2&gt;
&lt;p&gt;It would be awesome if I could say this is something I&#x27;ve been doing for a year and it&#x27;s worked flawlessly -- but no.
This is just a thing I am starting and trying in hopes that it will improve my backlog burn rate.&lt;&#x2F;p&gt;
&lt;p&gt;And if it doesn&#x27;t we&#x27;ll learn something too.
Either way, I&#x27;ll keep you posted.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla x Kong: The New Empire</title>
        <published>2025-12-20T00:00:00+00:00</published>
        <updated>2025-12-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-x-kong-the-new-empire/"/>
        <id>https://elijah.run/backlog/godzilla-x-kong-the-new-empire/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-x-kong-the-new-empire/">&lt;p&gt;Godzilla x Kong: The New Empire is a totally passable Godzilla movie following very closely in Godzilla vs Kong&#x27;s steps as far as visuals and story telling go.&lt;&#x2F;p&gt;
&lt;p&gt;Where it differs is in introducing a new (to me) cast of Kaiju that as far as I can tell are completely original to this story -- unlike the last few entries that pulled from the classic monster cast with Ghidora, MechaGodzilla, etc.&lt;&#x2F;p&gt;
&lt;p&gt;The story and acting fell a little flat for me, but the visuals are undeniably incredible, so for the specticle alone I would watch it again.&lt;&#x2F;p&gt;
&lt;p&gt;My only nit-pick about the visuals was that there is no sense of scale, most of the monsters might be huge or just normal animal size it&#x27;s hard to tell, but the fight scene at the end actually did a good job of selling &lt;em&gt;some&lt;&#x2F;em&gt; scale well which I appreciated.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Sinners</title>
        <published>2025-12-14T00:00:00+00:00</published>
        <updated>2025-12-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/sinners/"/>
        <id>https://elijah.run/backlog/sinners/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/sinners/">&lt;p&gt;I took a break from &lt;a href=&quot;&#x2F;tags&#x2F;godzilla&quot;&gt;Godzilla&lt;&#x2F;a&gt; to watch Sinners and was pleasently surprised with the whole thing.
Not that I thought it wouldn&#x27;t be good -- literally everything I heard about it sounded amazing, just that I didn&#x27;t go in knowing much &lt;em&gt;specific&lt;&#x2F;em&gt; about it at all.&lt;&#x2F;p&gt;
&lt;p&gt;I knew it had Michael B. Jordan -- twice-- but beyond that I wasn&#x27;t sure what I was getting into.&lt;&#x2F;p&gt;
&lt;p&gt;I really liked the southern setting.
The characters felt fun and unique, the music was incredible the whole way through, everything and everybody looked so good!
From sets to costumes to special effects every frame really was a painting in this movie.&lt;&#x2F;p&gt;
&lt;p&gt;I also really liked the contrast between most of the movie having an &quot;invisible special effects&quot; visual and the end scene which has some of the silliest gore and blood effects I have ever seen.
It&#x27;s not quite Evil Dead silly but I did laugh out loud at how absurd it looked, which helped sell how chaotic it moment was!&lt;&#x2F;p&gt;
&lt;p&gt;Over all great movie: great atmosphere, fun story, hot people.
No complaints.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla Minus One</title>
        <published>2025-12-11T00:00:00+00:00</published>
        <updated>2025-12-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-minus-one/"/>
        <id>https://elijah.run/backlog/godzilla-minus-one/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-minus-one/">&lt;p&gt;In contrast with the dynamic fast pace of &lt;a href=&quot;&#x2F;backlog&#x2F;shin-godzilla&quot;&gt;Shin Godzilla&lt;&#x2F;a&gt;, Minus One felt contemplative.
The pacing forced you to experience the hardships of the main characters, notice their growth and recovery, and empathize with their trauma as it came back at the worst times.&lt;&#x2F;p&gt;
&lt;p&gt;If I could do it again, I would watch Minus One after Godzilla Raids Again, or somewhere in the group of 60&#x27;s-era Godzillas.
It pulls from those heavily, like having the inventor scientist, or having a &quot;boat guy&quot;, and having the solution to a problem be coming together and building the impossible.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike those early Godzilla entries, this isn&#x27;t propaganda for the Japanese government; instead this story champions people&#x27;s collective action and rejection of the government&#x27;s status quo.
In that respect this is very similar to Shin Godzilla, injecting a youthful critique of the establishment into (ironically) one of the oldest film series still around.&lt;&#x2F;p&gt;
&lt;p&gt;Minus one rightfully holds the place as the highest rated Godzilla movie ,even beating out the 1954 original which has 70 years of nostalgia propping it up.
I can&#x27;t say it&#x27;s my personal favorite, but it&#x27;s easily in the top 3 and should be required viewing for all movie buffs.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla vs Kong</title>
        <published>2025-12-11T00:00:00+00:00</published>
        <updated>2025-12-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-vs-kong/"/>
        <id>https://elijah.run/backlog/godzilla-vs-kong/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-vs-kong/">&lt;p&gt;Gozilla vs Kong (vs MechaGozilla) feels like a direct continuation of &lt;a href=&quot;&#x2F;backlog&#x2F;godzilla-king-of-the-monsters&quot;&gt;Godzilla: King of the Monsters&lt;&#x2F;a&gt;, weaker in some respects and stronger in others.&lt;&#x2F;p&gt;
&lt;p&gt;Pros:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;As a neon-stan, the color scheme is incredible.&lt;&#x2F;li&gt;
&lt;li&gt;The fight in Hong Kong is epic.&lt;&#x2F;li&gt;
&lt;li&gt;MechaGodzilla looks badass, and the team-up is fun.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Cons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A weaker cast than King of the Monsters&lt;&#x2F;li&gt;
&lt;li&gt;Not enough monsters, especially compared with King of the Monsters&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Somewhere in the middle:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The story and acting just felt sillier&lt;&#x2F;li&gt;
&lt;li&gt;Wow they really ran with that &quot;Hollow Earth&quot; thing&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Over all a totally pleasent way to spend 2 hours, but also not a &quot;must watch&quot;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla: King of the Monsters</title>
        <published>2025-12-06T00:00:00+00:00</published>
        <updated>2025-12-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-king-of-the-monsters/"/>
        <id>https://elijah.run/backlog/godzilla-king-of-the-monsters/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-king-of-the-monsters/">&lt;p&gt;This is a sequel to Godzilla (2014) with many of the same characters and similar visual language carrying over, clearly starting an American Godzilla franchise.&lt;&#x2F;p&gt;
&lt;p&gt;While I liked the last Godzilla in the series, for it&#x27;s sense of scale and delivering on visual effects Godzilla has always deserved, this one felt shallow, scattered, and formulaic.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the thing though... I think that&#x27;s intentional.
Viewed from the lens that this is a modern American interpretation of &lt;em&gt;specifically&lt;&#x2F;em&gt; the 60&#x27;s era Godzilla films I think this nails it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A scientist who is done dirty holds the key to fixing all of our problems.&lt;&#x2F;li&gt;
&lt;li&gt;Not one but TWO people make the ultimate sacrifice.&lt;&#x2F;li&gt;
&lt;li&gt;There is a single comedy relief character.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It also faithfully references the classic 50s&#x2F;60s films:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;They drop an &quot;Oxygen Bomb&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Not only do they have the big hitters like Godzilla, King Ghidorah, and Mothra but they threw in Rodan!?&lt;&#x2F;li&gt;
&lt;li&gt;They clarify that King Ghidorah is from space.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nobody else got those references but I DO!
I JUST WATCHED ALL OF THE GODZILLA MOVIES!
I GET ALL THE REFERENCES!&lt;&#x2F;p&gt;
&lt;p&gt;So yeah, we&#x27;ve come a long way from Godzilla (1998) barely referencing it&#x27;s original canon to now very much honoring not only the lore but even the formula of the classic Godzilla movies.
I think that&#x27;s cool.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not saying it&#x27;s a &lt;em&gt;good&lt;&#x2F;em&gt; movie.
Kinda the opposite actually; the 50&#x27;s and 60&#x27;s Godzilla movies were &lt;em&gt;bad&lt;&#x2F;em&gt;.
They were campy as hell, but they were not &lt;em&gt;good&lt;&#x2F;em&gt; movies.
So while this movie is &lt;em&gt;also bad&lt;&#x2F;em&gt; I think that it&#x27;s a &lt;em&gt;faithful-to-the-original&lt;&#x2F;em&gt; kind of bad which is at least interesting.&lt;&#x2F;p&gt;
&lt;p&gt;All that said, the movie ends with basically Boston being nuked and I like... I might be too dumb but I don&#x27;t know what that means &lt;em&gt;metaphorically speaking&lt;&#x2F;em&gt;.
What does an American Godzilla movie where a major American city gets destroyed... mean?
Email me if you know the answer.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Priestdaddy (2017)</title>
        <published>2025-12-02T00:00:00+00:00</published>
        <updated>2025-12-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/priestdaddy/"/>
        <id>https://elijah.run/backlog/priestdaddy/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/priestdaddy/">&lt;p&gt;I read Priestdaddy (Patricia Lockwood, 2017) because &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Jacob_Geller&quot;&gt;Jacob Geller&lt;&#x2F;a&gt;, a really good games critic and essayist I follow, has suggested it at least four times in different mediums (Videos, Podcasts, Bluesky).
It got to the point where I had to admit &quot;Yeah this dude that I respect really likes this book, I guess I should read it.&quot;
So I did.
Like Geller I think you should read this book.
It is beautiful, interesting, informational, and heartwarming.&lt;&#x2F;p&gt;
&lt;p&gt;Priestdaddy is so good.
It&#x27;s an autobiography written by a poet so even throw-away lines describing a van are the most vivid descriptions I&#x27;ve ever encountered.
Every word is plucked from the aether and perfectly fit with the ones before and after creating a beautiful mosaic beautiful in the small and in the large, like a fractal.
As you can probably tell it also inspired me to like... try writing more interesting pros.&lt;&#x2F;p&gt;
&lt;p&gt;It also taught me a lot about Catholicism.
Not in the way a documentary teaches you about something, but in the way your childhood friend does; in bouts of lore dump and then long periods of subtle hints and vibes.
For example Lockwood will explicitly tell you the structure of the church hierarchy, who reports to who and how they get there, but then spend the latter half of a chapter alluding but never going out and saying that a priest is a predator.
It feels like I am conversational in a language but only have ~100 words in my vocabulary; I have the accent and the vibe and the important details but am immediately out of my depth five sentences in.&lt;&#x2F;p&gt;
&lt;p&gt;I should point out this book is &lt;em&gt;not&lt;&#x2F;em&gt; pro-catholic.
I wouldn&#x27;t say it&#x27;s quite &lt;em&gt;anti&lt;&#x2F;em&gt;-catholic either, but it certainly wants to paint a complete picture of the church and like... a &lt;em&gt;complete&lt;&#x2F;em&gt; picture of the modern catholic churn doesn&#x27;t exactly look &lt;em&gt;good&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #14 (November 2025)</title>
        <published>2025-11-30T00:00:00+00:00</published>
        <updated>2025-11-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/11/"/>
        <id>https://elijah.run/whats-good/2025/11/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/11/">&lt;h1 id=&quot;peak-jusant-and-sky-the-scraper&quot;&gt;Peak, Jusant, and Sky the Scraper&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;climbing-games.jpg&quot; alt=&quot;Climbing Games&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I played these three games that all kinda float around the theme of &quot;climbing&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Peak is a wonderful co-op climber where you help your buddies get up to the top of a mountain that really is trying to kill you.
My highlight is the wacky physics and the proximity chat which never fails to entertain; hearing your best friend&#x27;s yells &quot;Oh no oh no oh noooooooo&quot; get rapidly quieter as he falls off a ledge is just the funniest shit.&lt;&#x2F;p&gt;
&lt;p&gt;Jusant is a beautiful, dense, and interesting world.
Climbing this giant pillar mesa thing is really fun and has some genuinely interesting climbing puzzles.
It also tells a beautiful story with, as far as I can remember, zero spoken words.&lt;&#x2F;p&gt;
&lt;p&gt;Sky the Scraper is two games in one: an arcade window cleaning game and a very stressful life management simulator.
You spend like a minute cleaning windows and it&#x27;s really fun and challenging, then you spend like five minutes responding to texts from your mom about how sad she is that you haven&#x27;t visited in a while, then you go for a walk.
The arcade minigame is really fun though so it&#x27;s worth it.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;elechead-and-ooo&quot;&gt;Elechead and Öoo&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;cute-lil-platformers.jpg&quot; alt=&quot;Two Cute lil&amp;#39; platformers&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Elechead is a cute platformer puzzle game with a strong core mechanic explored in ~2 hours.
The core mechanic is that you are a little battery-headed robot that turns surfaces on and off by touching them.
Believe it or not there&#x27;s a good number of puzzles that fall out of that mechanic and this game has most of them!&lt;&#x2F;p&gt;
&lt;p&gt;Öoo is a cute platformer puzzle game with a strong core mechanic explored in ~2 hours... wait we just did this.
Anyway the mechanic is that you place and blow up bombs to get around!
Öoo is very cute and the puzzles are challenging.
I did feel Öoo was a bit more polished, so it&#x27;s cool to Takahashi&#x27;s skills getting even better.&lt;&#x2F;p&gt;
&lt;p&gt;I love that these two games are short and sweet, but not so short that they leave ideas on the table.
They explore the mechanic they set out to do and do it well.&lt;&#x2F;p&gt;
&lt;p&gt;I had never heard of the creator of these two games, Nama Takahashi, but I am a fan of their work and will keep tabs on them going forward.
I could play &quot;Cute character has this one weird trick you won&#x27;t believe!&quot; forever.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;mission-impossible-dead-final-reckoning&quot;&gt;Mission Impossible: Dead &amp;amp; Final Reckoning&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;mission-impossible-finale.png&quot; alt=&quot;Mission Impossible: Finales&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am still &lt;a href=&quot;&#x2F;whats-good&#x2F;2025&#x2F;05#rowing-with-tom-cruise&quot;&gt;rowing with Tom Cruise&lt;&#x2F;a&gt; and finished the Mission Impossible series this month.
The AI enemy was a little on the nose and honestly it would have been such a good twist if there was no real AI and it was just classic espionage double cross something something -- but alas Mission Impossible played it straight to the end.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;ll do Tom.
That&#x27;ll do.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;defunctland-disney-s-living-characters-a-broken-promise&quot;&gt;(Defunctland) Disney&#x27;s Living Characters: A Broken Promise&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;defunctland.jpg&quot; alt=&quot;Disney&amp;#39;s Living Characters&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The final part of Defunctland&#x27;s two-part series on Disney&#x27;s Animatronics&#x2F;Living Creatures was really spectacular.
A four+ &lt;em&gt;hour&lt;&#x2F;em&gt; documentary about animatronics, digital puppets, and a ton of really cool stuff!&lt;&#x2F;p&gt;
&lt;p&gt;Defunctland is one of the artists I support on Patreon and I think you should do the same.
They publish like two big videos per year, a podcast, some miscellaneous goodies.
It&#x27;s not a &lt;em&gt;lot&lt;&#x2F;em&gt; of content, it&#x27;s certainly not _consistent_c content, but goddamn it is good.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;two-sleepy-people&quot;&gt;Two Sleepy People&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;two-sleepy-people.jpg&quot; alt=&quot;Two Sleepy People&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not on TikTok anymore, but when I was I followed Baron Ryan.
I liked his style and appreciated that he stuck to it, sharpened his craft, and perfected it in little bites.&lt;&#x2F;p&gt;
&lt;p&gt;I was skeptical that he could deliver on a full length project but he (and a really good team) delivered!
I laughed, I cried, I enjoyed the twists and turns.&lt;&#x2F;p&gt;
&lt;p&gt;This is a genuinely good movie and if you get a chance to see it you should.&lt;&#x2F;p&gt;
&lt;p&gt;Support indies.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;zootopia-2&quot;&gt;Zootopia 2&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;zootopia-2.jpg&quot; alt=&quot;Zootopia 2&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Uhh... and then go see Zootopia 2 because it&#x27;s fun.&lt;&#x2F;p&gt;
&lt;p&gt;I was a &lt;em&gt;huge&lt;&#x2F;em&gt; fan of Zootopia.
I&#x27;m not a furry or anything, but I am whatever you would call a furry for buddy-cop movies and Zootopia delivers on the genre.&lt;&#x2F;p&gt;
&lt;p&gt;I admit the sequel didn&#x27;t have the same spark as the first one, but I suspect it&#x27;ll grow on me with repeat viewing (legally required when you have two small children).
Honestly there are many worse fates than watching Zootopia a couple dozen times.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;shin-godzilla&quot;&gt;Shin Godzilla&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;shin-godzilla.png&quot; alt=&quot;Shin godzilla&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Oh my god yes yes yes yes yes.
Dude this is so good.
Like I can tell you how and why but I promise it&#x27;s just &lt;em&gt;good&lt;&#x2F;em&gt;.
Go watch it right now.
I don&#x27;t care if you already watched it &lt;em&gt;today&lt;&#x2F;em&gt;, go watch it again!&lt;&#x2F;p&gt;
&lt;p&gt;Ok now that you&#x27;re back, let&#x27;s review:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Got pacing on &lt;em&gt;lock&lt;&#x2F;em&gt;. It&#x27;s like West Wing meets... Godzilla.&lt;&#x2F;li&gt;
&lt;li&gt;The CGI looks &lt;em&gt;incredible&lt;&#x2F;em&gt;. They really sell the scale in some of these shots.&lt;&#x2F;li&gt;
&lt;li&gt;The ENDING SHOT. No spoilers, go watch it again.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-anime-trilogy&quot;&gt;The Anime Trilogy&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;11&#x2F;godzilla-trilogy.png&quot; alt=&quot;Godzilla Anime Trilogy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Anime... were not as good as Shin.
Which makes sense, nothing is as good as Shin (for now), but they did do some interesting stuff!&lt;&#x2F;p&gt;
&lt;p&gt;The trilogy follows humans who were forced to leave Earth because the Kaiju took over or something.
They leave, come back, and fight Godzilla.
You... you probably could have figured that second part out from the premise.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-planet-of-the-monsters&quot;&gt;Godzilla: Planet of the Monsters&lt;&#x2F;h3&gt;
&lt;p&gt;Planet of Monsters was the weakest of the three for me.
The Animation style was hard to adjust to, but by the end I was enjoying it.
They&#x27;re able to do things visually that they simply could not get away with in a live-action Godzilla on a reasonable budget like explosion simulations and good looking space ships.&lt;&#x2F;p&gt;
&lt;p&gt;Also the twist after they defat Godzilla was... classic.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-city-on-the-edge-of-battle&quot;&gt;Godzilla: City on the Edge of Battle&lt;&#x2F;h3&gt;
&lt;p&gt;City on the Edge of Battle actually worked for me.
The characters has time to grow and develop, it almost felt more like Aliens.
The final scene was super epic and the movie&#x27;s take on Mecha-Godzilla was trippy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-the-planet-eater&quot;&gt;Godzilla: The Planet Eater&lt;&#x2F;h3&gt;
&lt;p&gt;The Planet Eater was the most psychedelic of the bunch, almost leaning into cosmic horror stuff.
Battling inner daemons manifested as uhh... Kaiju destroying the real world.
Cool stuff!&lt;&#x2F;p&gt;
&lt;p&gt;Over all I would say the Anime trilogy is fun but not great.
Get baked and enjoy the pretty visuals and you&#x27;ll have a good time.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla: Planet of Monsters&#x2F;City on the Edge of Battle&#x2F;The Planet Eater (2017-2018)</title>
        <published>2025-11-27T00:00:00+00:00</published>
        <updated>2025-11-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-anime/"/>
        <id>https://elijah.run/backlog/godzilla-anime/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-anime/">&lt;p&gt;In 2017&#x2F;2018 Toho Animation released a trilogy of anime-style CG animated Godzilla movies and they are &lt;em&gt;EPIC&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The series starts with all of Humanity on an intergalactic spaceship exploring the galaxy looking for a habitable planet after Earth was taken over by Kaiju.
Humanity ends up returning to Earth like... immediately and tries to re-colonize riiight after they beat Godzilla.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;planet-of-monsters&quot;&gt;Planet of Monsters&lt;&#x2F;h1&gt;
&lt;p&gt;First the bad:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Characters motivations felt flimsy. Humanity goes back to Earth almost immediately with no real reason to, and once at Earth entertains the idea of leaving again despite promising evidence that they can stay.&lt;&#x2F;li&gt;
&lt;li&gt;The core cast did not have time to develop so I didn&#x27;t feel attached to anybody.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now the good:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The visuals were stunning and clearly demonstrated why this story had to be told as an anime and not a live action Toho production.&lt;&#x2F;li&gt;
&lt;li&gt;The scale of Godzilla is really stunning. Not quite in the same way as in Shin or Godzilla (2014) but it is more of an epic &quot;Yeah he&#x27;s really THIS BIG&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;city-on-the-edge-of-battle&quot;&gt;City on the Edge of Battle&lt;&#x2F;h1&gt;
&lt;p&gt;This was my favorite of the three by far.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I finally felt connected to the core cast and cared when they were in danger!&lt;&#x2F;li&gt;
&lt;li&gt;The core concept of (spoiler) Mecha-Godzilla being a replicating nanobot AI thing was a fun twist on the character.&lt;&#x2F;li&gt;
&lt;li&gt;The ending battle was just the most epic battle shit I have ever seen.&lt;&#x2F;li&gt;
&lt;li&gt;The Gundums were sick as hell flying around.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Over all this felt a bit like Annihilation in that it was about people exploring a pretty inhospitable planet that wanted them dead -- except the threat here was more... Kaiju shaped.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-planet-eater&quot;&gt;The Planet Eater&lt;&#x2F;h1&gt;
&lt;p&gt;Planet Eater was the most... interesting of the bunch.
The threats in this movie felt more abstract, in addition to being literal Kaiju.
(Spoiler) King Ghidorah was a really fascinating take on the character, bordering on an Eldritch horror.
And of course battling your inner deamons is always a good way to quickly resolve an impossible situation, so that was fun.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Over all I am glad this was a trilogy.
It gave the story time to develop the characters and setting resulting in a story with a lot of breadth.&lt;&#x2F;p&gt;
&lt;p&gt;If you are considering watching this I would say you should turn your brain off and enjoy the visuals and don&#x27;t take the story too seriously... in case that wasn&#x27;t obvious.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Elechead (2021) &amp; Öoo (2025)</title>
        <published>2025-11-25T00:00:00+00:00</published>
        <updated>2025-12-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/elechead-ooo/"/>
        <id>https://elijah.run/backlog/elechead-ooo/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/elechead-ooo/">&lt;p&gt;Elechead and Öoo are delightful, short, and sweet puzzle platformers by Nama Takahashi.
Both have a strong core mechanic that is explored well.&lt;&#x2F;p&gt;
&lt;p&gt;They are short at ~3hrs each, but offer some rewarding hidden&#x2F;extra puzzles if you want to stay in the world a bit longer.&lt;&#x2F;p&gt;
&lt;p&gt;They also follow the golden rule of puzzle games:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&#x27;t distract from the puzzle.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Levels were focused, had a good learning curve, but consistently challenging.&lt;&#x2F;p&gt;
&lt;p&gt;My only critique of Nama Takahashi&#x27;s games so far is they require reflex-solutions more than I would like.
In general if you know what the solution is you should be able to execute on it, but reflexes&#x2F;timing is a barrier for some players.
That said the reflex requirement are really scant and often when I found myself trying a reflex solution there was a less-timing-sensitive solution I was supposed to do instead.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Sky the Scraper (2025)</title>
        <published>2025-11-25T00:00:00+00:00</published>
        <updated>2025-11-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/sky-the-scraper/"/>
        <id>https://elijah.run/backlog/sky-the-scraper/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/sky-the-scraper/">&lt;p&gt;I have to admit I haven&#x27;t gotten very far in this game, but I am calling it and wanted to record my thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;The arcade mechanic of scraping windows is really fun and you get into a rythm pretty quick.
It&#x27;s challenging and rewarding and has a good difficulty curve.&lt;&#x2F;p&gt;
&lt;p&gt;The bit, as the description text hints, is that a big chunk of the game is spent between those arcadey games managing your life, texting people, etc.&lt;&#x2F;p&gt;
&lt;p&gt;As far as game design goes that is brilliant.
I genuinely feel exhausted every time I&#x27;m between levels just managing my life and it&#x27;s not even that bad!
I don&#x27;t have to get groceries, I just need to read what my manager sent me.&lt;&#x2F;p&gt;
&lt;p&gt;That said, I really &lt;em&gt;just&lt;&#x2F;em&gt; want to play the fun part (duh) and I wish there was a way to skip past or auto-advance the plot.
Not because that life-management gameplay is bad but because it&#x27;s just really time consuming in a game where you reset quite often... or I did because I kept failing missions.&lt;&#x2F;p&gt;
&lt;p&gt;Over all a really good indie game with some interesting mechanics in an interesting package.&lt;&#x2F;p&gt;
&lt;p&gt;I do wish the Steam Deck support was better.
Menu interactions leave something to be desired.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mission Impossible: Dead Reckoning&#x2F;The Final Reckoning (2023&#x2F;2025)</title>
        <published>2025-11-22T00:00:00+00:00</published>
        <updated>2025-11-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/mission-impossible-finale/"/>
        <id>https://elijah.run/backlog/mission-impossible-finale/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/mission-impossible-finale/">&lt;p&gt;As part of &lt;a href=&quot;&#x2F;whats-good&#x2F;2025&#x2F;05#rowing-with-tom-cruise&quot;&gt;rowing with Tom Cruise&lt;&#x2F;a&gt; I watched the (allegedly) final two Mission Impossible flicks.
The premise was a little on the nose, but if you just ignore the AI stuff it&#x27;s a great mcguffin story with some amazing action set-pieces.&lt;&#x2F;p&gt;
&lt;p&gt;If you like action movies these are (still) worth watching!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Jusant (2023)</title>
        <published>2025-11-19T00:00:00+00:00</published>
        <updated>2025-11-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/jusant/"/>
        <id>https://elijah.run/backlog/jusant/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/jusant/">&lt;p&gt;Climbing has never felt so good.
(Well it felt pretty good in Breath of the Wild but I haven&#x27;t played more than an hour of any Zelda game so I can&#x27;t say for certain.)&lt;&#x2F;p&gt;
&lt;p&gt;The game is of course beautiful.
It is the best kind of eye-candy and I suspect it&#x27;ll age really well, except for the Unreal Engine ray-tracing fuzzyness but that&#x27;s kind of an aesthetic if you let it be.&lt;&#x2F;p&gt;
&lt;p&gt;I appreciated how concise it was, with room for exploration.
I only saw probably half of the side rooms to explore and if I played it again would get a totally different experience.&lt;&#x2F;p&gt;
&lt;p&gt;The vibe is also so chill.
In a world where everybody wants your attention and it feels like every screen is yelling at you, it&#x27;s so nice to have a low-simulation experience where you just... climb with your lil blob-dog.&lt;&#x2F;p&gt;
&lt;p&gt;My only critique is that there is a lot of &lt;em&gt;stuff&lt;&#x2F;em&gt; in the world and you can&#x27;t interact with nearly any of it.
I would have loved to pick up a vase or sit on a chair.
I&#x27;m going to explore every square inch, and little &quot;We know you&#x27;re going to click this&quot; acknowledgements go a long way.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Peak (2025)</title>
        <published>2025-11-03T00:00:00+00:00</published>
        <updated>2025-11-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/peak/"/>
        <id>https://elijah.run/backlog/peak/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/peak/">&lt;p&gt;Sam and I played peak pretty consistently every week for ~2 months and it&#x27;s really fun!&lt;&#x2F;p&gt;
&lt;p&gt;I like that the game is somewhat random with the map resetting daily.
Every time &lt;em&gt;we&lt;&#x2F;em&gt; played it was different, but we had the option to go back and try again with the same track.&lt;&#x2F;p&gt;
&lt;p&gt;The key feature is proximity chat, so if you are talking to your friend and they start to slip and fall you can hear them slowly fade away before they cut out.
Priceless.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m excited to revisit this game every few months as they add fun additions and improve quality of life.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Shin Godzilla (2016)</title>
        <published>2025-11-02T00:00:00+00:00</published>
        <updated>2025-11-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/shin-godzilla/"/>
        <id>https://elijah.run/backlog/shin-godzilla/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/shin-godzilla/">&lt;p&gt;Ok so I know I&#x27;ve said some of the other Godzillas were &lt;em&gt;good&lt;&#x2F;em&gt; and they are -- each Godzilla is good in it&#x27;s own way -- but Shin Godzilla is just categorically good.
Not &quot;Good for a Godzilla&quot; movie, not &quot;Good for a 1980s monster movie&quot; just a really good movie.&lt;&#x2F;p&gt;
&lt;p&gt;That 10 year hiatus between &lt;a href=&quot;&#x2F;backlog&#x2F;godzilla-final-wars&#x2F;&quot;&gt;Final Wars&lt;&#x2F;a&gt; and this really paid off.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The pacing is impeccable, feeling at times like a West Wing episode with just how much happens in dialog alone.&lt;&#x2F;li&gt;
&lt;li&gt;The visual effects are perfect, selling Godzilla&#x27;s scale in a way that we haven&#x27;t seen in a Toho production before.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I have no idea what the story is behind this movie but I am so glad it exists.
It doesn&#x27;t feel like any other Godzilla movie, it looks so good, and it is firing on absolutely every cylinder!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I guess it does feel &lt;em&gt;like&lt;&#x2F;em&gt; other Godzilla movies in that they do invent a novel interesting thing to finally kill Godzilla, but that&#x27;s only a similarity on paper.
The actual moment to moment story telling, camera work, visual language -- all of that is totally different from anything I&#x27;ve ever seen in a Toho film.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Voyager-19 (2024)</title>
        <published>2025-10-31T00:00:00+00:00</published>
        <updated>2025-10-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/voyager-19/"/>
        <id>https://elijah.run/backlog/voyager-19/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/voyager-19/">&lt;p&gt;I was house-bound on Halloween because I was sick and I have two little kids.
Instead of watching a scary movie I decided to play a short scary game and found &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;2925510&#x2F;Voyager19&#x2F;&quot;&gt;Voyager-19&lt;&#x2F;a&gt; in my backlog.&lt;&#x2F;p&gt;
&lt;p&gt;The most concise way I can describe Voyager-19 is to say that it is &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1846170&#x2F;Iron_Lung&#x2F;&quot;&gt;Iron Lung&lt;&#x2F;a&gt; in space.
Which if you haven&#x27;t played Iron Lung, means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Controlling a claustrophobicly small vessel.&lt;&#x2F;li&gt;
&lt;li&gt;Navigating an existentially horrifying and spooky map.&lt;&#x2F;li&gt;
&lt;li&gt;You can only see the world through photographs.&lt;&#x2F;li&gt;
&lt;li&gt;Clunky controls that add to the stress.&lt;&#x2F;li&gt;
&lt;li&gt;Your character is left for dead.&lt;&#x2F;li&gt;
&lt;li&gt;PS1 graphics aesthetics.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Voyager-19 differentiates itself in a few ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Your resources dwindle over time forcing you to make shitty trade-offs.&lt;&#x2F;li&gt;
&lt;li&gt;The interface degrades over time adding to your strain as a player.&lt;&#x2F;li&gt;
&lt;li&gt;In space (duh)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you like short spooky games this is a great way to spend 40 minutes!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla (2014)</title>
        <published>2025-10-30T00:00:00+00:00</published>
        <updated>2025-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-2014/"/>
        <id>https://elijah.run/backlog/godzilla-2014/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-2014/">&lt;p&gt;I liked it!
And honestly it wasn&#x27;t half bad; I think the Rotten Tomato score is ~75 and that feels right.&lt;&#x2F;p&gt;
&lt;p&gt;Two things I especially liked:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The camera work felt grounded, a-la Pacific Rim&#x27;s camera work.&lt;&#x2F;li&gt;
&lt;li&gt;An unmatched sense of scale with 2014 era special effects.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In general this felt like Godzilla + Cloverfield + 2010&#x27;s era disaster movies (think: 2012).&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #13 (October 2025)</title>
        <published>2025-10-30T00:00:00+00:00</published>
        <updated>2025-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/10/"/>
        <id>https://elijah.run/whats-good/2025/10/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/10/">&lt;h1 id=&quot;no-kings-part-ii&quot;&gt;No Kings Part II&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;no-kings-ii.jpg&quot; alt=&quot;No Kings II&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It was really difficult to capture the scale of the protests, so I chose this pretty picture instead.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;My sisters and step-mother visited from Chicago for a weekend and while in Portland we went to the No Kings protest.
We grew up going to protests during the George W. Bush era so this felt like a totally appropriate family activity.&lt;&#x2F;p&gt;
&lt;p&gt;The crowd felt massive, stretching tens of blocks around the city.
People were in inflatable costumes, I saw some good signs, and felt politically energized.
I also wish I had brought the kids.
I was worried about safety, but in practice it was totally civil.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;proximate-dead-letter-dept-without-a-dawn&quot;&gt;Proximate, Dead Letter Dept., Without a Dawn&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;three-games.jpg&quot; alt=&quot;Proximage, Dead Letter Dept., and Without a Dawn&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Jacob Geller came out with &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;0zxQ9YAzy00&quot;&gt;a great video about these three games&lt;&#x2F;a&gt; which I highly suggest you watch.
The bit that these were such short games hooked me and inspired me to play them &lt;em&gt;before&lt;&#x2F;em&gt; watching the essay to sort of &quot;do my homework before class&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;This was a neat exercise that I don&#x27;t usually have the opportunity to do.
Most videogame essays I watch are about sprawling series that require hundreds of hours and a &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;lnAWQz34PJs&quot;&gt;crazy high skill level&lt;&#x2F;a&gt; to even &lt;em&gt;see&lt;&#x2F;em&gt; the stuff the author is talking about, fair enough have interesting thoughts about the topic.
I&#x27;m in my dad mode phase, I don&#x27;t have time to play every Dragon Age game -- I barely have enough time to watch your &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;Vrd6GpZXvdk&quot;&gt;6 hour 40 minute video on the series Noah&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;So I was happy to have a (roughly) 3 hour block of games to get through and be &quot;caught up&quot; before watching this latest Geller essay.
And it was totally worth it!
All three games were appropriately spooky for, you know for October, and I even had thoughts about the games &lt;em&gt;before&lt;&#x2F;em&gt; hearing a smart man talk about them.&lt;&#x2F;p&gt;
&lt;p&gt;Proximate was the first one I played and my favorite of the bunch.
The mechanic of interacting with the world through a layer of abstraction felt very &quot;meta&quot;; you interact with this game world through a keyboard and mouse and screen, so adding another layer of abstraction builds on that.
Also the sound design made me pee my pants a lil.&lt;&#x2F;p&gt;
&lt;p&gt;Without a Dawn was the next one I played.
I didn&#x27;t really connect with the story and felt frustrated with the lack of choice present in the game.
I know that&#x27;s sorta the bit and there&#x27;s narrative meaning there but like... it wasn&#x27;t for me.
The shader effect was very cool though.&lt;&#x2F;p&gt;
&lt;p&gt;Dead Letter Department was the last one I played and at first I didn&#x27;t &quot;get it&quot;.
I followed instructions, chose the edgy dialog options, and got a bonkers ending after ~2 and a half hours of gameplay.
It was weird and spooky but then I watched the essay and realized there are &lt;em&gt;lots&lt;&#x2F;em&gt; of endings and &lt;em&gt;lots&lt;&#x2F;em&gt; of ways to try to break the game!
Sending yourself letters, different choices, lots of room for player creativity that I was so on auto-pilot I didn&#x27;t realize were there.
It almost felt like the environmental choices in Spec Ops: The Line, but in a spooky glitch grunge package.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h1&gt;
&lt;p&gt;This month we hit the 2004 - 2014 hiatus which is huge!
We&#x27;re finally in what I would call the &quot;modern era&quot; of Godzilla.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-against-mechagodzilla&quot;&gt;Godzilla Against Mechagodzilla&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;godzilla-against-mechagodzilla.jpg&quot; alt=&quot;Godzilla Against Mechagodzilla&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Main takeaway: lots of explicit death in this one.
Never really addressed, but you definitely notice the change in mood.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-tokyo-s-o-s&quot;&gt;Godzilla: Tokyo S.O.S.&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;godzilla-tokyo-sos.jpg&quot; alt=&quot;Godzilla: Tokyo S.O.S.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is just a mech film with Godzilla.
Also lots of people explicitly dying, weird theme.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-final-wars&quot;&gt;Godzilla: Final Wars&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;godzilla-final-wars.jpg&quot; alt=&quot;Godzilla: Final Wars&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You probably haven&#x27;t seen this one yet, but you should!&lt;&#x2F;p&gt;
&lt;p&gt;This is the first Godzilla movie in a &lt;em&gt;very long time&lt;&#x2F;em&gt; that I am suggesting to friends and family.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s like The Matrix + Power Rangers + Godzilla in one whacky package!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-2014&quot;&gt;Godzilla (2014)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;10&#x2F;godzilla-2014.jpg&quot; alt=&quot;Godzilla (2014)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I liked this one!&lt;&#x2F;p&gt;
&lt;p&gt;The camera work was grounded which really sold the scale of Godzilla in ways never seen before -- I can say that because I&#x27;ve seen all the other ones!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s like Cloverfield + 2010&#x27;s era disaster movies + Godzilla in one exciting package!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fantastic Four: First Steps (2025)</title>
        <published>2025-10-29T00:00:00+00:00</published>
        <updated>2025-10-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/fantastic-four-2025/"/>
        <id>https://elijah.run/backlog/fantastic-four-2025/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/fantastic-four-2025/">&lt;p&gt;I walked out of Fant4stic (2015) so the bar was pretty low.
The cast was totally solid, the story worked for me, the visuals felt fresh for a Marvel movie.&lt;&#x2F;p&gt;
&lt;p&gt;My only critique -- and it&#x27;s not a negative just a note -- is like... the dialog felt off.
Like the direction for every line was &quot;This is &lt;em&gt;the most important thing ever said&lt;&#x2F;em&gt;&quot;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla: Final Wars (2004)</title>
        <published>2025-10-24T00:00:00+00:00</published>
        <updated>2025-10-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-final-wars/"/>
        <id>https://elijah.run/backlog/godzilla-final-wars/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-final-wars/">&lt;p&gt;This movie fucks.&lt;&#x2F;p&gt;
&lt;p&gt;Seriously.
Odds are you haven&#x27;t seen this movie yet, and you need to fix that.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s Anime + Matrix + Power Rangers + Godzilla all in one magnificent package.&lt;&#x2F;p&gt;
&lt;p&gt;I cannot stress enough, you need to watch this movie.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Proximate, Dead Letter Dept., Without a Dawn</title>
        <published>2025-10-13T00:00:00+00:00</published>
        <updated>2025-10-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/proximate-dead-letter-dept-without-a-dawn/"/>
        <id>https://elijah.run/backlog/proximate-dead-letter-dept-without-a-dawn/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/proximate-dead-letter-dept-without-a-dawn/">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jacobgeller.com&#x2F;&quot;&gt;Jacob Geller&lt;&#x2F;a&gt; is easily my favorite video-game essayist&#x2F;critic working today.
I watch all of his videos, I subscribe to his his Patreon, and I even follow his on-again&#x2F;off-again podcast &quot;Something Rotten&quot; which is the most thoughtful -- yet &quot;dumb guy&quot; friendly -- critique of games.&lt;&#x2F;p&gt;
&lt;p&gt;So when Geller released his newest video &quot;&lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;0zxQ9YAzy00&quot;&gt;3 Games &#x2F; 3 Hours &#x2F; 3 Cursed Computers &lt;&#x2F;a&gt;&quot; with the context that the three games being talked about each took ~1 hour to complete I was like:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh... so I can just play these &lt;em&gt;right now&lt;&#x2F;em&gt;.
&lt;em&gt;&lt;strong&gt;Before&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; watching the video.
I&#x27;ve never done that before...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So I loaded up my cart and bought:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;2957800&#x2F;PROXIMATE&#x2F;&quot;&gt;Proximate&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1627350&#x2F;DEAD_LETTER_DEPT&#x2F;&quot;&gt;Dead Letter Dept&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;3145620&#x2F;Without_a_Dawn&#x2F;&quot;&gt;Without a Dawn&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s talk about them:&lt;&#x2F;p&gt;
&lt;div class=&quot;warning&quot;&gt;
    &lt;span class=&quot;warning-title&quot;&gt;
        Warning
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;warning-body&quot;&gt;
        &lt;p&gt;Just watch Jacob Geller&#x27;s video about these games!
He is a much better writer than I am.
In fact go buy his books and give him money on Patreon!
We need to support the Jacob Geller&#x27;s of the world!
#NotSponsored&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;proximate&quot;&gt;Proximate&lt;&#x2F;h1&gt;
&lt;p&gt;Proximate was the most mechanically interesting game of the bunch.
It&#x27;s a -- say it with me -- indie horror game that takes place in a sketchy under-sea research vessel.
But the bit is you can&#x27;t &lt;em&gt;see&lt;&#x2F;em&gt; anything, you are forced to use a headset that uses &quot;AI&quot; to describe your surroundings.&lt;&#x2F;p&gt;
&lt;p&gt;This means you have the following data:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What the THING is that AI thinks you&#x27;re looking at.&lt;&#x2F;li&gt;
&lt;li&gt;A % confidence score for that read-out.&lt;&#x2F;li&gt;
&lt;li&gt;A distance meter so you know how close you are to THING.&lt;&#x2F;li&gt;
&lt;li&gt;A compass so you know what direction you&#x27;re looking.&lt;&#x2F;li&gt;
&lt;li&gt;A waypoint marker for where you need to go&#x2F;home base.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This means while you&#x27;re technically just staring at the word &quot;WOMAN  48%&quot; you know that woman is probably in a horrific scene based on the &quot;KETCHUP 89%&quot; and &quot;MINCED BEEF 92%&quot; to her left and right.&lt;&#x2F;p&gt;
&lt;p&gt;And honestly this is a genius mechanic.
Just like when you read a book and fill in the details with the most horrific version of events, you fill in the details of what you&#x27;re reading with horrific visuals in far grater detail than the 1-person team could probably achieve otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;The game also ended with a really nice note from the developer and I just love when I play a game by a single person and they end it with &quot;Hey thank you for playing my game and thanks to my family and friends for supporting me&quot;.
It&#x27;s really sweet.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;without-a-dawn&quot;&gt;Without a Dawn&lt;&#x2F;h1&gt;
&lt;p&gt;Without a dawn is a piece of interactive fiction which has striking visuals and a... fine story.
Don&#x27;t get me wrong, there&#x27;s nothing bad about the story, it&#x27;s just compared to the visuals the story felt... secondary.&lt;&#x2F;p&gt;
&lt;p&gt;The visuals are an ascii shader implemented on top of what I think is pixel art that gives it a really unique style and makes what would have otherwise been a really forgettable game into something I&#x27;ll be thinking about for a while.
There are also options for the game like how much shimmer to add to the image, what character set, color scheme, backgrounds, etc.
It almost had an &quot;Obra Dinn&quot; vibe but in a pixel art visual novel.&lt;&#x2F;p&gt;
&lt;p&gt;My big gripe with the story is that for most of the &quot;go&#x2F;no-go&quot; dialog options, the &quot;no-go&quot; option is not &lt;em&gt;real&lt;&#x2F;em&gt;, but rather it just delays the actual choice the game forces you into.
Like... literally you choose &quot;stay&quot; and it says some version of &quot;Ok&quot; then you are presented with the same choice again forever.
I know that is the authors intent but it makes the presence of the choice feel cheap, like yet another game that railroads your choices, in a really transparent way.
I would rather have had the &quot;fake choice&quot; be implemented with some sort of character movement and the game nudging you to move if you are still for too long.
But I don&#x27;t want to dwell too much on comparing this game to a non-existent game in my head -- I hate when critics do that.&lt;&#x2F;p&gt;
&lt;p&gt;This &lt;em&gt;also&lt;&#x2F;em&gt; ended with a little note from the developer and I also thought it was sweet.
More games need to do that.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;dead-letter-dept&quot;&gt;Dead Letter Dept&lt;&#x2F;h1&gt;
&lt;p&gt;I did 1 run in this game and it took me ~2.5 hours so you know... not quite the quick little spooky journey I was hoping for but still relatively short.&lt;&#x2F;p&gt;
&lt;p&gt;The bit for this game, at least in my single run, is that you are a data entry person transcribing writing on letters that the postal service&#x27;s computers cannot transcribe automatically.
As you can imagine there are spooky letters with ominous writing&#x2F;photos&#x2F;context around them, environments with (as Geller describes) &quot;The worst vibes&quot;, and some really unsettling music.
You also umm... fall into madness.
At least that was how my run went.
Yippee.&lt;&#x2F;p&gt;
&lt;p&gt;The visuals of this, similar to the other two games, has a very degraded digital camera look.
The shader work was not nearly as &lt;em&gt;interesting&lt;&#x2F;em&gt; as Without a Dawn, but did it&#x27;s job.
I&#x27;m realizing though that I am really just not into the &quot;This game looks like shit and it&#x27;s hard to see anything&quot; aesthetic of a lot that a lot of indie horror games go for.
It works and it&#x27;s doing exactly what it&#x27;s setting out to do, but just feels gimmicky to me.&lt;&#x2F;p&gt;
&lt;p&gt;I liked the &quot;typing game&quot; mechanic and was pleasantly surprised at how fleshed out the rest of the world was, walking through the world to commute to work for example.
I was expecting more of a &quot;Papers Please&quot; thing where you just &quot;arrive&quot; at work every day but no you actually have to &lt;em&gt;go&lt;&#x2F;em&gt; to work.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m sure if I did another run or two I would have more to say since it&#x27;s a &quot;different every run&quot; type of game but I feel like I got what I will out of it.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;... is what I thought before I watched Jacob Geller&#x27;s video!
Geller pointed out that you can address letters &lt;em&gt;to your apartment&lt;&#x2F;em&gt; -- &lt;em&gt;intentionally&lt;&#x2F;em&gt;.
And you will receive them the next day!&lt;&#x2F;p&gt;
&lt;p&gt;I of course knew this because the game prompts you with a letter with your address on the second day and you receive it on the third morning -- but it never occurred to me that I could you know... lie to the computer.&lt;&#x2F;p&gt;
&lt;p&gt;I did a second run where I sent &lt;em&gt;every&lt;&#x2F;em&gt; letter to myself.
I would suggest &lt;em&gt;not&lt;&#x2F;em&gt; doing this as I was promptly fired.&lt;&#x2F;p&gt;
&lt;p&gt;So while there are 10 (I think?) endings I am content with my 2 for now.
I don&#x27;t really need to get all the endings in &quot;Spooky Stanley Parable&quot; right now, but I appreciate it much more after the context added by a wonderful video essay which, I would like to remind you, you should have watched instead of reading this post.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla: Tokyo S.O.S</title>
        <published>2025-10-12T00:00:00+00:00</published>
        <updated>2025-10-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-tokyo-sos/"/>
        <id>https://elijah.run/backlog/godzilla-tokyo-sos/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-tokyo-sos/">&lt;p&gt;This one felt like the sequel to Godzilla Against Mechagodzilla.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also setting in that Godzilla used to be very pro-Japan, and every problem was solved by Japan just being an industry powerhouse.
Now it&#x27;s at least Japan-skeptical with the industrious power being mighty but flawed with Mechagodzilla being a thing that Japan built but which causes about as many issues as it solves.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing I can think of after &lt;em&gt;just watching it a few minutes ago&lt;&#x2F;em&gt; is the after-credit scene is pretty tight.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Godzilla Against Mechagodzilla (2002)</title>
        <published>2025-10-10T00:00:00+00:00</published>
        <updated>2025-10-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-against-mechagodzilla/"/>
        <id>https://elijah.run/backlog/godzilla-against-mechagodzilla/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-against-mechagodzilla/">&lt;video width=100% controls muted&gt;
    &lt;source src=&quot;mechagodzilla-2002.mp4&quot;&#x2F;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Yeah this was pretty fun.&lt;&#x2F;p&gt;
&lt;p&gt;Godzilla against Mechagodzilla felt like a proto-Pacific-Rim in that it leaned into the Mech side of things which was cool!
Godzilla has been heavy on the Kaiju and light on the Mechs so this was a nice change of pace.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GMK: Giant Monsters All-Out Attack (2001)</title>
        <published>2025-10-06T00:00:00+00:00</published>
        <updated>2025-10-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/godzilla-giant-monsters-all-out-attack/"/>
        <id>https://elijah.run/backlog/godzilla-giant-monsters-all-out-attack/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/godzilla-giant-monsters-all-out-attack/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;backlog&#x2F;godzilla-giant-monsters-all-out-attack&#x2F;godzilla-drone-strike.jpg&quot; alt=&quot;Godzilla being targeted by a drone strike&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Surprisingly this was one of the more interesting Godzillas.&lt;&#x2F;p&gt;
&lt;p&gt;It included a lot of little stories, almost vignettes, in the beginning which was good for pacing.
For example&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;a nurse in a hospital sees Godzilla approaching, thinks it&#x27;s going to attack her building, then it pivots away... only to have his tail whip and knock the whole building over.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Which brings me to my next point: A lot of people very explicitly die in this movie!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s very explicit like &quot;That person died&quot; not &quot;That person got hurt, they&#x27;ll come back in the third act for the credits.&quot;
So that&#x27;s interesting.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #12 (September 2025)</title>
        <published>2025-09-30T00:00:00+00:00</published>
        <updated>2025-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/09/"/>
        <id>https://elijah.run/whats-good/2025/09/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/09/">&lt;h1 id=&quot;getting-3rd-in-a-dragon-boats-race&quot;&gt;Getting 3rd in a Dragon Boats Race&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;third-place.png&quot; alt=&quot;Wasabi Burn 3rd place PDX 2025&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My main social&#x2F;physical activity is Dragon Boats.
Two or three times a week I bike to the Portland water front and meet up with ~20 other paddlers, stretch, get on a boat, and paddle a big boat around and it&#x27;s super fun!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;flappy-bird-with-rewind&quot;&gt;Flappy Bird (with rewind)&lt;&#x2F;h1&gt;
&lt;p&gt;I released a game &lt;em&gt;very&lt;&#x2F;em&gt; early in the month called &lt;a href=&quot;&#x2F;games&#x2F;flappy&#x2F;&quot;&gt;Flappy Bird (with rewind)&lt;&#x2F;a&gt;.
It&#x27;s free to play and runs in your browser so check it out!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;blue-prince&quot;&gt;Blue Prince&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;blue-prince.jpg&quot; alt=&quot;Blue Prince&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Blue Prince is a really interesting rogue-like(-ish) mansion builder.
This is maybe the first game Lucy and I have played together because she was really interested and for some reason it&#x27;s not on Switch (!?!?) so she &lt;em&gt;had&lt;&#x2F;em&gt; to play with me on the Steam Deck!&lt;&#x2F;p&gt;
&lt;p&gt;We played for ~15 hours together, which is impressive given that this is the first time we&#x27;ve played a videogame together.
The puzzles are really interesting and I genuinely felt like I got something new out of every run, unlocking new info every iteration.&lt;&#x2F;p&gt;
&lt;p&gt;Now for the less good parts... I had to quit well before we were done.
My stamina for long games has never been strong and when every run is 30-60 minutes and only produces &lt;em&gt;maybe&lt;&#x2F;em&gt; one piece of information in a game that has no clear path to completion... I start to existentially question if this is the best use of my time.
On top of that a lot of the game presents what are, in my opinion, red herrings; dates that aren&#x27;t the solution to a puzzle, props that are just for decoration, a third thing.
A good puzzle game has very little on top of the mechanics of the puzzle, and those things that are &quot;just set dressing&quot; should be clearly messaged as such, but in this game &lt;em&gt;everything&lt;&#x2F;em&gt; feels like it&#x27;s saying &quot;Look at me! I&#x27;m a clue!&quot; and it&#x27;s exhausting.&lt;&#x2F;p&gt;
&lt;p&gt;Over all, if you like puzzle games you will probably enjoy Blue Prince.
It&#x27;s especially good for couples who want to play together as there is a lot of room to brainstorm and discuss strategy!
The randomness can be frustrating, but if you are used to rogue-like elements it won&#x27;t be &lt;em&gt;that&lt;&#x2F;em&gt; bad.
If you&#x27;ve had a bad run in Balatro it&#x27;s no worse than that.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;everything-must-go&quot;&gt;Everything Must Go&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;everything-must-go.jpg&quot; alt=&quot;Everything Must Go&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I listened to the audiobook version of &lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;everything-must-go-the-stories-we-tell-about-the-end-of-the-world-9780593317099&quot;&gt;Everything Must Go&lt;&#x2F;a&gt; by Dorian Lynskey this month and enjoyed it!
He does a good job of covering a lot of the breadth and history of &quot;end of the world&quot; stories without you know... being a massive bummer.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;gotham-city-year-one&quot;&gt;Gotham City: Year One&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;gotham-city-year-one.jpg&quot; alt=&quot;Gotham City: Year One&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dc.fandom.com&#x2F;wiki&#x2F;Gotham_City:_Year_One_Vol_1&quot;&gt;Gotham City: Year One&lt;&#x2F;a&gt; is a straight up good noir story that &lt;em&gt;happens&lt;&#x2F;em&gt; to be a prequel to Batman.
If you like the Noir genre you&#x27;ll enjoy this read.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;batman-hush&quot;&gt;Batman: Hush&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;batman-hush.jpg&quot; alt=&quot;Batman: Hush&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dc.fandom.com&#x2F;wiki&#x2F;Batman:_Hush&quot;&gt;Batman: Hush&lt;&#x2F;a&gt; reminds me a lot of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Batman:_The_Long_Halloween&quot;&gt;Batman: The Long Halloween&lt;&#x2F;a&gt;.
It spans over 12 issues, hits on most of the star villains, and has some twist at the end that it&#x27;s building up to.
I prefer Long Halloween, but Hush was a solid story with an interesting romance plot and taught me a bit more about the character(s) of Robin than I expected to learn.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;godzilla-t-shirt&quot;&gt;Godzilla T-Shirt&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;front-and-back.png&quot; alt=&quot;Front and back of t-shirt&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I commissioned a t-shirt!
I had the idea for a shirt with a kickass Godzilla collage on the front and a &quot;band tour&quot; list of all Godzilla movies on the back.
Coincidentally Blake Hester, of &lt;a href=&quot;https:&#x2F;&#x2F;nebula.tv&#x2F;somethingrotten&quot;&gt;Something Rotten Podcast&lt;&#x2F;a&gt; Fame -- among other things, designs t-shirts and announced on Bluesky that he was accepting commissions.
I slid into his dm&#x27;s and he accepted the project!
A few weeks later I had the designs, found a local printer (willing to print copyright material) and got a small order!
I&#x27;m sending this to folks participating in the Godzilla weekly movie thing, but I have a few extra so if you&#x27;re interested email me at godzilla@elijah.run (yes that is a real email that goes to my inbox).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-1998&quot;&gt;Godzilla 1998&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;godzilla-1998.jpg&quot; alt=&quot;Godzilla (1998)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a controversial statement: Godzilla 1998 is pretty good.
It&#x27;s not a good &lt;em&gt;Godzilla&lt;&#x2F;em&gt; movie, it&#x27;s more of a Jurassic Park&#x2F;Aliens knock-off, but it&#x27;s a really good knock-off!
The jokes land, it&#x27;s not distractingly 90&#x27;s in it&#x27;s you know misogyny, and the practical effects hold up really well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-2000-millennium&quot;&gt;Godzilla 2000 Millennium&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;godzilla-2000.jpg&quot; alt=&quot;Godzilla 2000 Millennium&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Godzilla 2000 Millennium felt... off.
Like Toho was going through the motions on this one.
The story was uninspired re-using a surprising number of elements from previous films like space ships that turn into Kaiju and the Defense Force trying yet again to kill Godzilla even though that has literally never come close to working since the first movie.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-megaguirus&quot;&gt;Godzilla vs. Megaguirus&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;godzilla-vs-megaguirus.jpg&quot; alt=&quot;Godzilla vs Megaguirus&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My only takeaway from this is that using a BLACK HOLE to kill Godzilla is the most metal weapon used in these movies to date.&lt;&#x2F;p&gt;
&lt;p&gt;Also the camera work is generally closer to the action which is a nice change from previous titles.
The fights feel more intimate as a result.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gmk-giant-monsters-all-out-attack&quot;&gt;GMK: Giant Monsters All-Out Attack&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;09&#x2F;gmk.jpg&quot; alt=&quot;Godzilla: Giant Monsters All-Out Attack&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I liked that there were a lot of little vignettes in this movie.&lt;&#x2F;p&gt;
&lt;p&gt;Also a weird theme of people dying.
Not like... maybe off-screen dying, there&#x27;s a lot of people standing around, then a giant tail swiping or foot stomping them.
Not dark, and rarely addressed explicitly, but definitely notable.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-backlog&quot;&gt;The Backlog&lt;&#x2F;h1&gt;
&lt;p&gt;I also started a project called &lt;a href=&quot;&#x2F;backlog&quot;&gt;The Backlog&lt;&#x2F;a&gt;.
It&#x27;s the public version of a private backlog I&#x27;ve kept in Obsidian for a few months now, but I figure to build the habit of writing I would start publishing the little notes I jot down after I finish something.&lt;&#x2F;p&gt;
&lt;p&gt;I am already overwhelmed at the number of games and tv shows I want to watch...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Batman: Hush (2003)</title>
        <published>2025-09-26T00:00:00+00:00</published>
        <updated>2025-09-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/backlog/hush/"/>
        <id>https://elijah.run/backlog/hush/</id>
        
        <content type="html" xml:base="https://elijah.run/backlog/hush/">&lt;p&gt;Another great &quot;meet the classic villians -- with a twist&quot; Batman series.
Similar to &quot;The Long Halloween&quot;, maybe one notch below on the tier list.&lt;&#x2F;p&gt;
&lt;p&gt;The ultimate bad guy is a complex mastermind and a good addition to the roster and I am excited to read more stories with him included.&lt;&#x2F;p&gt;
&lt;p&gt;The romance between Batman and Cat Woman is... interesting.
I like that a romantic relationship a new &lt;em&gt;type&lt;&#x2F;em&gt; of relationship for Batman which forced him to be vulnerable.
Did that relationship &lt;em&gt;have&lt;&#x2F;em&gt; to be romantic to achieve the same vulnerable result? Probably not.
Was it worse &lt;em&gt;because&lt;&#x2F;em&gt; it was romantic? Honestly no. It was fine.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Toddler Dad</title>
        <published>2025-09-17T00:00:00+00:00</published>
        <updated>2025-09-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/toddler-dad/"/>
        <id>https://elijah.run/fiction/toddler-dad/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/toddler-dad/">&lt;p&gt;Mike never considered himself an especially clean guy.
He wasn&#x27;t messy, but he certainly wasn&#x27;t a neat freak.
But when Mike had two kids, a toddler and a newborn, he found that his shoulders would tense and his breathing would shorten when the house was just a little too cluttered.&lt;&#x2F;p&gt;
&lt;p&gt;Now even with a supportive spouse&#x2F;co-parent two little kids is no walk in the park -- and walks in the park are harrowing if you forget snacks.
So Mike was used to staying in motion most hours of the day, from getting up at 6am to chasing the toddler at the park and rocking baby to nap until finally putting them to bed at 8pm.&lt;&#x2F;p&gt;
&lt;p&gt;But even with a quiet house (ignoring the noise machine that had probably outlived it&#x27;s usefulness) Mike couldn&#x27;t relax because just enough was out of place that he couldn&#x27;t quiet his mind.
So before kicking back and cracking open a cold seltzer water he did a cleaning pass at each room, picking things up off the floor, hanging up coats, sorting shoes, and either washing or putting away dishes.&lt;&#x2F;p&gt;
&lt;p&gt;Although Mike hadn&#x27;t taken a dance class since he was in middle school, when he thought it would get him closer to a girl, he would glide from room to room waltzing left and right, round and round.
He would reach a sort of state between calm flow, checking things off his list, and terminator targeting and eliminating enemies if his psyche.&lt;&#x2F;p&gt;
&lt;p&gt;This was how he ended most days; picking things up until he felt at ease.
Maybe just the act of picking things up was good enough, maybe it didn&#x27;t even matter how clean things got, just that he had left things better than he found it.
After a day of work and family time, sometimes Mike just needed 10 or 20 minutes to himself and that was all it took to fill his cup.&lt;&#x2F;p&gt;
&lt;p&gt;The end.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>🐦 flappy bird (with rewind)⏳</title>
        <published>2025-09-01T00:00:00+00:00</published>
        <updated>2025-09-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/games/flappy/"/>
        <id>https://elijah.run/games/flappy/</id>
        
        <content type="html" xml:base="https://elijah.run/games/flappy/">&lt;video autoplay=true&gt;
  &lt;source src=&quot;&#x2F;images&#x2F;games&#x2F;flappy.mp4&quot;&gt;&lt;&#x2F;source&gt;
&lt;&#x2F;video&gt;
&lt;ul&gt;
&lt;li&gt;free (in-browser): &lt;a href=&quot;https:&#x2F;&#x2F;popgame.itch.io&#x2F;flappy&quot;&gt;popgame.itch.io&#x2F;flappy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;tools: &lt;a href=&quot;https:&#x2F;&#x2F;bevy.org&quot;&gt;bevy&lt;&#x2F;a&gt; (engine), &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Jondolf&#x2F;avian&quot;&gt;avian&lt;&#x2F;a&gt; (physics), &lt;a href=&quot;https:&#x2F;&#x2F;www.blender.org&#x2F;&quot;&gt;blender&lt;&#x2F;a&gt; (visuals)&lt;&#x2F;li&gt;
&lt;li&gt;developed: july - august 2025, released: september 2025&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Around June of 2025 I decided to focus on making many small games by copying existing ideas and adding a fun twist.
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Flappy_Bird&quot;&gt;Flappy Bird&lt;&#x2F;a&gt; came to mind as a simple game to start with, and because I was playing &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;499180&#x2F;Braid_Anniversary_Edition&#x2F;&quot;&gt;Braid, Anniversery Edition&lt;&#x2F;a&gt; the idea of using rewind in some way came about naturally.
I was especially interested because rewind seemed easy to implement given the limited mechanics and I was genuinely curious if it would make the game more or less fun.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>about</title>
        <published>2025-08-31T00:00:00+00:00</published>
        <updated>2025-08-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/about/"/>
        <id>https://elijah.run/about/</id>
        
        <content type="html" xml:base="https://elijah.run/about/">&lt;p&gt;Hi 👋.
My name is Elijah and you&#x27;re reading the &quot;about&quot; page on my website!&lt;&#x2F;p&gt;
&lt;p&gt;A bunch of &quot;I&quot; statements:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;... live in Portland Oregon with my wife, two kids, and a dog&lt;&#x2F;li&gt;
&lt;li&gt;... write code and press buttons in the cloud for a living&lt;&#x2F;li&gt;
&lt;li&gt;... graduated from Oregon State University -- go beavs&lt;&#x2F;li&gt;
&lt;li&gt;... write little videogames games in Rust with bevy&lt;&#x2F;li&gt;
&lt;li&gt;... take and develop film photographs&lt;&#x2F;li&gt;
&lt;li&gt;... paddle on a dragon boat team&lt;&#x2F;li&gt;
&lt;li&gt;... talk about my cargo bike a lot&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;My riff on &lt;a href=&quot;&#x2F;images&#x2F;obama.png&quot;&gt;Barack Obama&#x27;s actual twitter bio&lt;&#x2F;a&gt; would go something like:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dad, husband, platform engineer, rustacean.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;contact&quot;&gt;contact&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Email me: &lt;code&gt;root@elijah.run&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Ping me on Bluesky: &lt;code&gt;@elijah.run&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #11 (August 2025)</title>
        <published>2025-08-31T00:00:00+00:00</published>
        <updated>2025-08-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/08/"/>
        <id>https://elijah.run/whats-good/2025/08/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/08/">&lt;p&gt;Hmm.&lt;&#x2F;p&gt;
&lt;p&gt;This looks different... did the website get a haircut?&lt;&#x2F;p&gt;
&lt;h1 id=&quot;lucy-s-fancy-film-digitizing-thing&quot;&gt;Lucy&#x27;s fancy film digitizing thing&lt;&#x2F;h1&gt;
&lt;p&gt;Lucy bought a &lt;a href=&quot;https:&#x2F;&#x2F;jackw01.github.io&#x2F;scanlight&#x2F;&quot;&gt;scanlight&lt;&#x2F;a&gt; for digitizing film negatives.
At first I thought this was a waste of $150 since we had a totally fine LED lightboard that cost like $20 from Amazon.&lt;&#x2F;p&gt;
&lt;p&gt;Boy was I wrong.
The scanlight webpage (linked above) is very thorough about &lt;em&gt;how&lt;&#x2F;em&gt; it works, so I won&#x27;t go into that -- something something a good light mixture and no LED lines.&lt;&#x2F;p&gt;
&lt;p&gt;So I&#x27;ll just just &lt;em&gt;show you&lt;&#x2F;em&gt; a side-by-side of the same picture digitized using the scanlight vs a cheap LED lightboard:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;comparison.png&quot; alt=&quot;The same photograph digitized; left: using the scanlight right: using the cheap lightboard&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;left: scanlight. right: cheap lightboard.
Note the reds on my ear come through a lot better on the scanlight.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And here is a zoomed in version:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;comparison-zoomed.png&quot; alt=&quot;The same photograph digitized (zoomed in to make the effect more obvious); left: using the scanlight, right: using a cheap lightboard&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;left: scanlight. right: cheap lightboard.
Note the lack of vertical lines where the LEDs are on the lightboard.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I definitely thought these scan lines were just an artifact of like... how the chemicals were put on the film -- nope!
That was totally just an artifact of the lightboard and there are better options.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;braid-anniversary-edition&quot;&gt;Braid Anniversary Edition&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;braid.jpg&quot; alt=&quot;Braid: Anniversary Edition&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I really wish more people played this game.&lt;&#x2F;p&gt;
&lt;p&gt;At ~2 hours Braid is a nice indie title with some really good puzzles.
Braid respects the player&#x27;s time by having &lt;em&gt;no filler&lt;&#x2F;em&gt;; each level explores a new idea and teaches the player something new.&lt;&#x2F;p&gt;
&lt;p&gt;At ~17 hours Braid: Anniversary Edition is &lt;em&gt;the most comprehensive videogame commentary every created&lt;&#x2F;em&gt;.
I&#x27;m serious this goes into every level, every little decision, explores ideas they &lt;em&gt;didn&#x27;t&lt;&#x2F;em&gt; do and even makes those into little interactive levels.
It also includes ~25 NEW LEVELS that are hard as fuck.
It&#x27;s also beautifully crafted with amazing painted moving backgrounds!&lt;&#x2F;p&gt;
&lt;p&gt;If you like puzzles games, you should play Braid.
If you are interested in how games get made, you should play the Anniversary Edition.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;comics&quot;&gt;Comics&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;superior-spider-man-2014&quot;&gt;Superior Spider-Man (2014)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;superior-spider-man.jpg&quot; alt=&quot;Superior Spider-Man&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Doctor Octopus body-swaps with Spider-Man, then Doc-Oc&#x27;s body (with Peter Parker inside) dies!
It is also a good reflection on having empathy for your enemies.&lt;&#x2F;p&gt;
&lt;p&gt;But right before he dies, Peter Parker (as Doc-Oc) instills the &quot;With great power...&quot; speech to Doc Oc (in Peter Parker&#x27;s body) and it works!
Doc Oc&#x2F;Superior Spider-Man tries to be a good guy and honestly in many ways succeeds.
Crime is going down, he&#x27;s got time for friends and family, things are great.
But of course Doc Oc&#x27;s criminal tendencies start to seep through and by the end Spider-Man is kind of a super villain with henchmen and everything!&lt;&#x2F;p&gt;
&lt;p&gt;Superior Spider-Man is a &lt;em&gt;big&lt;&#x2F;em&gt; comic book.
Like the compendium I have is &lt;em&gt;thick&lt;&#x2F;em&gt; with ~40 issues wrapped up into one book.&lt;&#x2F;p&gt;
&lt;p&gt;Superior is not an objectively good story, but for a main-line Spider-Man it&#x27;s exceptional.
The current run of Amazing Spider-Man is &lt;em&gt;still&lt;&#x2F;em&gt; referencing things that happened in this run over a decade ago.
And honestly the bar is so low for Marvel stories, I was blown away at the complexity of this run.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kaiju-score&quot;&gt;Kaiju Score&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;kaiju-score.webp&quot; alt=&quot;Kaiju $core&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What can I say, I like Kaiju.
This is a heist that takes place during a Kaiju invasion&#x2F;attack.
It&#x27;s a very sugary heist story, meaning it stretches that itch but doesn&#x27;t do much else.
Which is ok!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-nice-house-on-the-lake&quot;&gt;The Nice House on the Lake&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;the-nice-house-on-the-lake.jpg&quot; alt=&quot;The Nice House on the Lake&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Wow this was a sleeper for me.
This is such well executed mystery horror and I am here for it.
It&#x27;s the kind of story that begs you to pay attention to details, flip back between pages, and put clues together.
That said if you just blast through it like I did you&#x27;ll still enjoy the twists and turns.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;not-all-robots&quot;&gt;Not All Robots&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;not-all-robots.jpg&quot; alt=&quot;not all robots&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not All Robots is a good reflection not only on the obvious themes of automation, but also how a post-scarcity society can be &lt;em&gt;bad&lt;&#x2F;em&gt; if the means of production is owned by an elite few.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not sure why, but it also felt a bit like Alan Moore&#x27;s &quot;Top 10&quot; comic...
take that with a grain of salt though.
I really have no idea why I got that vibe.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;movies&quot;&gt;Movies&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;17-pages&quot;&gt;17 Pages&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;17-pages.jpg&quot; alt=&quot;17 pages&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;17 pages is the best demonstration of bias I have ever seen in media.
You are told one side of a story, then surprise there is a part 2!
You start that second part thinking &quot;Well there is no way I&#x27;m going to be convinced of... hmm... that&#x27;s actually a compelling point...&quot;&lt;&#x2F;p&gt;
&lt;p&gt;I have been subscribed to Nebula for a few years because I&#x27;m not nerd video essay YouTube.
It really depends on what you&#x27;re interested in if Nebula &quot;pays for itself&quot; especially since &lt;em&gt;most&lt;&#x2F;em&gt; of the videos are on YouTube, so if you have YouTube Premium, or you use an ad-blocker, it&#x27;s a similar experience.
That said, if you are interested in seeing this, subscribe for a month and watch it.
On top of being a well constructed documentary (Bobby Broccoli always does good stuff) this had improved visuals and production value.
I&#x27;m excited to see what BB does next!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;weapons-2025&quot;&gt;Weapons (2025)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;weapons.jpeg&quot; alt=&quot;Weapons (2025)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Weapons is on par with Get Out in instant modern horror classics.
I gasped in appropriately loud a few times in the theater and I felt uneasy most of the movie -- in a good way!&lt;&#x2F;p&gt;
&lt;p&gt;The story telling device of each chapter focusing on a different character was really good at setting up mysteries and then paying them off.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bullet-train&quot;&gt;Bullet Train&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;bullet-train.jpeg&quot; alt=&quot;Bullet Train&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This was one of the movies I&#x27;ve been watched while rowing and it is &lt;em&gt;so fun&lt;&#x2F;em&gt;.
The action is really well executed, the characters are fun and quippy, and the intensity is well paced.&lt;&#x2F;p&gt;
&lt;p&gt;Similar to &quot;Fall Guy&quot;, I love original action movies like this that are little action capsules.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-king-ghidorah&quot;&gt;Godzilla vs King Ghidorah&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;king-ghidorah.jpg&quot; alt=&quot;Godzilla vs King Ghidorah (1991)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is the first and possibly only Godzilla movie to use time travel, and for that I have to put it near the top of Godzilla movies.
Definitely not S or A tier but solid B or C+ tier.&lt;&#x2F;p&gt;
&lt;p&gt;They do a time travel, get rid of Godzilla, but then -- say it with me: Aliens Mind Control a Kaiju.
Well not Aliens, this time it&#x27;s humans from the future, but same diff.
So to fight this new kaiju threat we have to bring Godzilla back by nuking a dinosaur.&lt;&#x2F;p&gt;
&lt;p&gt;This is a very silly one.
Worth the watch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-mothra-1992&quot;&gt;Godzilla vs Mothra (1992)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;mothra.jpg&quot; alt=&quot;Godzilla vs Mothra (1992)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The real monster is Climate Change.
And the REAL monster is us for making Climate Change.&lt;&#x2F;p&gt;
&lt;p&gt;The special effects with the... Fairies(?) is much improved!
I love watching the history of budget special effects evolve throughout these movies.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-mechagodzilla-ii-1993&quot;&gt;Godzilla vs Mechagodzilla II (1993)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;mechagodzilla-ii.jpg&quot; alt=&quot;Godzilla vs Mechagodzilla II (1993)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m just going to share my stream of consiounce notes I took during this film:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;So there&#x27;s an giant Kaiju egg in a hillside that gets discovered when a storm does some erosion.
Unlike previous eggs this does not get turned into an amusement park attraction but is instead studied for science.
During said science they piece together that the egg glows red when it is scared, and it is not scared when a specific female scientist is around.
Yes this is a Mecha Godzilla movie.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway Mecha Godzilla and Godzilla fight.
Mecha loses.
The egg hatches and apparently this is a baby Godzilla -- but this is not Manilla, this is a different &lt;em&gt;vegan&lt;&#x2F;em&gt; baby Godzilla.&lt;&#x2F;p&gt;
&lt;p&gt;The anti Godzilla airplane is brought back after being shelved previously, both decisions being pretty haphazard.
They study baby Godzilla and find a second brain in it&#x27;s butt, and extrapolate that Godzilla also has a butt brain.
So they decide to fight Godzilla again with Super Mecha (Mechagodzilla + the airplane) but this time aim at Godzilla&#x27;s butt.&lt;&#x2F;p&gt;
&lt;p&gt;They almost win, but then Rodan -- did I mention Rodan is also here? -- flies in, dies on Godzilla, turns into energy glitter, causing Godzilla to go super sayan totally destroying Super Mecha but conveniently not the crew because screen cast doesn&#x27;t die.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So yeah... not perfect but pretty fun.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-vs-spacegodzilla-1994&quot;&gt;Godzilla vs SpaceGodzilla (1994)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;spacegodzilla.jpg&quot; alt=&quot;Godzilla vs SpaceGodzilla (1994)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Growing up I played an awesome fighting game where you played as different Godzilla Kaiju.
It may have been &quot;Godzilla: Save the Earth&quot; or one of the other games in that series.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;08&#x2F;godzilla-save-the-earth.png&quot; alt=&quot;Godzilla: Save the Earth&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I distinctly remember playing as Mechagodzilla, Godzilla (classic), and my favorite character: SpaceGodzilla!
The Kaiju felt so distinct in their fighting styles and it was (to a 9 year old&#x27;s sensibilities) a kickass fighting game.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway Space Godzilla was a total snooze fest for me save for one awesome mech scene at the end.
My notes include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Everybody is super chill around baby Godzilla.&lt;&#x2F;li&gt;
&lt;li&gt;Baby Godzilla is way better designed than Minilla (Son of Godzilla).&lt;&#x2F;li&gt;
&lt;li&gt;If the entire Japanese Defense Force can&#x27;t take down Godzilla why does one man on an island think he can...&lt;&#x2F;li&gt;
&lt;li&gt;SpaceGodzilla&#x27;s origin is from way back in Biollante??&lt;&#x2F;li&gt;
&lt;li&gt;OK the mechs combining is awesome and very Power Rangers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Next month:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Godzilla vs. Destoroyah (1995)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla (1998)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla 2000: Millennium (1999)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla vs. Megaguirus (2000)&lt;&#x2F;li&gt;
&lt;li&gt;GMK: Giant Monsters All-Out Attack (2001)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #10 (July 2025)</title>
        <published>2025-07-31T00:00:00+00:00</published>
        <updated>2025-07-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/07/"/>
        <id>https://elijah.run/whats-good/2025/07/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/07/">&lt;h1 id=&quot;2-year-birthday-party&quot;&gt;2 Year Birthday Party&lt;&#x2F;h1&gt;
&lt;p&gt;This month one of my boys turned two and it was fun!&lt;&#x2F;p&gt;
&lt;p&gt;We threw a block party -- which is apparently just a thing you can do!?
Fill out a form, pay a fee, print some signs that say &quot;Road Closed&quot; and you&#x27;re set!&lt;&#x2F;p&gt;
&lt;p&gt;Apparently we also know somebody that knows somebody that got us a friggen FIRE TRUCK &lt;em&gt;WITH REAL FIRE FIGHTERS&lt;&#x2F;em&gt; to show up.
I will never love anything as much as a group of little boys love fire trucks.
I spent nearly an entire roll of film just capturing the excitement.&lt;&#x2F;p&gt;
&lt;p&gt;Despite being brutally hot at over 95F -- it was a blast.
We had pizza, gelato, and a splash pad.
The kids didn&#x27;t mind it was so hot, and a bunch of people showed up!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;books&quot;&gt;Books&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;when-the-moon-hits-your-eye-2025&quot;&gt;When the Moon Hits Your Eye (2025)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;when-the-moon-hits-your-eye.png&quot; alt=&quot;When the Moon Hits Your Eye by John Scalzi&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Another very fun Scalzi romp in which the moon turns to cheese and the world goes through an existential crisis.&lt;&#x2F;p&gt;
&lt;p&gt;My favorite part was two short stories toward the end:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The first is about losing somebody you love and saying final goodbyes.&lt;&#x2F;li&gt;
&lt;li&gt;The second is about the pain of creating&#x2F;writing&#x2F;etc but the regret of not doing so.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;These both stand up on their own for me as solid stand-alone short stories and touch very little on the whimsical premise of the novel.&lt;&#x2F;p&gt;
&lt;p&gt;Fun characters, solid premise, quick read.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-talk-so-little-kids-will-listen-2017-audiobook&quot;&gt;How to Talk so Little Kids Will Listen (2017, Audiobook)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;how-to-talk-so-little-kids-will-listen.png&quot; alt=&quot;How to Talk so Little Kids by Joanna Faber &amp;amp; Julie King&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned above, I am responsible for a two year old boy which is... challenging.
Thankfully I have read this book and now I have TONS to tools to help!
I recommend this to anybody with, or about to come in long term contact with, a very young person.&lt;&#x2F;p&gt;
&lt;p&gt;The book prioritized recognizing, acknowledging, and leading with feelings which so far has been really effective!
Kids are having a tough time, just making sure they feel like you know where they&#x27;re coming from leads to a lot of good communication.&lt;&#x2F;p&gt;
&lt;p&gt;I have started using this script and it is &lt;em&gt;shockingly effective&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;(Kid having tantrum)
Dang.
You really want to do X.
X is really fun and you love doing it!
I also want you to do X!
The problem is, we need to do Y because of Z.
(Kid magically gets better)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Try it out!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;games&quot;&gt;Games&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;kentucky-route-zero-2020&quot;&gt;Kentucky Route Zero (2020)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;kentucky-route-zero.png&quot; alt=&quot;Kentucky Route Zero&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After &lt;em&gt;years&lt;&#x2F;em&gt; I have finally finished KRZ and like... wow.
I love it.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s an amazing game in so many ways, but also challenging like a dense novel.
The world is rich and imaginative and full of mystical realism.
It&#x27;s clearly crafted with love and feels like a work of art in a way that so few games achieve.&lt;&#x2F;p&gt;
&lt;p&gt;If haven&#x27;t yet, you should take a trip to The Zero.
You won&#x27;t regret it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;split-fiction-2025&quot;&gt;Split Fiction (2025)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;split-fiction.png&quot; alt=&quot;Split Fiction&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On the totally different end of the spectrum we have Split Fiction!&lt;&#x2F;p&gt;
&lt;p&gt;My friend and I played this as part of our co-op games we play every week.
If you&#x27;ve ever played a Hazelight game (It Takes Two, A Way Out, Brothers) you know what you&#x27;re in for:
Solid game design, interesting co-op puzzles, and just one or two infuriating platforming levels that I JUST CAN&#x27;T GET RIGHT DANGIT!&lt;&#x2F;p&gt;
&lt;p&gt;My favorite part: they saved the best for last.
That&#x27;s right you&#x27;re going to play an entire amazing game and then they&#x27;re going to BLOW YOUR MIND in the last 20 minutes.
... not to hype it up too much.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;movies&quot;&gt;Movies&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;superman-2025&quot;&gt;Superman (2025)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;superman.jpg&quot; alt=&quot;Superman (2025)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s solid!
Superman fights bad guys, struggles, is superman.
Also he&#x27;s pro-Palestine -- hell yeah!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h2&gt;
&lt;p&gt;This month we experienced a &lt;em&gt;HUGE&lt;&#x2F;em&gt; jump in Godzilla between the 70s and 80s Godzilla took almost a 10 year hiatus!
But he&#x27;s back and although the movies feel &lt;em&gt;slightly&lt;&#x2F;em&gt; more modern it&#x27;s the same Kaiju we love at it again.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-vs-megalon-1973&quot;&gt;Godzilla vs Megalon (1973)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;megalon.png&quot; alt=&quot;Godzilla vs Megalon (1973)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The hi-light of Megalon was the introduction of Jet Jaguar!
A character I knew and who felt &lt;em&gt;very familiar&lt;&#x2F;em&gt; thanks to my upbringing on &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Power_Rangers&quot;&gt;Power Rangers&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Big_Bad_Beetleborgs&quot;&gt;Beatleborgs&lt;&#x2F;a&gt;.
This was a welcome surprise.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly I don&#x27;t remember much about the Kaiju.&lt;&#x2F;p&gt;
&lt;p&gt;Besides that this movie had bitchin&#x27; car chases, a crazy house, and continued the running theme of scientists using million-dollar equipment in their personal time.
Science was just different in the 50&#x27;s, 60&#x27;s, and 70&#x27;s I guess.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-vs-mechagodzilla-1974&quot;&gt;Godzilla vs Mechagodzilla (1974)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;mechagodzilla.png&quot; alt=&quot;Godzilla vs Mechagodzilla (1974)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Mechagodzilla is a &lt;em&gt;classic&lt;&#x2F;em&gt;.
When I mention Godzilla folks usually say &quot;Oh yeah like Gidorah and Mechagodzilla&quot;.
That said... this entry was... mid if for no other reason than THE ALIENS ARE MIND CONTROLLING THE KAIJU AGAIN!!!
WHEN WILL THEY LEARN!&lt;&#x2F;p&gt;
&lt;p&gt;That said it in the final fight scene Godzilla becomes magnetic and I love that because power creep rocks.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;terror-of-mechagodzilla-1975&quot;&gt;Terror of Mechagodzilla (1975)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;terror-of-mechagodzilla.png&quot; alt=&quot;Terror of Mechagodzilla (1975)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is a totally forgettable entry BECAUSE THE ALIENS CONTROL THE KAIJU -- AGAIN!!&lt;&#x2F;p&gt;
&lt;p&gt;The movie does &lt;em&gt;start&lt;&#x2F;em&gt; with a recap of the ending fight scene from the last movie which I did like.
It&#x27;s a nice way to catch you up on where the story is and makes the movies feel more connected and less like a Kaiju sitcom.&lt;&#x2F;p&gt;
&lt;p&gt;... and then Godzilla (the series) fucked off for 9 years...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;return-of-godzilla-1984&quot;&gt;Return of Godzilla (1984)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;return-of-godzilla.png&quot; alt=&quot;The Return of Godzilla (1984)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This movie was more confusing than anything for me:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Godzilla is the bad guy? I thought kids loved him! And he fought off the other bad Kaiju!&lt;&#x2F;li&gt;
&lt;li&gt;Wait where are the other Kaiju? Were the last 15 movies even canon??&lt;&#x2F;li&gt;
&lt;li&gt;There is a nuclear threat that just... resolves 20 minutes before the end of the movie.&lt;&#x2F;li&gt;
&lt;li&gt;The magic solution machine made Godzilla sleepy -- wait didn&#x27;t they already do that?&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla still destroys Tokyo.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It feels like a reboot which I guess it sort of is.
The characters mention the &lt;em&gt;original&lt;&#x2F;em&gt; Godzilla movies in the 50s (as events in their world, not movies -- they&#x27;re not &lt;em&gt;THAT&lt;&#x2F;em&gt; meta) but none of the other stories after that which is fair... it&#x27;s a lot.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-vs-biollante-1989&quot;&gt;Godzilla vs Biollante (1989)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante.png&quot; alt=&quot;Godzilla vs Biollante (1989)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re back baby.
This is a classic Godzilla story if I&#x27;ve ever seen one.&lt;&#x2F;p&gt;
&lt;p&gt;Godzilla fights a genetic clone if himself -- but plant!&lt;&#x2F;p&gt;
&lt;p&gt;Honestly it just rocks visually:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante-explosions.jpeg&quot; alt=&quot;Godzilla in front of explosions&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante-fire.jpeg&quot; alt=&quot;Godzilla facing Biollante on fire&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante-woman.jpeg&quot; alt=&quot;Godzilla in background, woman in foreground&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And then ends with this &lt;em&gt;very on the nose&lt;&#x2F;em&gt; message to the viewer...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante-not-the-monsters.jpeg&quot; alt=&quot;Godzilla and Biollante are not the monsters&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;07&#x2F;biollante-we-are.jpeg&quot; alt=&quot;We&amp;#39;re the monsters for creating them&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;godzilla.multivariatepolynomial.xyz&#x2F;&quot;&gt;Next month&#x27;s Godzillas&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Godzilla vs King Ghidorah (1991)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla vs Mothra (1992)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla vs Mechagodzilla II (1993)&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla vs SpaceGodzilla (1994)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How I use typst</title>
        <published>2025-07-17T00:00:00+00:00</published>
        <updated>2025-07-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/how-i-use-typst/"/>
        <id>https://elijah.run/blog/how-i-use-typst/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/how-i-use-typst/">&lt;p&gt;This week I re-wrote &lt;a href=&quot;&#x2F;Elijah%20Voigt.pdf&quot;&gt;my resume&lt;&#x2F;a&gt;  in &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;&quot;&gt;typst&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;how-i-use-typst&#x2F;old.pdf&quot;&gt;Old&lt;&#x2F;a&gt;:
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;how-i-use-typst&#x2F;old.png&quot; alt=&quot;old resume&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;how-i-use-typst&#x2F;new.pdf&quot;&gt;New&lt;&#x2F;a&gt;:
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;how-i-use-typst&#x2F;new.png&quot; alt=&quot;new resume&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Can you tell the difference? No? Excellent!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since graduating college I don&#x27;t write a lot of LaTeX, but so far I prefer typst!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;anguished-typst-is-not-just-a-better-latex&quot;&gt;😧 typst is not (just) a better LaTeX&lt;&#x2F;h1&gt;
&lt;p&gt;I posted some first impressions on &lt;a href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;elijah.run&quot;&gt;Bluesky&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;bluesky-embed&quot; data-bluesky-uri=&quot;at:&#x2F;&#x2F;did:plc:srziwhupeikb2bcnyndug2ga&#x2F;app.bsky.feed.post&#x2F;3ltx7vsqt3s2m&quot; data-bluesky-cid=&quot;bafyreid2ol6s3bji2jkyiaxnwdgylql7qja72wojpnno5y2eohxahggswu&quot; data-bluesky-embed-color-mode=&quot;system&quot;&gt;&lt;p lang=&quot;en&quot;&gt;LaTeX being compatible with TeX makes it feel like the C++ of typesetting; a rich ecosystem with lots of bloat.
&lt;p&gt;typst not being constrained in that way makes it feel like the Zig of typesetting; smaller ecosystem but a much smoother writing experience.&lt;&#x2F;p&gt;— Elijah Voigt (&lt;a href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;did:plc:srziwhupeikb2bcnyndug2ga?ref_src=embed&quot;&gt;@elijah.run&lt;&#x2F;a&gt;) &lt;a href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;did:plc:srziwhupeikb2bcnyndug2ga&#x2F;post&#x2F;3ltx7vsqt3s2m?ref_src=embed&quot;&gt;July 14, 2025 at 1:25 PM&lt;&#x2F;a&gt;&lt;&#x2F;blockquote&gt;&lt;script async src=&quot;https:&#x2F;&#x2F;embed.bsky.app&#x2F;static&#x2F;embed.js&quot; charset=&quot;utf-8&quot;&gt;&lt;&#x2F;script&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To elaborate: typst doesn&#x27;t feel like an &lt;em&gt;improvement&lt;&#x2F;em&gt; on LaTeX, it feels like a from-the-ground-up typsestter that learns from the past uhh -- wait &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;LaTeX&quot;&gt;LaTeX&lt;&#x2F;a&gt; came out in 1984? and &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;TeX&quot;&gt;TeX&lt;&#x2F;a&gt; came out in 1978?? So yeah it learns from the past 41+ years.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;adult-computer-typst-is-just-programming-for-me&quot;&gt;🧑‍💻 typst is just programming (for me)&lt;&#x2F;h1&gt;
&lt;p&gt;To be fair, so is LaTeX.
If you give me a programming language I&#x27;m gonna program.&lt;&#x2F;p&gt;
&lt;p&gt;The typst docs make it seem like it&#x27;s &lt;code&gt;markdown&lt;&#x2F;code&gt; with functions, which is somewhat true:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typ&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-typ &quot;&gt;&lt;code class=&quot;language-typ&quot; data-lang=&quot;typ&quot;&gt;&lt;span&gt;== this is a title
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;this is a paragraph.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;- this
&lt;&#x2F;span&gt;&lt;span&gt;- is
&lt;&#x2F;span&gt;&lt;span&gt;- a
&lt;&#x2F;span&gt;&lt;span&gt;- list
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But my resume is more... function heavy than advertised.
For example, this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;how-i-use-typst&#x2F;example.png&quot; alt=&quot;example styled section&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Came from this function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typ&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-typ &quot;&gt;&lt;code class=&quot;language-typ&quot; data-lang=&quot;typ&quot;&gt;&lt;span&gt;&#x2F;&#x2F; Function for printing a role
&lt;&#x2F;span&gt;&lt;span&gt;#let role(org: none, location: none, title: none, date: none, description: ntypone) = {
&lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  #set text(weight: &amp;quot;bold&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  #org
&lt;&#x2F;span&gt;&lt;span&gt;  #set text(weight: &amp;quot;regular&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  (
&lt;&#x2F;span&gt;&lt;span&gt;    #text(13pt, location)
&lt;&#x2F;span&gt;&lt;span&gt;  )
&lt;&#x2F;span&gt;&lt;span&gt;  #h(1fr)
&lt;&#x2F;span&gt;&lt;span&gt;  #set text(weight: &amp;quot;bold&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  #title
&lt;&#x2F;span&gt;&lt;span&gt;  #set text(weight: &amp;quot;regular&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  #date
&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;text(12pt, description);
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Invoked like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typ&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-typ &quot;&gt;&lt;code class=&quot;language-typ&quot; data-lang=&quot;typ&quot;&gt;&lt;span&gt;#role(
&lt;&#x2F;span&gt;&lt;span&gt;  org: [CoreOS],
&lt;&#x2F;span&gt;&lt;span&gt;  location: [San Francisco, CA&#x2F;Remote],
&lt;&#x2F;span&gt;&lt;span&gt;  title: [Documentarian],
&lt;&#x2F;span&gt;&lt;span&gt;  date: [09&#x2F;2016 - 05&#x2F;2017],
&lt;&#x2F;span&gt;&lt;span&gt;  description: [
&lt;&#x2F;span&gt;&lt;span&gt;    - #xp([Migration Docs.], [Reviewed, tested, and contributed to public facing Kubernetes developer docs.])
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The result looks good, but it certainly doesn&#x27;t &quot;feel like markdown&quot;... that&#x27;s OK!
I know how to program and the functions are simple!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typ&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-typ &quot;&gt;&lt;code class=&quot;language-typ&quot; data-lang=&quot;typ&quot;&gt;&lt;span&gt;&#x2F;&#x2F; function definition:
&lt;&#x2F;span&gt;&lt;span&gt;#myfn(a, b, c) = {
&lt;&#x2F;span&gt;&lt;span&gt;  [
&lt;&#x2F;span&gt;&lt;span&gt;    #set foo(bar=&amp;quot;thing&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    #a
&lt;&#x2F;span&gt;&lt;span&gt;    #set foo(other=&amp;quot;stuff&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    #b -- #c
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F; called like so:
&lt;&#x2F;span&gt;&lt;span&gt;#myfn([asdf], [abcd123], [hello world])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F; produces:
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F; asdf abcd123 -- hello world
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;rabbit2-typst-is-fast&quot;&gt;🐇 typst is fast&lt;&#x2F;h1&gt;
&lt;p&gt;Which is... not surprising.
Not just because it&#x27;s written in Rust and I&#x27;m a voluntary Rust shill -- any new typesetter would probably be an improvement!
Any time you do a full rewrite, and ignore legacy usage, you&#x27;re gonna go sonic-levels of fast.
And again... LaTeX is 41 years old; there&#x27;s a lot of cruft in that ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;LaTeX&#x27;s output looks &lt;em&gt;gorgeous&lt;&#x2F;em&gt; but it is SLOW and BULKY.
To build my old resume I needed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A 12GB+ docker container.&lt;&#x2F;li&gt;
&lt;li&gt;Bunch of style files I copied from a friend 10 years ago.&lt;&#x2F;li&gt;
&lt;li&gt;A bunch of build phases I frankly did not understand.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This was my Makefile which was &lt;em&gt;as simple as I could get it&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-make &quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;resume
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;pdf
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;dvi&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;.tex
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;latex &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.tex
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;ps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;dvi
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;DOCKER&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;dvips&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -R -Poutline -t&lt;&#x2F;span&gt;&lt;span&gt; letter &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.dvi&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -o &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.ps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;pdf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ps
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ps2pdf &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.ps resume.pdf
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ps2pdf &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.ps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Elijah Caine McDade Voigt resume.pdf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ps2pdf &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;TARGET&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;.ps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Elijah Caine M. Voigt resume.pdf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;clean&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.aux
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.log
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.dvi
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.ps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;veryclean&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.aux
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.log
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.dvi
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.ps
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.pdf
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;DOCKER&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What is this &lt;code&gt;dvips&lt;&#x2F;code&gt; program?
What&#x27;s a &lt;code&gt;dvi&lt;&#x2F;code&gt; file?
And &lt;code&gt;.aux&lt;&#x2F;code&gt;??
Why do I need to build a &lt;code&gt;.ps&lt;&#x2F;code&gt; and a &lt;code&gt;.pdf&lt;&#x2F;code&gt;??&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, LaTeX is heavy and (for obvious reasons) typst is relatively light weight.&lt;&#x2F;p&gt;
&lt;p&gt;For comparison here&#x27;s how I build my current resume:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ typst compile resume.typ
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My dependencies are... &lt;code&gt;typst&lt;&#x2F;code&gt; and the &lt;code&gt;FreeMono&lt;&#x2F;code&gt; font.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;monocle-face-closing-thoughts&quot;&gt;🧐 Closing Thoughts&lt;&#x2F;h1&gt;
&lt;p&gt;But like I said, I don&#x27;t write a lot of LaTeX so why re-write my resume -- my only actively maintained LaTeX doc -- in a new typesetter?&lt;&#x2F;p&gt;
&lt;p&gt;Basically: I &lt;em&gt;dread&lt;&#x2F;em&gt; updating my resume &lt;em&gt;because&lt;&#x2F;em&gt; LaTeX is so heavy.
Every time I think to add it or tweak it or god forsake make a style change I find about a dozen reasons &lt;em&gt;not&lt;&#x2F;em&gt; to sink &lt;em&gt;hours&lt;&#x2F;em&gt; into that task.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still in the honeymoon phase, but I feel a lot more &lt;em&gt;excited&lt;&#x2F;em&gt; to write with typst.
Maybe I&#x27;ll update my resume more than once a year!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #9 (June 2025)</title>
        <published>2025-06-27T00:00:00+00:00</published>
        <updated>2025-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/06/"/>
        <id>https://elijah.run/whats-good/2025/06/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/06/">&lt;p&gt;This month I took full advantage of paternity leave, reading and playing some books and games I wouldn&#x27;t normally find the time for.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;books&quot;&gt;Books&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;polostan-2024&quot;&gt;Polostan (2024)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;polostan.jpg&quot; alt=&quot;Polostan by Neal Stephenson&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I listened to Neal Stephenson&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;polostan-9780062334497&quot;&gt;Polostan&lt;&#x2F;a&gt; at the start of the month.
At &lt;em&gt;merely&lt;&#x2F;em&gt; 12 hours feels suspiciously like the first 1&#x2F;3rd of a &quot;normal&quot; Neal Stephenson novel, which I honestly didn&#x27;t hate.
It&#x27;s easier for me to listen to three 12 hour books than even a single 24 hour novel.&lt;&#x2F;p&gt;
&lt;p&gt;I would not have picked up Polostan if I knew it was a pre-WWII historical spy fiction but once I was in deep enough to realize there wouldn&#x27;t be a sci-fi twist I was hooked and enjoying the ride, so it was for the best!&lt;&#x2F;p&gt;
&lt;p&gt;If you like Neal Stephenson you&#x27;ll like this book.
If you don&#x27;t &lt;em&gt;know&lt;&#x2F;em&gt; if you like Neal Stephenson I would recommend a book he co-authored (and nobody talks about) &lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;the-rise-and-fall-of-dodo-9780062409164&quot;&gt;The Rise and Fall of D.O.D.O&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-lost-cause-2023&quot;&gt;The Lost Cause (2023)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;the-lost-cause.jpg&quot; alt=&quot;The Lost Cause by Cory Doctrow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;lost-cause-9781250865939&quot;&gt;The Lost Cause&lt;&#x2F;a&gt; is a recent Cory Doctrow novel about how my kid&#x27;s generation might deal with the climate catastrophe, MAGA extremists, and refugee crisis all at the same time.
In some ways it is an optimistic read of the 2050s, in others it is pessimistic, and it weirdly made me want to visit Burbank.&lt;&#x2F;p&gt;
&lt;p&gt;Sci-fi tends to either be in the &quot;great ideas&quot; or &quot;great characters&quot; bucket and Cory Doctrow definitely leans more toward ideas and less toward characters.
As with most of his books this had great ideas like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;carbon-neutral concrete factories that run during excess solar production.&lt;&#x2F;li&gt;
&lt;li&gt;pre-fab housing that can be constructed in a week&lt;&#x2F;li&gt;
&lt;li&gt;banning all guns&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The characters aren&#x27;t the &lt;em&gt;most&lt;&#x2F;em&gt; complex, but it did get me to empathize with refugees in a way that no other piece of media has done before.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-sluts-2004&quot;&gt;The Sluts (2004)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;the-sluts.jpg&quot; alt=&quot;The Sluts by Dennis Cooper&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This might be the most interesting book I have ever read.
I picked up Dennis Cooper&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.powells.com&#x2F;book&#x2F;sluts-9780786716746&quot;&gt;The Sluts&lt;&#x2F;a&gt; on a whim after it was mentioned on the Something Rotten podcast.
I am really happy &lt;em&gt;that&lt;&#x2F;em&gt; I read it even if I did gasp, cringe, and laugh all within a single page while I sheepishly read this at my local coffee shop.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Interesting&lt;&#x2F;em&gt; feels too diplomatic, like &quot;-- no no I didn&#x27;t &lt;strong&gt;hate&lt;&#x2F;strong&gt; it -- it was just... interesting!&quot;
I am really happy that I read it as it played with themes and story telling devices I haven&#x27;t been exposed to before.
Buuut can also be a &lt;em&gt;brutal&lt;&#x2F;em&gt; book for anybody not numb to horror themes and imagery.
The pain &lt;em&gt;serves a purpose&lt;&#x2F;em&gt; to be sure, but it&#x27;s still uncomfortable as hell getting through those paragraphs.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fun fact, this is an &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Epistolary_novel&quot;&gt;Epistolary novel&lt;&#x2F;a&gt; (a new word for me!) told through early 2000&#x27;s forum post and escort reviews.
It plays with un-trustworthy narrators because &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;On_the_Internet,_nobody_knows_you%27re_a_dog&quot;&gt;on the internet nobody know&#x27;s you&#x27;re a dog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Ultimately I&#x27;m happy I read it and the ending was thought provoking in a &quot;raises a mirror to the reader&quot; sort of way without bashing you over the head with it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neverender-vol-1-2023&quot;&gt;Neverender Vol 1 (2023)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;neverender.jpg&quot; alt=&quot;Neverender Trade Paperback Cover&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;comics&#x2F;series&#x2F;158632&#x2F;neverender&quot;&gt;Neverender&lt;&#x2F;a&gt; is a very fun comic.
I would describe it as Gladiator in Space -- which looking at my shelf is &lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;comic&#x2F;4865868&#x2F;cosmoknights-vol-1-tp&quot;&gt;not a sparse sub-genre&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you enjoy anime fights, political intrigue, and big space stations you should check this graphic novel out.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;games&quot;&gt;Games&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;schim-2024&quot;&gt;SCHiM (2024)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;schim.jpg&quot; alt=&quot;SCHiM poster&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1519710&#x2F;SCHiM&#x2F;&quot;&gt;SCHiM&lt;&#x2F;a&gt; is an a e s t h e t i c platformer where you play as a little shadow frog thing (I guess it&#x27;s called a SCHiM) jumping from shadow to shadow.
I&#x27;m including it here because it was a fun take on platforming, making it both mechanically interesting while still feeling like a familiar platformer.&lt;&#x2F;p&gt;
&lt;p&gt;... that said I did not &lt;em&gt;finish&lt;&#x2F;em&gt; SCHiM; the game is just too damn long.
I got about half way through and felt like (a) I wasn&#x27;t getting new mechanics at a regular clip and (b) I wasn&#x27;t enjoying the Platforming (a genre I am especially bad at).&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a pretty game with tight but repetitive mechanics.
Honestly if I had more time on my hands I would have loved to turn my brain off and play the whole thing out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;norco-2022&quot;&gt;NORCO (2022)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;norco.jpg&quot; alt=&quot;Norco Poster&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1221250&#x2F;NORCO&#x2F;&quot;&gt;NORCO&lt;&#x2F;a&gt; was a gift from my best friend and &lt;a href=&quot;https:&#x2F;&#x2F;liquidmirror.itch.io&#x2F;martian-chess&quot;&gt;occasional collaborator&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;greatmist.bandcamp.com&#x2F;music&quot;&gt;Sam Hall&lt;&#x2F;a&gt;.
I don&#x27;t usually play point-and-click-adventures but this was really fun!&lt;&#x2F;p&gt;
&lt;p&gt;I pitch NORCO as &quot;Blade Runner in the Bayou&quot;.
It&#x27;s also got a dad-schedule-compatible playtime of just 6 hours.
Yippee!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;movies&quot;&gt;Movies&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;civil-war-2024&quot;&gt;Civil War (2024)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;civil-war.jpeg&quot; alt=&quot;Civil War by Alex Garland&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After finishing &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Devs_(TV_series)&quot;&gt;Devs&lt;&#x2F;a&gt; and watching &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Men_(2022_film)&quot;&gt;Men&lt;&#x2F;a&gt;, I figured I should continue on my Alex Garland&#x27;s directorial journey with &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Civil_War_(film)&quot;&gt;Civil War&lt;&#x2F;a&gt;.
I don&#x27;t think I have anything interesting to say that hasn&#x27;t already been said a few thousand times on the web, but I enjoyed the movie.
It&#x27;s got that Alex Garland cinematography a e s t h e t i c and some fun acting -- and did a good job of helping me empathize with civilians that have to live through a civil war.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s hoping it&#x27;s not &lt;em&gt;too&lt;&#x2F;em&gt; prophetic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzillas&quot;&gt;Godzillas&lt;&#x2F;h2&gt;
&lt;p&gt;This month&#x27;s Godzillas had some duds but also had my (current) favorite Godzilla -- a true S-Tier entry!Let&#x27;s get into it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;destroy-all-monsters-1968&quot;&gt;Destroy All Monsters (1968)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;destroy-all-monsters.jpg&quot; alt=&quot;Destroy All Monsters (1968)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t remember much about this one, but I remember that Ghidorah is a tool that sucks.
Also this continues a trend of 60s Godzillas that are &lt;em&gt;obsessed&lt;&#x2F;em&gt; with space travel, aliens, and aliens mind controlling kaiju.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;all-monsters-attack-1969&quot;&gt;All Monsters Attack (1969)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;all-monsters-attack.jpg&quot; alt=&quot;All Monsters Attack (1969)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Despite the &lt;em&gt;very similar title&lt;&#x2F;em&gt;, All Monsters Attack &lt;em&gt;rocks&lt;&#x2F;em&gt;.
This is easily my favorite Godzilla flick thus far because is breaks the formula in &lt;em&gt;so many ways&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It all takes place in a little boy&#x27;s imagination. Minilla (a.k.a. Son of Godzilla) teaches the boy a lesson. Great start.&lt;&#x2F;li&gt;
&lt;li&gt;The stakes are [in kaiju adjusted terms] very small, but still real! You are rooting for a boy to get out of a tough situation, not rooting for one guy in a rubber costume to beat up another one in a WWE match.&lt;&#x2F;li&gt;
&lt;li&gt;The whole movie has a more grounded 70&#x27;s film-making style without leaning into the cringe 70s stuff like disco and bell-bottoms (I&#x27;m looking at you Gigan)&lt;&#x2F;li&gt;
&lt;li&gt;The fight at the end is between kids and not Kaiju! Breaking! The! Formula!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;godzilla-vs-hedorah-1971&quot;&gt;Godzilla vs. Hedorah (1971)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;godzilla-vs-hedorah.jpg&quot; alt=&quot;Godzilla vs Hedorah (1971)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This has the most on the nose &quot;pollution is bad&quot; story and that&#x27;s &lt;em&gt;fine&lt;&#x2F;em&gt; except they fumble it at the end!
Instead of the solution to defeating the monster being like... going green and stopping polluting they just get Godzilla to electrocute the dang thing.&lt;&#x2F;p&gt;
&lt;p&gt;That said, there are some quirky animated sequences that felt vaguely Monty Python.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;godzilla-vs-gigan-1972&quot;&gt;Godzilla vs. Gigan (1972)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;06&#x2F;godzilla-vs-gigan.jpg&quot; alt=&quot;Godzilla vs Gigan (1972)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Again with the aliens mind-controlling Kaiju? Guys I have to dock you points just for unoriginality.
It was fine the first three times but now this feels like a cry for help.&lt;&#x2F;p&gt;
&lt;p&gt;Most Godzilla movies end with a fight and this is no exception, but this one feels &lt;em&gt;especially&lt;&#x2F;em&gt; like a WWE match.
I half expected them to jump into the ring and start doing pile drivers.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;godzilla.multivariatepolynomial.xyz&#x2F;&quot;&gt;Next month&#x27;s Godzillas&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Godzilla vs. Megalon (1973): June 30&lt;&#x2F;li&gt;
&lt;li&gt;Godzilla vs. Mechagodzilla (1974): July 7&lt;&#x2F;li&gt;
&lt;li&gt;Terror of Mechagodzilla (1975): July 14&lt;&#x2F;li&gt;
&lt;li&gt;The Return of Godzilla (1984):July 21&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #8 (May 2025)</title>
        <published>2025-06-01T00:00:00+00:00</published>
        <updated>2025-06-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/05/"/>
        <id>https://elijah.run/whats-good/2025/05/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/05/">&lt;p&gt;Hey I had a second kid!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;having-a-second-kid-is-good&quot;&gt;Having a second kid is good&lt;&#x2F;h1&gt;
&lt;p&gt;In mid May my wife and I had our second kid -- a healthy baby boy!
He was ~1 week ahead of his due date, just like his older brother.&lt;&#x2F;p&gt;
&lt;p&gt;He had a bit of jaundice at first, so he had to wear this dope &quot;blue-light blanket&quot; that made him look like a pre-cog from Minority Report.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;blue-light-blanket.png&quot; alt=&quot;Dramatic Reenactment&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Post-jaundice the new baby has been great!
Happy, healthy, and [in newborn adjusted terms] very easy!&lt;&#x2F;p&gt;
&lt;p&gt;I get to enjoy a few weeks off work which is a nice bonus~&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rowing-with-tom-cruise&quot;&gt;Rowing with Tom Cruise&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;mission-impossible.jpg&quot; alt=&quot;Mission: Impossible&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The rowing machine I have to exercise at home has a little attachment to stick your phone for movies, shows, videos, maybe workout routines I guess.&lt;&#x2F;p&gt;
&lt;p&gt;Finding good content for rowing isn&#x27;t hard per-se, but you do have to put some thought into it:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Devs_(TV_series)&quot;&gt;Devs&lt;&#x2F;a&gt;? Too slow.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Godzilla&quot;&gt;Godzillas&lt;&#x2F;a&gt;? Subtitles are hard to read.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mission:_Impossible&quot;&gt;Missions: Impossible&lt;&#x2F;a&gt;? Perfect.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It needs to be exciting, there needs to be be lots of it, and the excitement should re-up every ~5 minutes to keep you PUMPED -- but not &lt;em&gt;too&lt;&#x2F;em&gt; pumped or you&#x27;ll gass out.
Some TV would be ideal, but the &lt;del&gt;7&lt;&#x2F;del&gt; 8 Mission: Impossible flicks out are good for ~24 workout sessions (30-minutes a piece) which should last me a few weeks.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;godzillas-part-2-of-8&quot;&gt;Godzillas (part 2 of 8)&lt;&#x2F;h1&gt;
&lt;p&gt;This month we kept the Godzilla train going with &lt;strong&gt;5&lt;&#x2F;strong&gt; Godzilla flicks!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mothra-vs-godzilla-1964&quot;&gt;Mothra vs. Godzilla (1964)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;mothra.jpg&quot; alt=&quot;Mothra vs Godzilla (1964)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The visual effects for the two ummm... fairies?
-- you know what I&#x27;m talking about --
were on point.
Not to say it &lt;em&gt;holds up&lt;&#x2F;em&gt; but the VFX department did great with what they had and it totally works.&lt;&#x2F;p&gt;
&lt;p&gt;The Mothra theme song is... haunting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ghidorah-the-three-headed-monster-1964&quot;&gt;Ghidorah, the Three-Headed Monster (1964)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;ghidorah.webp&quot; alt=&quot;Ghidorah, the Three-Headed Monster (1964)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is really a kaiju team-up film which is fun.
Everybody hates Ghidorah which makes sense, he&#x27;s flashey and think&#x27;s he&#x27;s better than everybody because he has three heads.
What a tool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;invasion-of-astro-monster-1965&quot;&gt;Invasion of Astro-Monster (1965)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;astro-monster.jpg&quot; alt=&quot;Invasion of Astro-Monster (1965)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ok this is just another Ghidorah film, with a dash of &quot;How to Serve Man&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Also the dubbing on the one white guy, whose name I could not be bothered to remember, did &lt;em&gt;not&lt;&#x2F;em&gt; hold up.
I think his name was Glenn?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ebirah-horror-of-the-deep-1966&quot;&gt;Ebirah, Horror of the Deep (1966)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;ebirah.jpg&quot; alt=&quot;Ebirah, Horror of the Deep (1966)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ebirah has been the weakest movie so far.
The main baddy felt disconnected from the rest of the film and didn&#x27;t really do anything special-effects-wise that blew me away.&lt;&#x2F;p&gt;
&lt;p&gt;Also my subtitles were borked for this film which... may have made me feel a bit less connected to the movie.
That&#x27;s a skill isuse on my part.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;son-of-godzilla-1967&quot;&gt;Son of Godzilla (1967)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;05&#x2F;son-of-godzilla.jpg&quot; alt=&quot;Son of Godzilla (1967)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Son of Godzilla is both the best an worst Godzilla flick so far.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Worst&lt;&#x2F;strong&gt; because Son of Godzilla looks, and is musically accompanied by, the worst shit ever.
Seriously every second he&#x27;s on screen I want to punch this little dragon.
He&#x27;s not cute or vulnerable, he&#x27;s just awful.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Best&lt;&#x2F;strong&gt; becuase all that said... I do feel like I got to learn more about Godzilla&#x27;s personality which is neat.
Godzilla isn&#x27;t just a flat destruction machine, he&#x27;s a flat desturction machine that also hits his kid.&lt;&#x2F;p&gt;
&lt;p&gt;The people story in this one, while scientifically dubious, was enjoyable.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #7 (April 2025)</title>
        <published>2025-04-30T00:00:00+00:00</published>
        <updated>2025-04-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/04/"/>
        <id>https://elijah.run/whats-good/2025/04/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/04/">&lt;p&gt;Hey I turned 30! That&#x27;s good!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;boyhood&quot;&gt;Boyhood&lt;&#x2F;h1&gt;
&lt;p&gt;To celebrate I &lt;em&gt;finally&lt;&#x2F;em&gt; threw myself a birthday party!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;boyhood.png&quot; alt=&quot;Boyhood&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Usually I forgo the birthday &lt;em&gt;party&lt;&#x2F;em&gt; in favor of like... a nice dinner or something.
A little treat instead of a big thing.
I lean introverted so why stress myself out?&lt;&#x2F;p&gt;
&lt;p&gt;But I figure 30 is the new 50 or something so I should go big.
I rented out a local second-run movie theater for 3 hours and screened &lt;a href=&quot;https:&#x2F;&#x2F;www.rottentomatoes.com&#x2F;m&#x2F;boyhood&quot;&gt;Boyhood (2014)&lt;&#x2F;a&gt; with ~40 of my friends.&lt;&#x2F;p&gt;
&lt;p&gt;Boyhood (Lucy&#x27;s idea) was a great choice.
It&#x27;s a movie shot over ~12 years and the main character is basically my (and many of my friend&#x27;s) age, so we all got to experience a nostalgia trip with ipods, hit 2000&#x27;s songs, and Ethan Hawke.
If you haven&#x27;t seen it you should!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-comics-backlog&quot;&gt;The Comics Backlog&lt;&#x2F;h1&gt;
&lt;p&gt;Since ~November 2024 I have been working through my comics backlog of ~200 (probably closer to 300 by now) single issue comic books.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;saga.jpg&quot; alt=&quot;a stack of saga comic books&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have been collecting new release comics since ~2018 and while I read &lt;em&gt;some&lt;&#x2F;em&gt; of them I never had the habit of reading &lt;em&gt;all&lt;&#x2F;em&gt; of them, so over the years the &quot;unread&quot; pile stacked up.
In November I decided to slay the dragon and finally vanquish the beast that was my comics backlog...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;nights.jpg&quot; alt=&quot;a stack o fnights comic books&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;... and 6 months later I finall did!&lt;&#x2F;p&gt;
&lt;p&gt;I read a lot of great comics -- I will write a tier list at some point -- and I am &lt;em&gt;very&lt;&#x2F;em&gt; glad to be caught up.
A weight is lifted off my shoulders now that I have reached &lt;em&gt;Comic Book Inbox Zero&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;dawn-runner.jpg&quot; alt=&quot;a stack of dawn runner comic books&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just ignore my trade paper backs backlog which is like... even more daunting than singles were.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I want to call out my two favorite characters across all 200-300-ish issues...&lt;&#x2F;p&gt;
&lt;p&gt;Jeff (Deadpool, Marvel):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;jeff.jpg&quot; alt=&quot;jeff the shark dog&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;and Sploot (Saga, Image):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;sploot.jpg&quot; alt=&quot;sploot the dolphin dog&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I would die for Sploot.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I just realized Jeff and Sploot are both dog-like aquatic animals. I wonder if that&#x27;s a coincidence...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;godzillas-part-1-of-8&quot;&gt;Godzillas (part 1 of 8)&lt;&#x2F;h1&gt;
&lt;p&gt;So it turns out there are 38 Godzilla flicks, most of which are in the Criterion Collection!
A friend of mine decided to watch 1 Godzilla movie every week for the remainder of the year -- and hey there are (err were) 38 weeks left in the year.
There&#x27;s a spreadsheet and everything.&lt;&#x2F;p&gt;
&lt;p&gt;I watched a handful of the old Godzilla films with my grandparents growing up, but haven&#x27;t done a comprehensive study of the series, so I was more than happy to tag along!&lt;&#x2F;p&gt;
&lt;p&gt;Anyway here&#x27;s what I think of this month&#x27;s Godzillas...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-1954&quot;&gt;Godzilla (1954)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;godzilla.png&quot; alt=&quot;Godzilla (1954)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Godzilla is a classic.
Black and white, dramatic, the guy in the rubber suit is only on camera a bit more than the shark in Jaws was, it&#x27;s fun.
Totally holds up if you go in expecting a 71 year old movie with accompanying special effects.&lt;&#x2F;p&gt;
&lt;p&gt;Funny enough Godzilla pretty conclusively dies in this one, so all other Godzillas are just like... cousins?
They were clearly &lt;strong&gt;not&lt;&#x2F;strong&gt; in the franchise building mindset at this point.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godzilla-raids-again-1956&quot;&gt;Godzilla Raids Again (1956)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;godzilla-raids-again.png&quot; alt=&quot;Godzilla Raids Again (1956)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have no idea why it&#x27;s called &quot;Raids Again&quot; -- Godzilla does not raid anything.
It fights a big ol&#x27; dino, fucks some shit up, then gets buried in an avalanche.&lt;&#x2F;p&gt;
&lt;p&gt;The characters are better, the visual effects are better, it does feel like an general improvement on the original.
It&#x27;s sort of half way between the original one-off story and the later &quot;monster of the week&quot; chapters.&lt;&#x2F;p&gt;
&lt;p&gt;This one at least leaves Godzilla&#x27;s death bit more ambiguous leaving room for...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;king-kong-vs-godzilla-1962&quot;&gt;King Kong vs Godzilla (1962)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;04&#x2F;king-kong-vs-godzilla.png&quot; alt=&quot;King Kong vs Godzilla (1962)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is the first Godzilla in COLOR and it pops!
Some &quot;Natives&quot; in one scene have vibrant costumes that really put that color film to work.
The joy of an industry adopting a novel tech and really showing it off -- reminds me of the early days of CGI when each polygon was placed by hand and you &lt;em&gt;felt every vertex&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now it&#x27;s two guys in rubber suits and they punch and it&#x27;s awesome!
Also they defeat King Kong by giving him some melatonin which is hilarious.&lt;&#x2F;p&gt;
&lt;p&gt;This film pretty solidly sets up the next 30 years of franchise which is fun in retrospect.
The formula being &quot;X vs Godzilla&quot; with a new X every year or two, print money, repeat.&lt;&#x2F;p&gt;
&lt;p&gt;-- also if Godzilla is a metaphor for the atomic bomb, and King Kong is a metaphor for slavery... I have no idea what this movie is saying.
Probably just &quot;monsters fight hell yeah brother&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Of course it ends with a &lt;em&gt;very&lt;&#x2F;em&gt; ambiguous death to leave room for... another one.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #6 (Mar 2025)</title>
        <published>2025-03-31T00:00:00+00:00</published>
        <updated>2025-03-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/03/"/>
        <id>https://elijah.run/whats-good/2025/03/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/03/">&lt;p&gt;For starters: I wasn&#x27;t sick for the whole month so it was &lt;em&gt;easily&lt;&#x2F;em&gt; better than February.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;film-photography&quot;&gt;Film Photography&lt;&#x2F;h1&gt;
&lt;p&gt;In February I picked up a film camera that Lucy inherited from her grandpa.
I took some amazing pictures of the snowfall we got, my toddler sledding, I got really into it!
I finished a roll, wound back the film, opened the camera and... it was empty!
Doh! I didn&#x27;t even think to check if it was loaded!&lt;&#x2F;p&gt;
&lt;p&gt;I recovered from this devastating self-prank, loaded the camera, and shot a roll.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;coke.JPG&quot; alt=&quot;Literally the best picture I got out of my first attempt at color film -- ugh&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The inherited camera was... kinda jank.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;lucy-and-ollie-lunch.JPG&quot; alt=&quot;jank photo of lucy and ollie eating lunch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong, it&#x27;s an aesthetic... but I also only got like 3-4 useful pictures out of a roll of 37 which is a &lt;em&gt;bad ratio&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;ollie-swings.JPG&quot; alt=&quot;Jank picture of my family on a swing&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Most of the picutres were not this cool dream vibe -- they were just blown our or totally blank.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;ollie-slide-edited.JPG&quot; alt=&quot;Another jank photo of my kid on a slide&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As I got more into it, I acquired two cameras that worked more reliably:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A cheap &lt;a href=&quot;https:&#x2F;&#x2F;ilford.com&#x2F;product&#x2F;sprite-35-ii-camera&#x2F;&quot;&gt;Ilford Reusable Disposable camera&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Lucy got me a refurbished &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Olympus_OM-1&quot;&gt;Olympus OM-1&lt;&#x2F;a&gt;!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;cherry-blossoms.JPG&quot; alt=&quot;cherry blossoms&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &quot;Reusable Disposable&quot; sounds like an oxymoron but it&#x27;s exactly what you&#x27;d expect:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Basic plastic shell&lt;&#x2F;li&gt;
&lt;li&gt;Static lens&lt;&#x2F;li&gt;
&lt;li&gt;Static exposure settings&lt;&#x2F;li&gt;
&lt;li&gt;Flash&lt;&#x2F;li&gt;
&lt;li&gt;Rewind so you can load and unload your own film&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I shot my first &lt;em&gt;successful&lt;&#x2F;em&gt; roll of Color film on the Illford and it was great!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;negatives.jpg&quot; alt=&quot;Negative film on a lightbox&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;positives.png&quot; alt=&quot;Inverted film on a lightbox&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The OM-1 is a &lt;em&gt;really&lt;&#x2F;em&gt; nice manual film camera and lens -- a &quot;camera system&quot;.
Lucy got it refurbished for ~$60 which feels like a steal given the build quality!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;flower.JPG&quot; alt=&quot;A flower&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I love this camera.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;chairs.JPG&quot; alt=&quot;stacked chairs&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve also been &lt;em&gt;developing&lt;&#x2F;em&gt; the film at home which for me has been half the fun!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;WpgsITqoDXQ&quot;&gt;black and white film&lt;&#x2F;a&gt; I do &quot;Stand Development&quot; where you dilute your developer 1:100 so the process takes ~1 hour but you can&#x27;t over-develop.&lt;&#x2F;li&gt;
&lt;li&gt;For &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;rW1cg3hDdc4&quot;&gt;color film development&lt;&#x2F;a&gt; I&#x27;m just doing C41 development, which required me to buy a Sous Vide!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;c41.jpg&quot; alt=&quot;C41 development requires chemicals to be at exactly 102F&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yay kitchen sink science!&lt;&#x2F;p&gt;
&lt;p&gt;I have zero interest in &lt;em&gt;film printing&lt;&#x2F;em&gt; so I&#x27;ve recruited Lucy to digitize the photos by taking pictures with her DSLR (also an Olympus camera -- we&#x27;re an Olympus family I guess) and inverting + editing them in Gimp.
The results are great!&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s some more pictures!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;cherry-blossoms.JPG&quot; alt=&quot;some cherry blossoms&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;drink-coffee-hail-satan.JPG&quot; alt=&quot;a silicon valley show reference&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;wheel-chairs.JPG&quot; alt=&quot;wheel chairs&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;golf-clubs.JPG&quot; alt=&quot;golf clubs&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;03&#x2F;eli-ollie-out-of-focus.JPG&quot; alt=&quot;eli with ollie out of focus&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note: I have a &lt;em&gt;lot&lt;&#x2F;em&gt; of photos of my toddler but I am avoiding publishing those too widely for his privacy.
I also want them to be fresh when he inevitably uses them as dating profile fodder.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Besides photography I&#x27;ve &lt;em&gt;started&lt;&#x2F;em&gt; some stuff this month but nothing I can say was especially &lt;em&gt;good&lt;&#x2F;em&gt; yet, so I&#x27;ll leave it there.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #5 (Feb 2025)</title>
        <published>2025-03-01T00:00:00+00:00</published>
        <updated>2025-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/02/"/>
        <id>https://elijah.run/whats-good/2025/02/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/02/">&lt;p&gt;Similar to January, February was a tough month for finding &quot;Good Stuff&quot;.
I got sick with a cold, then sick again with a longer cold.&lt;&#x2F;p&gt;
&lt;p&gt;So it goes -- there were still some highlights!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;lazer-tag&quot;&gt;Lazer Tag&lt;&#x2F;h1&gt;
&lt;p&gt;For Lucy&#x27;s 30th birthday we did a &quot;13 going on 30&quot; themed party at a uhh... whatever you call an &quot;arcade + bowling + lazer tag + bar&quot; establishment.
Much like a tween&#x27;s birthday party, we payed for 22 of our friends to come play 2 games of lazer tag, and got some arcade credit and pizza!
Honestly it was a blast and I thought it was the perfect amount of whimsy for a 30th birthday.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;seven-games-audiobook&quot;&gt;Seven Games (Audiobook)&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;02&#x2F;seven-games.jpg&quot; alt=&quot;Seven Games: A human Story by Oliver Roeder&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Seven Games: A Human Story&quot; focuses on -- you guessed it -- seven games that progress in complexity:&lt;&#x2F;p&gt;
&lt;p&gt;I liked that this took seriously the history and best-in-class for these important games.
I also love that the author just like... entered major competitions for all of these games.
Very good reporting on his part.&lt;&#x2F;p&gt;
&lt;p&gt;Perfect information games&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Checkers: relatively simple, solved.&lt;&#x2F;li&gt;
&lt;li&gt;Chess: More complex, not solved but computers easily beat humans.&lt;&#x2F;li&gt;
&lt;li&gt;Go: Far more complex, only recently did computers surpass humans.&lt;&#x2F;li&gt;
&lt;li&gt;Backgammon: Not more complex, but introduces randomness into the mix.&lt;&#x2F;li&gt;
&lt;li&gt;Poker: Introduces hidden information.&lt;&#x2F;li&gt;
&lt;li&gt;Scrabble: A word game.&lt;&#x2F;li&gt;
&lt;li&gt;Bridge: Introduces teams and coordination.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Some hi-lights in no particular order:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Checkers is solved?! And basically through brute force which is wild.&lt;&#x2F;li&gt;
&lt;li&gt;The format of each chapter is basically &quot;History of game, who the best human players are, how the best computer was developed&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Backgammon was so new -- popularized in the mid 20th century -- and was so closely associated with playboy rich guys!&lt;&#x2F;li&gt;
&lt;li&gt;Something to the effect of &quot;Every word in the Scrabble dictionary is part of the rules of Scrabble. If you don&#x27;t know all the words you don&#x27;t know the rules.&quot;&lt;&#x2F;li&gt;
&lt;li&gt;For Bridge I feel like using discards as coded messages is kind of bullshit, but then I found out there&#x27;s only &lt;em&gt;at most&lt;&#x2F;em&gt; 15 unique messages you can convey and I was a little more forgiving. Still kinda smells bad, but nobody plays Bridge anyway.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;why-congress-audiobook&quot;&gt;Why Congress (Audiobook)&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;02&#x2F;why-congress.jpg&quot; alt=&quot;Why Congress by Phillip Wallach&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Taking a break from political &lt;em&gt;news&lt;&#x2F;em&gt; to learn some political &lt;em&gt;history&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Why Congress&quot; is an in depth historical overview of the institution of Congress, it&#x27;s intended function, it&#x27;s practiced (dis)function, and some hypothetical outcomes about how it might change&#x2F;what might happen if it does not change.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not going to gaslight you and say that &quot;Actually Congress is functioning exactly as it should be&quot; because it&#x27;s definitely not.
Congress has sucked my entire life.
That said this book was a really interesting perspective on how the institution &lt;em&gt;ought&lt;&#x2F;em&gt; to function, when it has functioned well in the past, and why we should want it to function better.&lt;&#x2F;p&gt;
&lt;p&gt;The author focuses on the Civil Rights Act as the pinnacle of Congress functioning well, mostly because it was a large and long battle to get bi-partisan support for an important change in American law.
That contrasted with executive actions, judicial decisions, and even rushed Congressional laws that lacked sufficient buy-in which were eventually overturned or weakened, like the Affordable Care Act, COVID-19 response, and Row v Wade.&lt;&#x2F;p&gt;
&lt;p&gt;This was the first time I thought it would be &lt;em&gt;interesting&lt;&#x2F;em&gt; to run to be a state representative, although I don&#x27;t think all of the worlds good intentions would &lt;em&gt;actually&lt;&#x2F;em&gt; do anything without an act of god.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>🎴 set</title>
        <published>2025-01-31T00:00:00+00:00</published>
        <updated>2025-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/games/set/"/>
        <id>https://elijah.run/games/set/</id>
        
        <content type="html" xml:base="https://elijah.run/games/set/">&lt;style&gt; p&gt;img { width: 100%; } &lt;&#x2F;style&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;games&#x2F;set.gif&quot; alt=&quot;set gameplay&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;free (in-browser): &lt;a href=&quot;https:&#x2F;&#x2F;popgame.itch.io&#x2F;set&quot;&gt;popgame.itch.io&#x2F;set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;tools: &lt;a href=&quot;https:&#x2F;&#x2F;bevy.org&quot;&gt;bevy&lt;&#x2F;a&gt; (engine), &lt;a href=&quot;https:&#x2F;&#x2F;rx.cloudhead.io&#x2F;&quot;&gt;rx&lt;&#x2F;a&gt; (visuals)&lt;&#x2F;li&gt;
&lt;li&gt;developed: january 2025, released: january 31, 2025&lt;&#x2F;li&gt;
&lt;li&gt;music by &lt;a href=&quot;https:&#x2F;&#x2F;greatmist.bandcamp.com&#x2F;&quot;&gt;Sam Hall&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a house art show I put together this very rudimentary single-player version of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Set_(card_game)&quot;&gt;Set!&lt;&#x2F;a&gt; and setup a laptop in the corner for people to play.
Every single introvert played a few rounds and gave me some great feedback.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s Good #4 (Jan 2025)</title>
        <published>2025-01-31T00:00:00+00:00</published>
        <updated>2025-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2025/01/"/>
        <id>https://elijah.run/whats-good/2025/01/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2025/01/">&lt;p&gt;This was a tough month for &quot;What&#x27;s Good&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;A goal of the series is to encourage me to &lt;em&gt;focus&lt;&#x2F;em&gt; and &lt;em&gt;mono-tasking&lt;&#x2F;em&gt;.
Instead of reading 5 books half-heartedly, read 1 book all the way though; that sort of thing.
This month though I struggled to reach that focus and kept picking things up for a day and putting them down.&lt;&#x2F;p&gt;
&lt;p&gt;Oh well.
There&#x27;s always next month!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;stand-up-comedy&quot;&gt;Stand-Up Comedy&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;01&#x2F;montavilla-open-mic.jpeg&quot; alt=&quot;Montavilla Open Mic&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=NVGuFdX5guE&quot;&gt;theme&lt;&#x2F;a&gt; for January was to do stand-up comedy &lt;em&gt;at least once&lt;&#x2F;em&gt;.
And I did!
... &lt;em&gt;exactly once&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;I did a 3 minute set, a joke about my allergic reaction to Amoxicillin, which got a few chuckles.
Watching other people try out &lt;em&gt;very new&lt;&#x2F;em&gt; material, and getting targeted &lt;em&gt;a concerning amount&lt;&#x2F;em&gt; during during crowd work, was a blast!
It went from 7pm - 11pm, which was a stretch for my almost-30-something ass, but worth it to tell and hear some funny jokes!&lt;&#x2F;p&gt;
&lt;p&gt;My excuses for not doing more sets were:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Due to scheduling I could only really do this on Tuesday nights.&lt;&#x2F;li&gt;
&lt;li&gt;The first week I thought all the open mics were still on holiday hiatus -- I was wrong but only found that out Wednesday morning.&lt;&#x2F;li&gt;
&lt;li&gt;The second Tuesday I signed up for the Helium open mic... and didn&#x27;t make the list.&lt;&#x2F;li&gt;
&lt;li&gt;The third Tuesday I went to the Montavilla open mic and &lt;em&gt;did&lt;&#x2F;em&gt; perform! Woohoo!&lt;&#x2F;li&gt;
&lt;li&gt;The fourth Tuesday I was sick with a cold.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The Montavilla open mic was &lt;em&gt;so fun&lt;&#x2F;em&gt; I plan on going regularly!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;omsi-science-playground-ages-0-6&quot;&gt;OMSI Science Playground (ages 0-6)&lt;&#x2F;h1&gt;
&lt;p&gt;With the new year we bought an annual pass to OMSI &lt;em&gt;just&lt;&#x2F;em&gt; so we could go to the &lt;a href=&quot;https:&#x2F;&#x2F;omsi.edu&#x2F;exhibits&#x2F;science-playground&#x2F;&quot;&gt;Science Playground&lt;&#x2F;a&gt;.
It&#x27;s an amazing room (for kids) with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a huge secure climbing structure&lt;&#x2F;li&gt;
&lt;li&gt;&quot;like school&quot; lessons room&lt;&#x2F;li&gt;
&lt;li&gt;mock grocery store&lt;&#x2F;li&gt;
&lt;li&gt;foam block pit&lt;&#x2F;li&gt;
&lt;li&gt;water area&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you told me two years ago that this loud, chaotic, germ infested room would be my happy place I would not have believed you.
But knowing that my kid will be safe &lt;em&gt;and&lt;&#x2F;em&gt; entertained, with only one way in and out, it&#x27;s almost euphoric.
#dadMode&lt;&#x2F;p&gt;
&lt;h1 id=&quot;starter-villain&quot;&gt;Starter Villain&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;01&#x2F;starter-villain.jpg&quot; alt=&quot;Starter Villian&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m a big fan of John Scalzi, the author of Old Mans War, Kaiju Preservation Society, and Fuzzy Nation (among others).&lt;&#x2F;p&gt;
&lt;p&gt;Starter Villain was a Christmas present I gave my mom in 2023 which has since circulated through our family back to me.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a solid short novel.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If you &lt;em&gt;like&lt;&#x2F;em&gt; Scalzi&#x27;s other work you should check it out.&lt;&#x2F;li&gt;
&lt;li&gt;If you &lt;em&gt;don&#x27;t know&lt;&#x2F;em&gt; if you like Scalzi yet... you should check it out!&lt;&#x2F;li&gt;
&lt;li&gt;If you &lt;em&gt;don&#x27;t like&lt;&#x2F;em&gt; Scalzi... ok.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;game-makers-toolkit-mind-over-magnet&quot;&gt;Game Makers Toolkit&#x2F;Mind over Magnet&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;01&#x2F;mind-over-magnet.jpg&quot; alt=&quot;Mind Over Magnet&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gamemakerstoolkit.com&#x2F;&quot;&gt;Game Makers Toolkit&lt;&#x2F;a&gt; is one of the &lt;em&gt;many&lt;&#x2F;em&gt; gaming&#x2F;game design Youtubers I follow.
While not my favorite in content or voice, the channel did something &lt;em&gt;wild&lt;&#x2F;em&gt; over the last three years: they made a game!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;2685900&#x2F;Mind_Over_Magnet&#x2F;&quot;&gt;Mind Over Magnet&lt;&#x2F;a&gt; is a short game about a robot helping machines &lt;del&gt;eat the rich&lt;&#x2F;del&gt; escape a factory.
While on it&#x27;s own merits Mind Over Magnet is... meh... when paired with &quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=4Q7eU3VUi14&amp;amp;list=PLc38fcMFcV_uH3OK4sTa4bf-UXGk2NW2n&quot;&gt;Developing&lt;&#x2F;a&gt;&quot; -- the video essay series made in parallel with the game -- it is a unique view into what it takes to create an indie title!
He has episodes about prototyping, scoping, play-testing, burnout&#x2F;motivation, hiring talent for music and art, and eventually shipping!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pools&quot;&gt;Pools&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2025&#x2F;01&#x2F;pools.jpg&quot; alt=&quot;Pools&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;2663530&#x2F;POOLS&#x2F;&quot;&gt;Pools&lt;&#x2F;a&gt; is the best horror game I have played in a while.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Well... that&#x27;s probably not true.
I guess I don&#x27;t play much horror in the first place.
I mean I played Exit8 but -- whatever let&#x27;s move on&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Pools is the most suspenseful horror game I have every played.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yeah that&#x27;s accurate.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Pools has you walking around a dreamlike MC Escher world of pools, and pool-adjacent environments, until eventually you reach the end of a chapter.
You do this for 6 chapters, about 30 minutes each in playtime.
All the while your palms are sweaty and you are pretty sure somebody is breathing down your neck.
But no, nobody is breathing down your neck.
No monsters... just pools.&lt;&#x2F;p&gt;
&lt;p&gt;The &quot;hook&quot; for me is that it &lt;em&gt;never releases the tension&lt;&#x2F;em&gt; inherit in that concept.
There are no other people.
There are no monsters.
There is &lt;em&gt;one&lt;&#x2F;em&gt; jump scare that I only found because I was going &lt;em&gt;out of my way&lt;&#x2F;em&gt; to &lt;em&gt;look&lt;&#x2F;em&gt; for scares -- and honestly that was a blink-and-you&#x27;ll-miss-it event.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a demo on Steam.
Check it out if that sounds interesting.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s good: December 2024</title>
        <published>2024-12-27T00:00:00+00:00</published>
        <updated>2024-12-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2024/12/"/>
        <id>https://elijah.run/whats-good/2024/12/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2024/12/">&lt;h1 id=&quot;friend-s-art-house-show&quot;&gt;&quot;Friend&#x27;s Art&quot; House Show&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;12&#x2F;lucy-art.jpg&quot; alt=&quot;Photography by Lucy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My wonderful wife Lucy had the &lt;em&gt;genius&lt;&#x2F;em&gt; idea of inviting our friends to show their artwork at our home!
None of our friends are &lt;em&gt;professional&lt;&#x2F;em&gt; artists, at least not in the medium they were showing, which made the event really fun!&lt;&#x2F;p&gt;
&lt;p&gt;We had a great showing too!
Folks shared a variety of ARTifacts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Photography from a class taken years ago&lt;&#x2F;li&gt;
&lt;li&gt;Sketches from a class taken recently&lt;&#x2F;li&gt;
&lt;li&gt;Stamps they just got into making (all fall-themed)&lt;&#x2F;li&gt;
&lt;li&gt;A poem made for the event&lt;&#x2F;li&gt;
&lt;li&gt;A piano cover many months in the works&lt;&#x2F;li&gt;
&lt;li&gt;I used the deadline to light a fire under my ass to make a small game.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It was really nice that everybody was able to share a piece of themselves that doesn&#x27;t come up often and which is usually (at best) just hanging up at their home.
It was an open invitation to share a part of yourself you have put time and effort into, but don&#x27;t usually feel  you can brag or show off without it being an &quot;all-eyes-on-me-big-deal&quot; thing.&lt;&#x2F;p&gt;
&lt;p&gt;If this sounds fun you should try it!&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Invite your friends to submit art&lt;&#x2F;li&gt;
&lt;li&gt;Collect the art a few days before the event&lt;&#x2F;li&gt;
&lt;li&gt;Install the art in your home; hang on walls, etc.&lt;&#x2F;li&gt;
&lt;li&gt;Acquire charcuterie and wine (make it feel like a fancy art opening)&lt;&#x2F;li&gt;
&lt;li&gt;Enjoy!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;ubik&quot;&gt;Ubik&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;12&#x2F;ubik.png&quot; alt=&quot;Ubik&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ubik&quot;&gt;Ubik&lt;&#x2F;a&gt; is a novel by Philip K. Dick which somehow I had &lt;em&gt;never&lt;&#x2F;em&gt; heard of but I &lt;em&gt;absolutely loved&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The premise is that in the far future of... (&lt;em&gt;checks notes&lt;&#x2F;em&gt;) &lt;strong&gt;1992&lt;&#x2F;strong&gt; we have flying cars, regular trips to Moon colonies, and micro-transactions in real life.
We also have a way to extend life in a half-living state called Half Life (no relation to physics or the video game), and people with mental powers like mind reading and predicting the future exist -- also people who can cancel those powers out.&lt;&#x2F;p&gt;
&lt;p&gt;The premise is fun and includes a bunch of themes I really like including time-travel-adjacent plots and a dubiously trustworthy narrator.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ubik was a recommendation from a friend who lent me the book which I really appreciated! It was nice to talk about the book and the next day start reading (as opposed to waiting for the library copy that was a few weeks out).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;in-the-miso-soup&quot;&gt;In the Miso Soup&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;12&#x2F;in-the-miso-soup.png&quot; alt=&quot;In the Miso Soup&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;In_the_Miso_Soup&quot;&gt;In the Miso Soup&lt;&#x2F;a&gt; is a psychological horror novel by Ryu Murakami which I really enjoyed!
The way the novel builds tension, then releases it, and then uhh... has an entire third part was very exciting!
I don&#x27;t read a lot of horror but this made me want to get into the genre.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This book was reading for a podcast I follow called &lt;a href=&quot;https:&#x2F;&#x2F;nebula.tv&#x2F;somethingrotten&quot;&gt;Something Rotten&lt;&#x2F;a&gt;.
Usually the hosts talk about Video Games, but they &lt;em&gt;clearly&lt;&#x2F;em&gt; want to talk about books so I&#x27;m glad they are doing a book-club season!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;absolute-batman-ongoing&quot;&gt;Absolute Batman (ongoing)&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;12&#x2F;absolute-batman.png&quot; alt=&quot;Absolute Batman&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;comic&#x2F;2463692&#x2F;absolute-batman-1&quot;&gt;Absolute Batman&lt;&#x2F;a&gt; is an ongoing (as of December 2024) Batman series part of the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Absolute_Universe&quot;&gt;Absolute Universe&lt;&#x2F;a&gt;.
The other Absolute&#x27;s do not quite click for me, but Absolute Batman is my jam.
Batman is poor and scrappy and Alfred is a bad-ass international spy dude and &lt;em&gt;it all rocks&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The art is by &lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;people&#x2F;876&#x2F;nick-dragotta&quot;&gt;Nick Dragotta&lt;&#x2F;a&gt; who you would remember from &lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;comic&#x2F;8063885&#x2F;east-of-west-1&quot;&gt;East of West&lt;&#x2F;a&gt; -- and yes he can only draw one old man but that&#x27;s OK because now that old man is Alfred and he looks like a BAMF.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sonic-the-hedgehog-3&quot;&gt;Sonic The Hedgehog 3&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;12&#x2F;sonic-3.png&quot; alt=&quot;Somic The Hedgehog 3&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Sonic is the only movie series I actually go to the theater to watch.
Not Marvel, not Nolan&#x27;s films like Oppenheimer, just Sonics 1, 2, and now 3.
So trust me when I say Sonic 3 is the best Sonic so far.&lt;&#x2F;p&gt;
&lt;p&gt;As always the film is nothing without Jim Carrey.
Don&#x27;t get me wrong, I love Ben Schwartz but let&#x27;s be real... this is the only Carrey-being-carrey movie we&#x27;ve gotten since uhh... Dumb and Dumber To?
Enjoy the gem (pun intended) that is Jim Carrey as Doctor Robotnik.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s good: November 2024</title>
        <published>2024-11-30T00:00:00+00:00</published>
        <updated>2024-11-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2024/11/"/>
        <id>https://elijah.run/whats-good/2024/11/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2024/11/">&lt;h1 id=&quot;so-much-batman&quot;&gt;So. Much. Batman.&lt;&#x2F;h1&gt;
&lt;p&gt;This month a friend of mine shared that they weren&#x27;t really into comics &lt;em&gt;except for Batman&lt;&#x2F;em&gt;.
I have been reading a &lt;em&gt;lot&lt;&#x2F;em&gt; of comics recently (I&#x27;ll write a post about my backlog journey sometime) and I realized I have &lt;em&gt;never read a batman comic&lt;&#x2F;em&gt;.
No joke, just never picked one up.
I&#x27;ve played games, watched movies, but never engaged with the source material.&lt;&#x2F;p&gt;
&lt;p&gt;This month I changed that.
Let&#x27;s get into it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;batman-year-one&quot;&gt;Batman: Year One&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;11&#x2F;batman-year-one.png&quot; alt=&quot;Batman: Year One&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As the title suggests, this is the &lt;em&gt;classic&lt;&#x2F;em&gt; origin Batman origin story.
Great place to start if you want to get into Batman.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;batman-the-long-halloween&quot;&gt;Batman: The Long Halloween&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;11&#x2F;batman-the-long-halloween.png&quot; alt=&quot;Batman: The Long Halloween&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This was a &lt;em&gt;perfect&lt;&#x2F;em&gt; follow-up to Year One.
It reads more like a noir story and less like a super-hero comic, which I liked.&lt;&#x2F;p&gt;
&lt;p&gt;Also the cape &lt;em&gt;is a character&lt;&#x2F;em&gt;.
Not in the literal sense, but visually it is striking.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;batman-the-white-knight&quot;&gt;Batman: The White Knight&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;11&#x2F;batman-the-white-knight.png&quot; alt=&quot;Batman: The White Knight&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is more current era compared to the Year One and Long Halloween.
It served as an interesting introduction for me to The Joker and Harley Quinn(s).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;toontown-rewritten&quot;&gt;Toontown Rewritten&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;11&#x2F;toontown-rewritten.png&quot; alt=&quot;Toontown Rewritten&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Besides Batman I got into a little MMO called &lt;a href=&quot;https:&#x2F;&#x2F;www.toontownrewritten.com&#x2F;&quot;&gt;Toontown Rewritten&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yes. &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Toontown_Online&quot;&gt;&lt;em&gt;That&lt;&#x2F;em&gt; Toontown&lt;&#x2F;a&gt;. The one from the early 2000&#x27;s.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Toontown Rewritten is &lt;em&gt;amazing&lt;&#x2F;em&gt;.
I have no idea &lt;em&gt;how&lt;&#x2F;em&gt; it got made, but it&#x27;s an entirely community made, free to play, micro-transaction-free MMO in the year of our lord 2024.
&lt;strong&gt;HOW&lt;&#x2F;strong&gt;??&lt;&#x2F;p&gt;
&lt;p&gt;It is fun, free, and a whimsical experience.
You should check it out!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What&#x27;s good: October 2024</title>
        <published>2024-10-31T00:00:00+00:00</published>
        <updated>2024-10-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/whats-good/2024/10/"/>
        <id>https://elijah.run/whats-good/2024/10/</id>
        
        <content type="html" xml:base="https://elijah.run/whats-good/2024/10/">&lt;p&gt;October was a pretty good month for my media diet -- so good in fact I was inspired to start blogging about all the good stuff I&#x27;m enjoying!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;comics-rare-flavors&quot;&gt;Comics: Rare Flavors&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;10&#x2F;rare-flavors.jpg&quot; alt=&quot;Rare Flavors&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;leagueofcomicgeeks.com&#x2F;comics&#x2F;series&#x2F;167569&#x2F;rare-flavours&quot;&gt;Rare Flavors&lt;&#x2F;a&gt; is so goddamn good.
The pastel colors, history spanning story, and love of it&#x27;s culinary subject make for a short and sweet story I think everybody should read.
In fact I&#x27;ve already given a copy to a comics-loving friend and my comics-loving dad.&lt;&#x2F;p&gt;
&lt;p&gt;I read a lot of comics this month, making a modest dent in my 200+ issue backlog (not including trade paperbacks, we&#x27;ll get to those... later).
My big takeaway from &quot;the backlog&quot; is that &lt;a href=&quot;https:&#x2F;&#x2F;imagecomics.com&#x2F;&quot;&gt;Image&lt;&#x2F;a&gt; puts out bangers.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re in Portland check out my go-to comics shop: &lt;a href=&quot;https:&#x2F;&#x2F;bookswithpictures.com&#x2F;&quot;&gt;Books With Pictures&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tech-screenzen&quot;&gt;Tech: ScreenZen&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;10&#x2F;screenzen-example.jpg&quot; alt=&quot;ScreenZen in action&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.screenzen.co&#x2F;&quot;&gt;ScreenZen&lt;&#x2F;a&gt; I have finally broken my addiction to YouTube, an app I use so much I have been a Premium subscriber since it was called &quot;YouTube Red&quot;.
I would recommend it to anybody that wants to spend less time on their phone, or in my case just less time on &lt;em&gt;certain&lt;&#x2F;em&gt; apps.
And hey it&#x27;s free and doesn&#x27;t have ads which feels &lt;em&gt;insane&lt;&#x2F;em&gt; in 2024.&lt;&#x2F;p&gt;
&lt;p&gt;ScreenZen is similar to Android&#x27;s built-in &quot;digital wellbeing timer&quot; but works better for me because it stops you &lt;em&gt;before&lt;&#x2F;em&gt; you open an app &lt;em&gt;as well as&lt;&#x2F;em&gt; limits your over-all usage.
You can set custom timers when an app starts, so you have to wait say 30 seconds before you can actually &lt;em&gt;use&lt;&#x2F;em&gt; an app, as well as per-session timers and sessions-per-day.
This hooks into the dopamine loop much earlier so instead of getting a few minutes of excitement &lt;em&gt;first&lt;&#x2F;em&gt;, and then just upping the timer because its like 2 taps (why is it so easy to do that?), you are forced to sit there... waiting... looking at your reflection in the screen... then after 30 seconds admit you were just trying to avoid a few seconds of boredom -- which of course devolves into 20 minutes of scrolling on the toilet -- but that time has passed so do you really &lt;em&gt;need&lt;&#x2F;em&gt; to scroll?
No.
You&#x27;re free now.
Clean up and get on with your day.&lt;&#x2F;p&gt;
&lt;p&gt;So yeah ScreenZen has been awesome.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;video-dropout-tv&quot;&gt;Video: Dropout.tv&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;whats-good&#x2F;2024&#x2F;10&#x2F;make-some-noise.png&quot; alt=&quot;Make! Some! Noise! Dropout.TV&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Dropout shows like &lt;a href=&quot;https:&#x2F;&#x2F;www.dropout.tv&#x2F;make-some-noise&quot;&gt;Make! Some! Noise!&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.dropout.tv&#x2F;game-changer&quot;&gt;Game Changer&lt;&#x2F;a&gt; have become my new &quot;Internet TV&quot; of choice and I love it.
The production value is on-par with legacy TV, the talent is talenting, and there&#x27;s shows for many tastes.&lt;&#x2F;p&gt;
&lt;p&gt;I wouldn&#x27;t say &lt;em&gt;every&lt;&#x2F;em&gt; show on Dropout is for &lt;em&gt;everybody&lt;&#x2F;em&gt;, I&#x27;ve bounced off of a few of their running series, but if you like comedy game shows&#x2F;tabletop role-playing games there is &lt;em&gt;something&lt;&#x2F;em&gt; on Dropout for you.
They have a wide array of genres and they put out new stuff across a few shows every week.
Oh and they have all of the old CollegeHumor skits which is like... infinite internet nostalgia.&lt;&#x2F;p&gt;
&lt;p&gt;Support indie streaming services!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;music-spotify&quot;&gt;Music: Spotify&lt;&#x2F;h1&gt;
&lt;p&gt;After holding out for about 10 years, I finally caved and started using Spotify and honestly it&#x27;s been pretty nice.&lt;&#x2F;p&gt;
&lt;p&gt;Once I did the exhausting task of manually importing all of my liked songs from -- don&#x27;t cancel me -- YouTube Music, the algorithm has a pretty good idea of what I liked.
Playlists like Discovery Weekly are a good balance between risky and safe choices, shared DJing is a really seamless experience during events, and best of all I don&#x27;t feel judged when I have to say &quot;I don&#x27;t use Spotify, can you just tell me the name of the song so I can listen to it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not all sunshine and rainbows though.
I &lt;em&gt;really&lt;&#x2F;em&gt; wish Spotify&#x27;s performance on Android was better; using the app for more than 20 minutes caused to crash twice during &quot;the great liked songs import&quot;.
I also still believe YouTube Music has a more comprehensive collection, remix albums like Girl Talk&#x27;s &quot;&lt;a href=&quot;https:&#x2F;&#x2F;illegalart.net&#x2F;allday&#x2F;&quot;&gt;All Day&lt;&#x2F;a&gt;&quot; and My Sick Uncle&#x27;s &quot;&lt;a href=&quot;https:&#x2F;&#x2F;patrickmoberg.com&#x2F;500-days-of-weezy&#x2F;&quot;&gt;500 Days of Wheezy&lt;&#x2F;a&gt;&quot; being notable absences from Spotify.&lt;&#x2F;p&gt;
&lt;!-- Links --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>🪐 martian chess♟️</title>
        <published>2024-05-01T00:00:00+00:00</published>
        <updated>2024-05-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/games/martian-chess/"/>
        <id>https://elijah.run/games/martian-chess/</id>
        
        <content type="html" xml:base="https://elijah.run/games/martian-chess/">&lt;style&gt; p&gt;img { width: 100%; } &lt;&#x2F;style&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;games&#x2F;martian-chess.gif&quot; alt=&quot;martian chess gameplay&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;free (download): &lt;a href=&quot;https:&#x2F;&#x2F;liquidmirror.itch.io&#x2F;martian-chess&quot;&gt;liquidmirror.itch.io&#x2F;martian-chess&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;tools: &lt;a href=&quot;https:&#x2F;&#x2F;bevy.org&quot;&gt;bevy&lt;&#x2F;a&gt; (engine), &lt;a href=&quot;https:&#x2F;&#x2F;www.fmod.com&#x2F;&quot;&gt;fmod&lt;&#x2F;a&gt; (audio), [blender] (visuals)&lt;&#x2F;li&gt;
&lt;li&gt;developed: late 2023 - early 2024, released: may 2024&lt;&#x2F;li&gt;
&lt;li&gt;visuals and music by &lt;a href=&quot;https:&#x2F;&#x2F;greatmist.bandcamp.com&#x2F;&quot;&gt;Sam Hall&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After failing for more than a year to make progess on an original game idea, I brought the idea of implementing &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Martian_chess&quot;&gt;Martian Chess&lt;&#x2F;a&gt; to Sam.
The idea being the game design was &quot;done&quot; and the value we were adding was appealing visuals and music.
Sam agreed and we spent a few months making on our first finished game: Martian Chess.
We contacted the publishers of the original board game and let them know of the project; they agreed to let us develop the game with the caveat that we not make money from it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Ergonomics: Default and From</title>
        <published>2022-05-17T00:00:00+00:00</published>
        <updated>2022-05-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/rust-default-from/"/>
        <id>https://elijah.run/blog/rust-default-from/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/rust-default-from/">&lt;p&gt;I&#x27;ve been writing Rust off and on since 2014 and consistently since 2019
when I got into Rust Game Development. Once I started writing more Rust
code I noticed it wasn&#x27;t just more lines of code, but each part of the
code was more verbose.&lt;&#x2F;p&gt;
&lt;p&gt;Coming from Python where ideas &lt;em&gt;tend&lt;&#x2F;em&gt; to be pretty succinct, Rust forced
you to spell everything out in intense detail. Of course you &lt;em&gt;got&lt;&#x2F;em&gt;
something for that verbosity -- &quot;if it compiles, it probably works&quot; --
but my hands were getting tired. There has to be a better way!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verbose-structs&quot;&gt;Verbose Structs&lt;&#x2F;h2&gt;
&lt;p&gt;There is a better way, but let&#x27;s clarify what the problem &lt;em&gt;is&lt;&#x2F;em&gt; exactly.
Take this example of a real struct from the &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;bevy game engine&lt;&#x2F;a&gt; &lt;code&gt;PbrBundle&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;PbrBundle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;MaterialMeshBundle&amp;lt;StandardMaterial&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s a type-alias to a &lt;code&gt;MaterialMeshBundle&lt;&#x2F;code&gt;.
Let&#x27;s check that out:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MaterialMeshBundle&amp;lt;M&amp;gt; where
&lt;&#x2F;span&gt;&lt;span&gt;    M: SpecializedMaterial,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;mesh&lt;&#x2F;span&gt;&lt;span&gt;: Handle&amp;lt;Mesh&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;material&lt;&#x2F;span&gt;&lt;span&gt;: Handle&amp;lt;M&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;transform&lt;&#x2F;span&gt;&lt;span&gt;: Transform,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;global_transform&lt;&#x2F;span&gt;&lt;span&gt;: GlobalTransform,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;visibility&lt;&#x2F;span&gt;&lt;span&gt;: Visibility,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;computed_visibility&lt;&#x2F;span&gt;&lt;span&gt;: ComputedVisibility,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow that&#x27;s a fair number of struct members.&lt;&#x2F;p&gt;
&lt;p&gt;If you wanted to create a &lt;code&gt;PbrBundle&lt;&#x2F;code&gt; by hand it would be a &lt;em&gt;tedious&lt;&#x2F;em&gt; process.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; my_pbr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; PbrBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    mesh: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get_mesh_handle&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    material: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get_material_handle&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    transform: Transform {
&lt;&#x2F;span&gt;&lt;span&gt;        translation: Vec3::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        rotation: Quat::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        scale: Vec3::new(),
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    global_transform: GlobalTransform {
&lt;&#x2F;span&gt;&lt;span&gt;        translation: Vec3::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        rotation: Quat::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        scale: Vec3::new(),
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    visibility: Visibility {
&lt;&#x2F;span&gt;&lt;span&gt;        is_visibile: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    computed_visibility: ComputedVisibility {
&lt;&#x2F;span&gt;&lt;span&gt;        is_visibile: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow my fingers are already tired.&lt;&#x2F;p&gt;
&lt;p&gt;Now, assuming you don&#x27;t know the punchline, you&#x27;re probably thinking:
&lt;em&gt;Just use a constructor!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That solves the use-case where the author of the code has a constructor for my use-case, something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; my_pbr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;PbrBundle::new(mesh, material); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Default Transform and Visibilty
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what if I want a &lt;em&gt;mostly&lt;&#x2F;em&gt; &quot;default&quot; &lt;code&gt;PbrBundle&lt;&#x2F;code&gt;, with say &lt;code&gt;is_visible = false&lt;&#x2F;code&gt;?
Or I want to add a Transform with a custom scale but a default translation and rotation?&lt;&#x2F;p&gt;
&lt;p&gt;Basically, what if I am &lt;em&gt;picky&lt;&#x2F;em&gt; and want the &lt;em&gt;flexibility&lt;&#x2F;em&gt; of struct initialization with the &lt;em&gt;convenience&lt;&#x2F;em&gt; of constructor methods?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;default-fill-in-the-blanks&quot;&gt;Default: Fill in the blanks&lt;&#x2F;h2&gt;
&lt;p&gt;This is totally supported thanks to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;default&#x2F;trait.Default.html&quot;&gt;Rust&#x27;s &quot;Default&quot; Trait&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The usage is something like this from the previous example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; my_pbr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; PbrBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    mesh: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get_mesh_handle&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    material: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;get_material_bundle&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    transform: Transform {
&lt;&#x2F;span&gt;&lt;span&gt;        scale: Vec3::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    visibility: Visibilty {
&lt;&#x2F;span&gt;&lt;span&gt;        is_visible: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example shows creating a &lt;code&gt;PbrBundle&lt;&#x2F;code&gt; with a custom &lt;code&gt;mesh&lt;&#x2F;code&gt;, &lt;code&gt;material&lt;&#x2F;code&gt;, and &lt;code&gt;scale&lt;&#x2F;code&gt;, but everything else is a &quot;Default&quot; value.&lt;&#x2F;p&gt;
&lt;p&gt;While this flexibility is totally possible with constructors, it would require some creativity, maybe something like this?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pbr_bundle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;PbrBundle::new(mesh, material)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_scale&lt;&#x2F;span&gt;&lt;span&gt;(Vec3::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_visibility&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is fine, but it is a &lt;strong&gt;lot&lt;&#x2F;strong&gt; of toil for the author.
They need to add and maintain a method for each element of their nested struct, document those methods, probably write tests, and all to accomplish the goal of a &quot;Fill in the rest for me&quot; API.&lt;&#x2F;p&gt;
&lt;p&gt;One nice part of &lt;code&gt;Default&lt;&#x2F;code&gt; is it can be automagically added to any struct whose members implement it via &lt;code&gt;#[derive(Default)]&lt;&#x2F;code&gt;.
This means you get that &quot;Fill in the rest for me&quot; interface for free!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;close-but-distinct-types&quot;&gt;Close but Distinct Types&lt;&#x2F;h2&gt;
&lt;p&gt;Another pain-point I found in Rust was converting between similar but distinct types.
Unlike my last language Python, which was &lt;em&gt;very&lt;&#x2F;em&gt; forgiving about types (to a fault), Rust requires very precise type expressions.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take this example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Base Engine Color
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Default, Debug, PartialEq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Color {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;red&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;green&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;blue&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F;&#x2F; Color for UI elements
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Default, Debug, PartialEq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;UiColor(Color);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F;&#x2F; Just a demo function, not sure if this is useful...
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;color_rotate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;: Color) -&amp;gt; Color {
&lt;&#x2F;span&gt;&lt;span&gt;    Color {
&lt;&#x2F;span&gt;&lt;span&gt;        red: color.green,
&lt;&#x2F;span&gt;&lt;span&gt;        green: color.blue,
&lt;&#x2F;span&gt;&lt;span&gt;        blue: color.red,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Does not compile!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; E0308: mismatched types expected struct `Color`, found struct `UiColor`
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; UiColor(Color {
&lt;&#x2F;span&gt;&lt;span&gt;        red: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;color_rotate&lt;&#x2F;span&gt;&lt;span&gt;(a);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we have a &lt;code&gt;UiColor&lt;&#x2F;code&gt; struct that wraps our base &lt;code&gt;Color&lt;&#x2F;code&gt; struct.
We want to use a method made for &lt;code&gt;Color&lt;&#x2F;code&gt; values but we get an error that the compiler is expecting a &lt;code&gt;Color&lt;&#x2F;code&gt; but we gave it a &lt;code&gt;UiColor&lt;&#x2F;code&gt;!
Come on Rust, just look inside the box!&lt;&#x2F;p&gt;
&lt;p&gt;We can work around this issue like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; UiColor(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;color_rotate&lt;&#x2F;span&gt;&lt;span&gt;(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which passes the inside of &lt;code&gt;a&lt;&#x2F;code&gt; to &lt;code&gt;color_rotate&lt;&#x2F;code&gt; and then wraps the return in a new &lt;code&gt;UiColor&lt;&#x2F;code&gt; struct.
This works, but it&#x27;s hard to read and more importantly it requires a keep our API in our head to write &lt;em&gt;any&lt;&#x2F;em&gt; code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-and-into-simple-type-coercion&quot;&gt;From and &lt;code&gt;into&lt;&#x2F;code&gt;: Simple type coercion&lt;&#x2F;h2&gt;
&lt;p&gt;The solution is to use the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;convert&#x2F;trait.From.html&quot;&gt;&quot;From&quot;&lt;&#x2F;a&gt; and trait which provides the &lt;code&gt;into()&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;p&gt;Extending the above example, we can implement &lt;code&gt;From Color -&amp;gt; UiColor&lt;&#x2F;code&gt; and &lt;code&gt;From UiColor -&amp;gt; Color&lt;&#x2F;code&gt; like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Color&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;UiColor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: Color) -&amp;gt; UiColor {
&lt;&#x2F;span&gt;&lt;span&gt;        UiColor(input)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;UiColor&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Color {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: UiColor) -&amp;gt; Color {
&lt;&#x2F;span&gt;&lt;span&gt;        input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately we can&#x27;t do anything like &lt;code&gt;#[derive(From&amp;lt;UiColor&amp;gt;)]&lt;&#x2F;code&gt; (yet?) but implementing these traits is fairly straight forward and &lt;em&gt;very&lt;&#x2F;em&gt; powerful.&lt;&#x2F;p&gt;
&lt;p&gt;Here we can see our &lt;code&gt;main&lt;&#x2F;code&gt; function is fixed with passing assertions.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; UiColor(Color {
&lt;&#x2F;span&gt;&lt;span&gt;        red: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(a, UiColor(Color { red: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;, green: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, blue: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0 &lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b: UiColor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;color_rotate&lt;&#x2F;span&gt;&lt;span&gt;(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(b, UiColor(Color { red: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, green: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, blue: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.5 &lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust was not only able to cast our &lt;code&gt;UiColor&lt;&#x2F;code&gt; to a &lt;code&gt;Color&lt;&#x2F;code&gt; in the call to &lt;code&gt;color_rotate&lt;&#x2F;code&gt; but we were able to coerce the result back to a &lt;code&gt;UiColor&lt;&#x2F;code&gt; by declaring the type of our &lt;code&gt;b&lt;&#x2F;code&gt; variable.&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;code&gt;From&lt;&#x2F;code&gt; and &lt;code&gt;into()&lt;&#x2F;code&gt; is great because it allows you to ignore the specifics of the types you&#x27;re working with while still getting the benefits of a strong type system.
When you use it enough it can feel like parts of your code are &quot;Duckly&quot; typed, like Python and Ruby which have very ergonomic type interactions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-simple-to-complex&quot;&gt;From Simple to Complex&lt;&#x2F;h2&gt;
&lt;p&gt;Since learning about &lt;code&gt;From&lt;&#x2F;code&gt; started to abuse it to convert simplified types to more complex ones.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example this UI struct in Bevy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;NodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;node&lt;&#x2F;span&gt;&lt;span&gt;: Node,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;style&lt;&#x2F;span&gt;&lt;span&gt;: Style,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;: UiColor,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: UiImage,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;focus_policy&lt;&#x2F;span&gt;&lt;span&gt;: FocusPolicy,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;transform&lt;&#x2F;span&gt;&lt;span&gt;: Transform,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;global_transform&lt;&#x2F;span&gt;&lt;span&gt;: GlobalTransform,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;visibility&lt;&#x2F;span&gt;&lt;span&gt;: Visibility,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On it&#x27;s own this isn&#x27;t bad, but if you write enough UI code it can get tedious.
Both &lt;code&gt;Node&lt;&#x2F;code&gt; and &lt;code&gt;Style&lt;&#x2F;code&gt; are nested structs that have a lot of complexity -- &lt;code&gt;Style&lt;&#x2F;code&gt; is a struct with 21 members! -- so using &lt;code&gt;Default&lt;&#x2F;code&gt; won&#x27;t cut it here.&lt;&#x2F;p&gt;
&lt;p&gt;Instead I made a &quot;dumbed down&quot; version like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;SimpleNodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;position&lt;&#x2F;span&gt;&lt;span&gt;: SimplePosition,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span&gt;: Color,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;: Vec2,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;SimplePosition {
&lt;&#x2F;span&gt;&lt;span&gt;    BottomLeft,
&lt;&#x2F;span&gt;&lt;span&gt;    BottomRight,
&lt;&#x2F;span&gt;&lt;span&gt;    TopLeft,
&lt;&#x2F;span&gt;&lt;span&gt;    TopRight,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is maybe &lt;em&gt;too&lt;&#x2F;em&gt; simple, but you can add the complexity you need down the line. The important part is that our &lt;code&gt;Simple&lt;&#x2F;code&gt; struct is you know... less complex than what it&#x27;s going to map to.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have a simple struct that we can use to quickly write out some UI elements.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; my_ui_element &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; SimpleNodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    position: SimplePosition::TopRight,
&lt;&#x2F;span&gt;&lt;span&gt;    size: Vec2 { x: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;25.0&lt;&#x2F;span&gt;&lt;span&gt;, y: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;100.0 &lt;&#x2F;span&gt;&lt;span&gt;},
&lt;&#x2F;span&gt;&lt;span&gt;    color: Color::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;RED&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On it&#x27;s own though this is useless.
Bevy doesn&#x27;t know what a &lt;code&gt;SimpleNodeBundle&lt;&#x2F;code&gt; is, we need to convert this to the &quot;lower level&quot; struct it&#x27;s replacing.
We need to cast it up to a Bevy &lt;code&gt;NodeBundle&lt;&#x2F;code&gt; with an implementation of &lt;code&gt;From&amp;lt;SimpleNodeBundle&amp;gt; for NodeBundle&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;SimpleNodeBundle&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;NodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;from(input: SimpleNodeBundle) -&amp;gt; NodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;        NodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;            color: UiColor(input.color),
&lt;&#x2F;span&gt;&lt;span&gt;            style: Style {
&lt;&#x2F;span&gt;&lt;span&gt;                position: input.position.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;                size: input.size.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; NodeBundle&amp;#39;s position is a Rect&amp;lt;Val&amp;gt; so we convert SimplePosition to Rect&amp;lt;Val&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;SimplePosition&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Rect&amp;lt;Val&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;from(input: SimplePosition) -&amp;gt; Rect&amp;lt;Val&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;SimplePosition::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; input {
&lt;&#x2F;span&gt;&lt;span&gt;            BottomLeft  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Rect {
&lt;&#x2F;span&gt;&lt;span&gt;                bottom: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                left: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;            BottomRight &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Rect {
&lt;&#x2F;span&gt;&lt;span&gt;                bottom: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                right: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;            TopLeft     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Rect {
&lt;&#x2F;span&gt;&lt;span&gt;                top: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                left: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;            TopRight    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Rect {
&lt;&#x2F;span&gt;&lt;span&gt;                top: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                right: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default()
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Similarly size is a Size&amp;lt;Val&amp;gt; but we have a Vec2, so we conver to the right type
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Vec2&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Size&amp;lt;Val&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;from(input: Vec2) -&amp;gt; Size&amp;lt;Val&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Size {
&lt;&#x2F;span&gt;&lt;span&gt;            width: Val::Px(input.x),
&lt;&#x2F;span&gt;&lt;span&gt;            height: Val::Px(input.y),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Putting this all together we get (pseudocode) something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; my_ui_element &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; SimpleNodeBundle {
&lt;&#x2F;span&gt;&lt;span&gt;    position: SimplePosition::TopRight,
&lt;&#x2F;span&gt;&lt;span&gt;    size: Vec2 { x: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;25.0&lt;&#x2F;span&gt;&lt;span&gt;, y: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;100.0 &lt;&#x2F;span&gt;&lt;span&gt;},
&lt;&#x2F;span&gt;&lt;span&gt;    color: Color::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;RED&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;some_bevy_ui_method&lt;&#x2F;span&gt;&lt;span&gt;(my_ui_element.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Skeptical readers might be thinking &quot;Wow that is awful.
This is so much code just to convert one stuct to another slightly simpler struct&quot;.
You&#x27;re right that it&#x27;s a lot of code, but I promise in practice this is a game changer.
Instead of remembering how to express your ideas to your library of choice every single time, you can express a higher level concept and &lt;code&gt;.into()&lt;&#x2F;code&gt; your framework&#x27;s lower-level structure.
Being able to succinctly express yourself while still getting the flexibility of a strong expressive type system is a killer feature of Rust and the use of these traits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Many of Rust&#x27;s &quot;pros&quot; are also &quot;cons&quot;.
Memory safety results in frustratingly negotiating with the compiler.
A strong type system with compile-time complexity results in slow (but improving) compile times.&lt;&#x2F;p&gt;
&lt;p&gt;For the purposes of this post it is Rust&#x27;s bias toward being explicit.
Unlike other languages which automagically apply crazy changes to your code, Rust rarely &lt;em&gt;assumes&lt;&#x2F;em&gt; you want magic sprinkled everywhere.
You can opt-in to that magic and all of the compile-time and runtime penalties that come with it, but it won&#x27;t be secretly given to you for you to
opt-out of.&lt;&#x2F;p&gt;
&lt;p&gt;Rust can sprinkle magic on your code, but you have to explicitly call &lt;code&gt;.magic()&lt;&#x2F;code&gt; -- or in our case &lt;code&gt;.into()&lt;&#x2F;code&gt; and &lt;code&gt;.default()&lt;&#x2F;code&gt;.
This is a nice middle ground between tedious code and black magic.
When a language has &lt;em&gt;too much&lt;&#x2F;em&gt; magic it can result in wild performance implications from seemingly small code changes.
While tedious code is just a pain to write, even if it is transparent about it&#x27;s runtime performance.
Here Rust is able to be transparent, you can audit every use of &lt;code&gt;.into()&lt;&#x2F;code&gt; and assess the runtime penalty, while still feeling magical.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Buying a House Part 4: Is this investing?</title>
        <published>2022-01-18T00:00:00+00:00</published>
        <updated>2022-01-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/buying-a-house-04-is-this-investing/"/>
        <id>https://elijah.run/blog/buying-a-house-04-is-this-investing/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/buying-a-house-04-is-this-investing/">&lt;p&gt;&lt;em&gt;This is part 4 of a 4 part series on buying a home&lt;&#x2F;em&gt;.
&lt;em&gt;Check out &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-01-lets-go-shopping&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt; for to start from the beginning.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Before buying a house a major talking point used to convince me of the idea was some variation of &quot;It&#x27;s a great investment!&quot; or &quot;You&#x27;re just throwing money away by renting&quot;.
I try to have a healthy level of skepticism about things, especially when counter-arguments aren&#x27;t part of most the usual talking points on a topic.
So let&#x27;s figure out &quot;is buying a house a good investment?&quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;houses-are-a-great-investment-origin-story&quot;&gt;&quot;Houses are a great investment&quot; origin story&lt;&#x2F;h2&gt;
&lt;p&gt;Before de-bunking -- or just bunking -- this myth, let&#x27;s ask where it came from.&lt;&#x2F;p&gt;
&lt;p&gt;Hundreds of years ago, when you had to own property to be considered a voting citizen, investing in property was a great idea! Housing was the most affordable asset you could buy that could passively grow in value.&lt;&#x2F;p&gt;
&lt;p&gt;As the years went on this continued to be true.
Housing is a market rarely which declines value, with umm... one big exception, and it can easily be passed on to family, creating generational wealth.&lt;&#x2F;p&gt;
&lt;p&gt;This notion also pre-dates easier market investing tools like the index fund, Vanguard, and Robinhood.
When it wasn&#x27;t really clear how an average individual could get a diversified portfolio of stocks and bonds, a house was a safe investment that was all but guaranteed to increase in value -- and it would protect you from snow and rain and
shit!&lt;&#x2F;p&gt;
&lt;p&gt;So the origin story of this mantra isn&#x27;t &lt;em&gt;false&lt;&#x2F;em&gt;, but it may be outdated.
Let&#x27;s find out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;meet-finley&quot;&gt;Meet Finley&lt;&#x2F;h2&gt;
&lt;p&gt;For the purposes of this post we will invent a hypothetical protagonist named Finley.
Our fictional mascot was created in a lab to be incredibly average: the most basic curve-fitting person we could find in the the Portland tri-state area.
Finley likes all the Marvel movies, drinks IPAs, and they go on hikes every other weekend.
They also make an average salary, live in an average apartment, and intend to buy an average house.
How convenient for talking about hypotheticals.&lt;&#x2F;p&gt;
&lt;p&gt;Finley lives in Portland, so all of our numbers are for Portland Oregon, USA.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;first-finley-rents-an-apartment&quot;&gt;First Finley rents an apartment&lt;&#x2F;h3&gt;
&lt;p&gt;Finley is currently renting an apartment. On average this is $1250 for the Portland area.
This is roughly equivalent to what you would pay for a mortgage on a 300k house with a 20% (60k) down payment and a 3.0% interest rate (which is only a little optimistic).&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what I used to cook up those numbers: *
&lt;a href=&quot;https:&#x2F;&#x2F;www.mortgagecalculator.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.mortgagecalculator.org&#x2F;&lt;&#x2F;a&gt; *
&lt;a href=&quot;https:&#x2F;&#x2F;www.realtor.com&#x2F;mortgage&#x2F;rates&#x2F;Portland_OR&quot;&gt;https:&#x2F;&#x2F;www.realtor.com&#x2F;mortgage&#x2F;rates&#x2F;Portland_OR&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;then-finley-buys-a-house&quot;&gt;Then Finley buys a house&lt;&#x2F;h3&gt;
&lt;p&gt;In 2020, when I bought a house, the median house prices ranged from 430k to 500k trending upward.
In the last 12 months from writing this post median home prices have ranged from 469k to 550k with a trend still going up.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.redfin.com&#x2F;city&#x2F;30772&#x2F;OR&#x2F;Portland&#x2F;housing-market&quot;&gt;https:&#x2F;&#x2F;www.redfin.com&#x2F;city&#x2F;30772&#x2F;OR&#x2F;Portland&#x2F;housing-market&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For simplicity let&#x27;s say Finley got a deal and bought a house for 480k with a 3.0% mortgage rate.
Their down-payment is 96k and their monthly mortgage payment is $1,900.&lt;&#x2F;p&gt;
&lt;p&gt;Right off the bat Finley is paying 650 more per month on top of the 96k they had to pay up front.
Let&#x27;s assume Finley is still able to cover this cost since they&#x27;re very frugal and despite cost of living going up 34% they are still spending less than 1&#x2F;3 of their income on living expenses.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-money-works-for-you&quot;&gt;How money works for you&lt;&#x2F;h2&gt;
&lt;p&gt;What has Finley &lt;em&gt;financially&lt;&#x2F;em&gt; gained and lost by buying a house?&lt;&#x2F;p&gt;
&lt;p&gt;Finley has &lt;em&gt;lost&lt;&#x2F;em&gt; the ability to invest a lump sum of 96k on top of an extra 600&#x2F;month which could be going toward a range of investments.
Assuming Finley would have invested this in a stock market index we expect this to have increased in value by about 10% year over year given historical trends.
To put numbers to these claims: 96k alone would have appreciated in value to 1,600,000 over 30 years, the duration of most home loans.
If we add the additional 600&#x2F;month we would have about 2,860,000 after 30 years.&lt;&#x2F;p&gt;
&lt;p&gt;(these are very rough calculations using this python code)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;600 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;12  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Annual investable income
&lt;&#x2F;span&gt;&lt;span&gt;s &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;96000     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Starting seed fund
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;30&lt;&#x2F;span&gt;&lt;span&gt;):  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Collect 30 years
&lt;&#x2F;span&gt;&lt;span&gt;  s &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.1           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Grow by 10% for the year
&lt;&#x2F;span&gt;&lt;span&gt;  s &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+= &lt;&#x2F;span&gt;&lt;span&gt;a             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Add money saved by renting
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(this is a very rough approximation of collecting interest over 30 years)&lt;&#x2F;p&gt;
&lt;p&gt;Note this doesn&#x27;t mean he are guaranteed to have 2.9 million at the end of 30 years; some of those gains would be diminished by inflation, rent would go up, and the market could have a down-turn at the 30 year mark.
Plus, Finley would probably spend more as they get older (called &quot;lifestyle inflation&quot;) resulting in diminished invest-able funds -- but they would also probably get cost of living raises over time, so this should all come out in the wash.&lt;&#x2F;p&gt;
&lt;p&gt;But a house would &lt;em&gt;also&lt;&#x2F;em&gt; grow in value right?
This is tricky to calculate because we&#x27;re in a weird housing market right now -- don&#x27;t
call it a bubble -- but let&#x27;s take the last 10 years at face value.
In 2011 the median Portland house was ~260k, and today it is ~550k.
This is a 111% return over 10 years, or 7.82% annually.&lt;&#x2F;p&gt;
&lt;p&gt;So if Finley sold their house after 10 years they would make a profit of ~290k.&lt;&#x2F;p&gt;
&lt;p&gt;I neglected to calculate what Finely&#x27;s index fund strategy would return after only 10 years, so let&#x27;s do that now.
Using the above code, but limiting it to just 10 years instead of 30, we get a ~363k total which does beat the housing investment by a fair margin.
&lt;a href=&quot;https:&#x2F;&#x2F;www.calculator.net&#x2F;roi-calculator.html?beginbalance=259000&amp;amp;endbalance=550000&amp;amp;investmenttime=date&amp;amp;investmentlength=2.5&amp;amp;beginbalanceday=08%2F01%2F2011&amp;amp;endbalanceday=08%2F01%2F2021&amp;amp;ctype=1&amp;amp;x=69&amp;amp;y=36&#x2F;&quot;&gt;citation needed&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note that I am omitting all of the nickles and dimes that add up on both sides.
Capital gains tax makes your index fund strategy less appealing.
Home ownership means you are on the hook to fix anything that breaks, pay property tax, and there are fees associated with buying and selling a home -- plus the cost of the loan which we didn&#x27;t touch on at all!
At the same time, all the money Finley was paying in rent really was being flushed away and not appreciating in value, which is a shame.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;elijah-just-tell-me-if-it-s-good-or-bad&quot;&gt;Elijah, just tell me if it&#x27;s good or bad&lt;&#x2F;h2&gt;
&lt;p&gt;A house is not a great investment, but that&#x27;s not the point.&lt;&#x2F;p&gt;
&lt;p&gt;I didn&#x27;t buy a house because it was a good investment, I bought a house because I wanted more space and it penciled out to about the same monthly cost as my super expensive bougie central-Portland apartment.
I am glad that my house will re-coop some cost when I decide to move out, and I do like the stability of home ownership; I don&#x27;t need to worry about rent going up, or getting evicted because my landlord wants to demolish the building for something else, etc.&lt;&#x2F;p&gt;
&lt;p&gt;So many variables go into the &quot;is this a good investment&quot; question.
If you need to stretch yourself thin, or you already have debt, or what the monthly cost is -- all of these and more contribute to the viability of buying a house.
If your monthly housing costs wouldn&#x27;t go up, it&#x27;s probably a solid move.&lt;&#x2F;p&gt;
&lt;p&gt;Home ownership is not perfect, it&#x27;s not a great investment, but it is an OK use of your money if you can afford it.
It&#x27;s financially sound if you can make it work, comfortably, but it&#x27;s not your only option.
Being frugal and renting an affordable apartment allows you to make other &quot;better&quot; investments, if that&#x27;s all you&#x27;re min-maxing for.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t regret buying a house (yet?) but I would be just as happy if I was renting a house, or still living in an apartment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-more-soap-box&quot;&gt;One more soap-box&lt;&#x2F;h2&gt;
&lt;p&gt;Side note: we need to build more housing.
Portland passed a bill recently allowing more dense housing.
If I had more money I would throw money at building triplex housing in Portland.&lt;&#x2F;p&gt;
&lt;p&gt;For too many of my 20-something peers the problem is not &quot;If I want to buy a house&quot; but &quot;When can I afford to buy a house?&quot;.
There is a bit of a market boom right now, but with more housing the market should settle down.
In a perfect world anybody would be able to buy property if they want.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Thank you for reading this fourth and final installment of my housing series.
Now go out a buy a house!&lt;&#x2F;p&gt;
&lt;p&gt;Lol, just kidding.
Go do more research you crazy kid.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Buying a House Part 3: Renovation Station!</title>
        <published>2022-01-04T00:00:00+00:00</published>
        <updated>2022-01-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/buying-a-house-03-renovation-station/"/>
        <id>https://elijah.run/blog/buying-a-house-03-renovation-station/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/buying-a-house-03-renovation-station/">&lt;p&gt;&lt;em&gt;This is part 3 of a 4 part series on buying a home&lt;&#x2F;em&gt;.
&lt;em&gt;Check out &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-01-lets-go-shopping&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt; for to start from the beginning.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Congratulations!
You slogged through finding, trying to buy, and then successfully buying a house.
Give yourself a pat on the back because that is an impressive feat you&#x27;ve accomplished.&lt;&#x2F;p&gt;
&lt;p&gt;This post is more of a personal post than the others covering the renovations we&#x27;ve made to our house in the first year.
I hope it helps illustrate some of the pros (and cons) of being able to do whatever the heck you want when you own the place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-fuck-up-this-yard&quot;&gt;Let&#x27;s fuck up this yard&lt;&#x2F;h2&gt;
&lt;p&gt;The best part of our house has been the back yard.
I&#x27;m writing this post from my standing desk on my back patio, our doggo loves playing fetch in the yard, and we even started a garden.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;patiooooo&quot;&gt;Patiooooo&lt;&#x2F;h3&gt;
&lt;p&gt;Our first project was to build a stone patio.
Not some half-assed &quot;throw some rocks on the ground and call it good&quot; thing, but some real HGTV quality shit.&lt;&#x2F;p&gt;
&lt;p&gt;Lucy of course did all of the research, planning, and purchasing of materials.
I moved a bunch of rocks.&lt;&#x2F;p&gt;
&lt;p&gt;Before we could build the patio we had to dig 7&quot; of dirt out from the ground, which is non-trivial.
We invited some friends, bought Thai food, and got to work in late October.&lt;&#x2F;p&gt;
&lt;p&gt;Fun fact: 7&quot; of dirt for a 10&quot;x16&quot; hole is a shit-ton of dirt.
We eventually had to rent one of those big metal waste disposal bins you usually see in front of houses or other construction sites.
Of course then we had to move the dirt a second time from piles in our yard to the bin, but then it was gone for good.&lt;&#x2F;p&gt;
&lt;p&gt;Once we dug out the dirt we were able to fill it back in with rocks (pebbles) then smaller rocks (sand) and finally pavers, which is what the industry calls short cube rocks -- not to be confused with bricks.&lt;&#x2F;p&gt;
&lt;p&gt;The hardest part was definitely making everything flat.
The pavers are big squares, which I though would be forgiving if the underlying sand and gravel wasn&#x27;t flat, but wow I was wrong.
Eventually I found my groove and got very zen about making the sand flat.
We used used a 10&#x27; 2x4 and dragged it across our layer of sand in a variety of patterns until eventually it was &quot;flat enough&quot;.
In retrospect it was kinda fun.
Very calming once you submit to the process.&lt;&#x2F;p&gt;
&lt;p&gt;Finally we put the pavers down, filled the cracks with polymeric sand (which is just &quot;concrete lite&quot;), and sealed that bitch up.&lt;&#x2F;p&gt;
&lt;p&gt;The whole project took a few weeks and cost about 1k for materials.&lt;&#x2F;p&gt;
&lt;p&gt;We almost gave up at the end when we realized making things flat was way harder than expected.
The quote to get the project finished, which was 90% done, was around 5k which gave us heart-burn so we stubbornly finished it ourselves.
So it turns out we saved ~5k by doing this project ourselves.&lt;&#x2F;p&gt;
&lt;p&gt;After this I&#x27;m game to do any home project myself as long as it doesn&#x27;t involve electricity and plumbing in the walls.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;baby-you-re-a-fiiiireee-pit&quot;&gt;Baby you&#x27;re a fiiiireee-pit&lt;&#x2F;h3&gt;
&lt;p&gt;A comparatively small project was our fire pit.
This was just a fire ring with some bricks stacked on the outside.
Very safe, very simple.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly it was nice to get a quick win.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;big-ass-raised-bed&quot;&gt;Big ass raised bed&lt;&#x2F;h3&gt;
&lt;p&gt;We also built a big ass raised bed.
It&#x27;s 4&#x27;x12&#x27; and it gets a &lt;em&gt;lot&lt;&#x2F;em&gt; of sun.
Also a quick win.&lt;&#x2F;p&gt;
&lt;p&gt;Everything feels like a quick win after building that fucking patio.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;new-hvac-who-this&quot;&gt;New HVAC, who this?&lt;&#x2F;h2&gt;
&lt;p&gt;In December ancient gas furnace ran out of diesel, resulting in not having heat... funny how that works.
This is usually trivial to solve: you call a company and they fill your gas tank and charge you a few hundo.
With gas in the tank your heat comes back on.&lt;&#x2F;p&gt;
&lt;p&gt;Multiple people talked about how great the furnace we had was.
It was installed with the house, so it was at least 70 years old and it did work well.
The heat that came out of the vents was super hot, but it also ran on gasoline in a tank in our basement.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m sure the carbon footprint of my home&#x27;s gas heating is negligible when compared to the carbon footprint of every flight I take, but Lucy and I decided if we &lt;em&gt;could&lt;&#x2F;em&gt; get rid of it we &lt;em&gt;should&lt;&#x2F;em&gt;.
We did some research on alternatives and decided an electric Heat-Pump would be a good alternative.
It would provide us with heat &lt;em&gt;and&lt;&#x2F;em&gt; cooling, and wouldn&#x27;t run on diesel; the only downside is it&#x27;d be expensive.&lt;&#x2F;p&gt;
&lt;p&gt;A few things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A Heat-Pump is a heating and cooling system that operates on similar physics to a refrigerator (taking warm air and turning it into cool air, and the inverse).&lt;&#x2F;li&gt;
&lt;li&gt;The Heat-Pump has an outdoor unit, you&#x27;ve definitely seen them outside some homes.
Usually it&#x27;s a metal box about 3&quot; cubed with a fan.&lt;&#x2F;li&gt;
&lt;li&gt;They don&#x27;t tell you that&#x27;s just the &lt;em&gt;outdoor&lt;&#x2F;em&gt; part of the Heat-Pump, there is also a huge freaking indoor unit that converts chemical energy into warm&#x2F;cool air that gets pumped around your house.&lt;&#x2F;li&gt;
&lt;li&gt;Heat-pumps are fully electric so no gas!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So that&#x27;s how a Heat-Pump works.
A few stars aligned for this to work out:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Our house already has vents that the oil furnace used to heat the house.
This means we can easily heat&#x2F;cool the entire house with one indoor unit.&lt;&#x2F;li&gt;
&lt;li&gt;We had some extra cash we didn&#x27;t end up needing for our down-payment, so we were able to pay in cash saving us a lot in interest payments for the Heat-Pump (like 10%!).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We could have made it work without those happy coincidences; they make in-wall Heat-Pumps that heat&#x2F;cool one or two rooms, and we could have financed if we were strapped for cash, or we could have just kept the old gas furnace.
But we &lt;em&gt;were&lt;&#x2F;em&gt; able to upgrade our central-air because 6 months later Portland had a 118℉  heat wave and another 100℉+ heat wave the day before our wedding!
Both of which we barely worried about because we were fortunate enough to have AC.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;life-after-renting&quot;&gt;Life after renting&lt;&#x2F;h2&gt;
&lt;p&gt;I hope this post showed some of the awesome pros of home ownership, like being able to add a patio, with some healthy cons, like having to spend 12k on a new furnace.
We were able to get rid of the gas guzzling heating system in favor of a full-electric system.
We were able to build a patio, add a raised bed, fuck up the yard, without asking anybody for permission.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a lot of work, and a lot of money sometimes, but it is empowering to be able to &lt;em&gt;own&lt;&#x2F;em&gt; your house.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In the next post we&#x27;ll throw all this soft &quot;american dream&quot; and
&quot;empowered to change&quot; stuff out the window and figure out if this is a
good investment!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Buying a House Part 2: Show Me The Money!</title>
        <published>2021-12-21T00:00:00+00:00</published>
        <updated>2021-12-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/buying-a-house-02-show-me-the-money/"/>
        <id>https://elijah.run/blog/buying-a-house-02-show-me-the-money/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/buying-a-house-02-show-me-the-money/">&lt;p&gt;&lt;em&gt;This is part 2 of a 4 part series on buying a home&lt;&#x2F;em&gt;.
&lt;em&gt;Check out &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-01-lets-go-shopping&#x2F;&quot;&gt;part 1&lt;&#x2F;a&gt; for to start from the beginning.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In this post we will talk about everything that happens between getting an offer accepted on a house and your move-in day.
How exciting!
Let&#x27;s get started.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-you-got-an-offer-accepted&quot;&gt;So you got an offer accepted&lt;&#x2F;h2&gt;
&lt;p&gt;You slogged through the home-buying process, your heart was broken in 12 pieces when you barely didn&#x27;t get &quot;the one&quot; and then &quot;the other one&quot; and finally &quot;the real one&quot;, but you powered through and now you have an offer accepted.&lt;&#x2F;p&gt;
&lt;p&gt;Great, you&#x27;re half way done!
Just kidding, this part is much easier, but it is time consuming.&lt;&#x2F;p&gt;
&lt;p&gt;Now in theory you can skip all these steps with a shit-ton of money and taking a shot of unnecessary risk.
I mean you can pay in cash for a house &lt;em&gt;and&lt;&#x2F;em&gt; waive home inspections to expedite the home-buying process.
I only have one anecdote of this happening, and the guy who told it to me was a prick, so I&#x27;m pretty sure it&#x27;s fake news.
The only reason you would pay in cash is to avoid paying mortgage fees and to close the deal faster.
The only reason you would waive inspections is to make close on the house faster if you don&#x27;t care or really trust the current owner.
Mortgage rates are bonkers low right now, and most people aren&#x27;t in &lt;em&gt;that much&lt;&#x2F;em&gt; of a rush to close on their house, so again: fake news.
For normal people with a normal amount of debt and a sane income we do things the way I&#x27;m about to describe.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Steps down from soap-box&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now that your offer is accepted you have a 30 day clock.
At the end of those 30 days you will hopefully have a house.
Very cool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inspections&quot;&gt;Inspections&lt;&#x2F;h2&gt;
&lt;p&gt;The first step is to schedule home inspections.
Your realtor should do this.
You will schedule a standard home inspection, but you can also request special inspections if you are concerned.
For example we tested for Radon and buried oil tanks, because both of those are shitty things in Portland.
These inspections are one of the few fees paid by the buyer because you as the buyer can be as picky as you want about the
inspections.&lt;&#x2F;p&gt;
&lt;p&gt;Once the inspections happen you&#x27;ll do a walk-through.
Often this is the &lt;em&gt;second time you have seen the house in person&lt;&#x2F;em&gt;, which I just find hilarious.
The inspector should walk you through the house and tell you literally everything wrong with the house that they can find.
They might also mention any concerns they have based on the listing&#x27;s disclosures and the year the house was built&#x2F;renovated.
The inspector shouldn&#x27;t have any horse in this race, they&#x27;re getting paid weather the deal falls through or not, so they should be pretty matter-of-fact.
This means they might tell you some scary shit like &quot;This ceiling is probably asbestos, don&#x27;t touch it until you get that tested&quot;, this is just because you need to know everything that might be a deal breaker before the next step.&lt;&#x2F;p&gt;
&lt;p&gt;Once the walk-through is complete your inspector will write up an inspection report and send it to you and your realtor for you to review and keep.
This is a very long, very boring, and very important document.
Keep a copy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;negotiations&quot;&gt;Negotiations&lt;&#x2F;h2&gt;
&lt;p&gt;Now that you know everything about the house:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Disclosures given in the house listing.&lt;&#x2F;li&gt;
&lt;li&gt;Inspection results.&lt;&#x2F;li&gt;
&lt;li&gt;You&#x27;ve been inside like... twice.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can enter the negotiation phase fully informed.
Negotiations are not done in a board room -- I wish -- they&#x27;re done asynchronously by the seller and buyer&#x27;s realtors.&lt;&#x2F;p&gt;
&lt;p&gt;You sit down &lt;strong&gt;with your realtor&lt;&#x2F;strong&gt; and go over the inspection results.
If your realtor is good they&#x27;ll basically do the negotiation for you, reviewing what the plan is before locking it in.&lt;&#x2F;p&gt;
&lt;p&gt;For example, our realtor said the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The pipes are clogged with baby wipes or something, that can take 7k to fix so let&#x27;s ask to knock off 7k.&lt;&#x2F;li&gt;
&lt;li&gt;The garage door is busted, let&#x27;s ask to take 5k off for that.&lt;&#x2F;li&gt;
&lt;li&gt;Some other stuff got knocked off but I don&#x27;t remember it a year later.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We figure out how much to ask for by basically looking up how much it would reasonably cost to fix broken shit.
If your roof was caving in you would be able to ask to take a lot, if a stair was busted that would probably be less.&lt;&#x2F;p&gt;
&lt;p&gt;You can&#x27;t get away with asking for price reductions for &lt;em&gt;aesthetic&lt;&#x2F;em&gt; differences, like you wish the house had more outlets, but you could ask to get the price knocked if the electrical was unsafe.&lt;&#x2F;p&gt;
&lt;p&gt;Your realtor should then write this up and send it to the seller&#x27;s realtor who will respond with a counter.
Sometimes they will choose to fix broken things themselves or they may drop the price for a given request.
In our case the owner dropped the price a bit, around 3k, and spent her own money to fix clogged pipes, which cost a few thousand.&lt;&#x2F;p&gt;
&lt;p&gt;In the negotiation the seller has an incentive to keep the final price fairly high while the buyer has an incentive to get the price as low as possible.
This means sellers might find more expensive quotes and the buyer might find cheaper quotes for repair costs.
But both parties have an incentive to complete the sale of the house.&lt;&#x2F;p&gt;
&lt;p&gt;If a seller refuses to negotiate on the price of the house, the buyer at this point has the option to pull out of the deal.
The buyer will most likely get their Earnest Money back because they found something out about the house after the offer was accepted which the buyer refused to fix or decrease the price for.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-what-does-the-bank-think-it-s-worth&quot;&gt;But what does the bank think it&#x27;s worth?&lt;&#x2F;h2&gt;
&lt;p&gt;After negotiating on a price the bank gets involved again.
It takes the bank under a week to, given the home inspection plus their piles of data, determine what they think it&#x27;s worth.
This has very little to do with what you thought it was worth and it is what the bank is willing to cover in the form of a home loan.&lt;&#x2F;p&gt;
&lt;p&gt;If the bank decides the house is worth &lt;em&gt;more&lt;&#x2F;em&gt; than the final offer you&#x27;re golden.
You get a loan for the negotiated price and it&#x27;ll be 100% covered by the bank.&lt;&#x2F;p&gt;
&lt;p&gt;For example: If the final offer is 100k and the bank decides the house is worth 105k, you need to do the normal 20% down payment, and then you get an 80k loan for the rest.&lt;&#x2F;p&gt;
&lt;p&gt;... But if the bank decides the house is worth &lt;em&gt;less&lt;&#x2F;em&gt; than the final offer you&#x27;re some amount of fucked.
You need to pay the difference out of pocket, or pull out of the deal.&lt;&#x2F;p&gt;
&lt;p&gt;For example: If the final offer is 100k but the bank decides the house is worth 60k, you need to cover 20k down payment, plus the 20k difference on the remaining cost.
100k - 20k = 80k ideal loan.
80k - 20k = 60k what the bank will actually loan you.&lt;&#x2F;p&gt;
&lt;p&gt;Note, I&#x27;m using 100k as a round number for math examples.
This is not some cruel joke, it&#x27;s just easier numbers.
Most houses we looked at were between 350k and 600k.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;side-note-why-do-we-need-down-payments&quot;&gt;Side note, why do we need down payments?&lt;&#x2F;h3&gt;
&lt;p&gt;Wait, why do we have down payments?
It&#x27;s complicated, but I &lt;em&gt;think&lt;&#x2F;em&gt; it&#x27;s a collection of reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The more you pay up front, the less monthly payments you have.
20% up front is a good way to reduce your monthly payments from the get-go.&lt;&#x2F;li&gt;
&lt;li&gt;Credit worthiness or some bullshit.
Banks want to make sure you have skin in the game, so before you can get approved for a loan you need to prove you have 20%+ of the cost of the house for them to cover the other 80%.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That&#x27;s my best bet.
Ask a realtor or your local economist or banker or something; they&#x27;ll probably have a better answer.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Once the bank settles on a price you can close on the house.
You&#x27;ll get a real loan for the final price (minus the difference you&#x27;ve paid in cash).
Finally, 30 days (ish) after getting your offer accepted you&#x27;ll walk into a title company, go over a stack of papers with a professional, sign a bunch of those papers, and walk out the proud owner of a house.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-now&quot;&gt;What now?&lt;&#x2F;h2&gt;
&lt;p&gt;We had to wait a few weeks after closing to actually move in.
The previous owner needed the funds from closing to close on her own house, but that ended up going faster than expected so we only had to stay at my parents house (#privilege #safetynet) for two weeks.&lt;&#x2F;p&gt;
&lt;p&gt;Your realtor should give you some keys for the new house.
I suggest throwing those out once you&#x27;re moved in and replace the locks -- even in a nice neighborhood, you have no idea who has the old keys.&lt;&#x2F;p&gt;
&lt;p&gt;Rent a moving van and bribe your friends, or hire some movers if you&#x27;re smart, and enjoy your beautiful house!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Wait, is this pipe supposed to be leaking?
In the next post we&#x27;ll talk about home renovations!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dynamic Dispatch in Python</title>
        <published>2021-09-02T00:00:00+00:00</published>
        <updated>2021-09-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/python-dynamic-dispatch/"/>
        <id>https://elijah.run/blog/python-dynamic-dispatch/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/python-dynamic-dispatch/">&lt;p&gt;🦝 Hey want tO see a nEat PYtHoN triCK?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;hiya &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(name))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;locals&lt;&#x2F;span&gt;&lt;span&gt;()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Spongebob&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;🐮 Oh cool, does that use the string &lt;code&gt;&quot;f&quot;&lt;&#x2F;code&gt; to find--&lt;&#x2F;p&gt;
&lt;p&gt;🦝 DoEs It FiNd ThE fUnCtIoN &lt;code&gt;&quot;f&quot;&lt;&#x2F;code&gt; aNd CaLl iT?? yEaH It DoEs.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ python script.py
&lt;&#x2F;span&gt;&lt;span&gt;hiya Spongebob
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;🐮 Oh that&#x27;s neat. I didn&#x27;t know you could do that with Python--&lt;&#x2F;p&gt;
&lt;p&gt;🦝 whaTEveR i dON&#x27;t cArE wHaT YOU tHinK.&lt;&#x2F;p&gt;
&lt;p&gt;🐮 You asked me --&lt;&#x2F;p&gt;
&lt;p&gt;🦝 I sAiD sHuT uP. i&#x27;M dOiNg HoT gIrL sHiT.&lt;&#x2F;p&gt;
&lt;p&gt;🐮 Are you ok? You&#x27;re yelling a lot about Python again--&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# shut up
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;test_patrick&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;: TestContext):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# do thing
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;test_crabs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;: TestContext):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# do other thing
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;context &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;TestContext&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;tests &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;locals&lt;&#x2F;span&gt;&lt;span&gt;():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;t.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;startswith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;test_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;        tests.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(t)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;test &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;tests:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;(context)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;🐮 Oh so you could...&lt;&#x2F;p&gt;
&lt;p&gt;🦝 ...&lt;&#x2F;p&gt;
&lt;p&gt;🐮 Are you going to interrupt me?&lt;&#x2F;p&gt;
&lt;p&gt;🦝 Not yet.&lt;&#x2F;p&gt;
&lt;p&gt;🐮 Ok... you could search your scope and find a bunch of functions with a name and common interface--&lt;&#x2F;p&gt;
&lt;p&gt;🦝 AND CALL THEM! DYNAMIC DISPATCH!!&lt;&#x2F;p&gt;
&lt;p&gt;🐮 That&#x27;s nice.&lt;&#x2F;p&gt;
&lt;p&gt;🦝 YEAH IT IS COOL!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Buying a House Part 1: Let&#x27;s Go Shopping!</title>
        <published>2021-08-26T00:00:00+00:00</published>
        <updated>2021-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/buying-a-house-01-lets-go-shopping/"/>
        <id>https://elijah.run/blog/buying-a-house-01-lets-go-shopping/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/buying-a-house-01-lets-go-shopping/">&lt;p&gt;So you&#x27;re interested in buying a house eh?
Well boy howdy do I have a series of blog posts for you.
This four part series will equip you, a first-time home buyer, with a bunch of knowledge I wish I had before starting my journey to buying a home.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the road-map:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-01-lets-go-shopping&#x2F;&quot;&gt;Part 1: 🛒 Let&#x27;s Go Shopping!&lt;&#x2F;a&gt; in which we start looking for houses.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-02-show-me-the-money&#x2F;&quot;&gt;Part 2: 💸 Show Me the Money!&lt;&#x2F;a&gt; in which we buy a freaking house.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-03-renovation-station&#x2F;&quot;&gt;Part 3: 👷 Renovation Station.&lt;&#x2F;a&gt; in which we live in the freaking house.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-04-is-this-investing&#x2F;&quot;&gt;Part 4: 📈 Is This Investing?&lt;&#x2F;a&gt; where we figure out if we made a huge financial mistake (or achievement!)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;hey-quick-disclaimer&quot;&gt;Hey, quick disclaimer&lt;&#x2F;h2&gt;
&lt;p&gt;Some things I &lt;strong&gt;can&lt;&#x2F;strong&gt; claim to be an expert on: Docker, Linux, why my dog is making that face, etc.
But with home-buying I am at best a novice, so please take everything you read here with a grain of salt.&lt;&#x2F;p&gt;
&lt;p&gt;I am just one lowly home owner in his mid-20s who bought a house during a pandemic.
I got here through a bunch of privilege, support, luck, and the modest amount amount of hard work &lt;em&gt;required&lt;&#x2F;em&gt; to live a wonderful mortgage-filled life.&lt;&#x2F;p&gt;
&lt;p&gt;I am not a financial advisor, realtor, none of that stuff.
I encourage you to do independent research, check my work, etc.
Don&#x27;t make any decisions based purely on this series.
Please use it as one of many sources in your research before buying a house.&lt;&#x2F;p&gt;
&lt;p&gt;Okay, &lt;strong&gt;now&lt;&#x2F;strong&gt; we can get started.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;so-um-why-do-you-want-to-buy-a-house&quot;&gt;So um, why do you want to buy a house?&lt;&#x2F;h2&gt;
&lt;p&gt;Before diving into the home buying process, let&#x27;s ask an annoyingly
simple (but annoyingly effective) question: &quot;why?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a million reasons to want to buy a house.
A few that come to mind are&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;You want more space or a yard.&lt;&#x2F;li&gt;
&lt;li&gt;You want an investment.&lt;&#x2F;li&gt;
&lt;li&gt;You want to be in a residential neighborhood.&lt;&#x2F;li&gt;
&lt;li&gt;You want to fulfill the American Dream™.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now none of these &lt;em&gt;require&lt;&#x2F;em&gt; you to buy a house.
You could rent a house to get more space, invest in high yield assets to make passive income, etc. but a house tends to check &lt;strong&gt;all&lt;&#x2F;strong&gt; these boxes.&lt;&#x2F;p&gt;
&lt;p&gt;My fiance (now wife) and I we were living in a small apartment before buying a house.
This apartment was perfect pre-COVID.
It was a 10-20 minutes walking commute to work, centrally located, and big enough to sleep, cook meals, and rest while being young 20-somethings living our best lives.&lt;&#x2F;p&gt;
&lt;p&gt;When COVID hit we though we could muddle through in the apartment, but around the 2 month mark we thought:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hmm, this isn&#x27;t gonna be the &quot;Come on Morty.
Just two weeks, we&#x27;ll be in and out.
Just a little pandemic to spice things up.&quot; thing that we thought this would be...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We looked for house rentals, but while there were hundreds of houses for sale there were almost no houses rentals available in the Portland area. I was always resistant to buying a house, but after realizing it was a reasonable financial decision we got started.&lt;&#x2F;p&gt;
&lt;p&gt;This is where our home buying journey begins.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-triage&quot;&gt;Let&#x27;s triage&lt;&#x2F;h2&gt;
&lt;p&gt;Before buying a house, or even visiting a house, you should go to sites like Zillow and Redfin to get a lay of the land.
They both have basically the same home listings, so choose whichever site has a better interface for you.
This goes without saying though; you found this obscure blog post so you&#x27;re probably deeply familiar with all the different home buying sites.
I promise this series will start saying less &quot;yeah duh&quot; stuff in the next section.&lt;&#x2F;p&gt;
&lt;p&gt;We knew roughly what neighborhoods we wanted to live in: East Portland with a bias toward the Tabor neighborhoods. This made it quick to narrow
our search and skip the existential question &quot;where in the world do I want to live?&quot; I&#x27;m sure some people confront.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;money-talk&quot;&gt;Money talk&lt;&#x2F;h2&gt;
&lt;p&gt;Once you have a feel for the housing market in your target locations, check in with your finances.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-big-wad-of-cash&quot;&gt;A big wad of cash&lt;&#x2F;h3&gt;
&lt;p&gt;Buying your soon-to-be house will require a down-payment.
This means you&#x27;ll need a very big pile of money &lt;em&gt;very soon&lt;&#x2F;em&gt;.
Figure out what your liquid assets (savings, non-retirement investment accounts, dubious favors you can call in) talley up to.
This is the max you could use for a down-payment.&lt;&#x2F;p&gt;
&lt;p&gt;Down payments tend to be 20% of the purchase price of the house, and houses are hundreds of thousands of dollars, so... yeah that&#x27;s a lot.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If you have 20k in usable assets, you can afford a down payment on a 100k house.&lt;&#x2F;li&gt;
&lt;li&gt;84k usable assets? 420k house.&lt;&#x2F;li&gt;
&lt;li&gt;13.8k usable assets? 69k house.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nice.&lt;&#x2F;p&gt;
&lt;p&gt;This sets an upper-limit on which houses you can afford.
Hopefully this upper-limit lines up with median home prices in your target neighborhoods.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-smaller-monthly-wad-of-cash&quot;&gt;A smaller monthly wad of cash&lt;&#x2F;h3&gt;
&lt;p&gt;You also need to consider the monthly cost of your potential home.
Ideally you only spend up to 30% of your monthly income on living expenses.
This means your house (with utilities) costs no more than 30% of what you take home.
Some of you may be laughing at this because it is in fact an outdated metric that has not kept up with inflating home prices.
Don&#x27;t worry, we&#x27;ll cover how terrible home prices are in a later installment.&lt;&#x2F;p&gt;
&lt;p&gt;The 30% rule says:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If you take home 2k&#x2F;month (roughly a 30k&#x2F;year salary after taxes) your
housing should cost no more than 600&#x2F;month.&lt;&#x2F;li&gt;
&lt;li&gt;5833&#x2F;month (100k salary) take-home? 1750 housing expenses.&lt;&#x2F;li&gt;
&lt;li&gt;11452&#x2F;month (200k salary) take-home? 3435 housing expenses.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But what does that translate to for home prices?
You don&#x27;t pay for the whole house up front (the bank does that).
Instead you pay for it in monthly installments with interest -- which is hard for me to intuit.
Skipping some prelude:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If your house is 100k, you put up a 20k down payment, and you acquire a 30 year loan with 4% interest, your monthly payment will be ~587.&lt;&#x2F;li&gt;
&lt;li&gt;200k house, 40k down, 4% interest 30yr loan? ~1070.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With these numbers, as the price of the house goes up the monthly payments go up sub-linearly.
This means so a 400k house is a little less than 2000&#x2F;month, ec.&lt;&#x2F;p&gt;
&lt;p&gt;I have no idea how to calculate these numbers by hand, I always use a calculator... &lt;a href=&quot;https:&#x2F;&#x2F;www.zillow.com&#x2F;mortgage-calculator&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.zillow.com&#x2F;mortgage-calculator&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Once you have established you can afford both the down-payment and monthly payments now we can start shopping!&lt;&#x2F;p&gt;
&lt;p&gt;If prices in your target neighborhood are out of reach, explore other candidates; neighborhoods near your targets, or even the &#x27;burbs.
Also if you just like shopping for homes for the kick of it, because shopping is fun, power to you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;get-yourself-a-realtor&quot;&gt;Get yourself a realtor&lt;&#x2F;h2&gt;
&lt;p&gt;A realtor is like a lawyer.
You never &lt;em&gt;want&lt;&#x2F;em&gt; one, but they are incredible necessary for some of life&#x27;s biggest shit.&lt;&#x2F;p&gt;
&lt;p&gt;We were #blessed to have a family friend that was an active realtor; her name is Mary.&lt;&#x2F;p&gt;
&lt;p&gt;The relationship we had with our realtor was like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Every week around Tuesday we would send her a list of houses we wanted to see.
Between 5-10 houses every week.&lt;&#x2F;li&gt;
&lt;li&gt;Occasionally she would also find a house she thought we would be interested in.&lt;&#x2F;li&gt;
&lt;li&gt;The first week she picked about half the houses to get a feel for what we were interested in, and we brought some we found on our own.&lt;&#x2F;li&gt;
&lt;li&gt;She would drive us around to these houses, because we refuse to buy a car and she is &lt;em&gt;very&lt;&#x2F;em&gt; nice.&lt;&#x2F;li&gt;
&lt;li&gt;Mary would schedule a time for us to visit the house, around 30 minutes per house, during this time we were the only ones in the homes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;As a card-carrying realtor Mary had special privileges not given to us normies, and information not found on public sites.
For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Mary had a list of things disclosed about the house like &quot;It&#x27;s very full of asbestos&quot; or &quot;It&#x27;s full of radon&quot; or &quot;The roof caved in last year, just fixed&quot;.
Info you would want to know before putting an offer on a house.&lt;&#x2F;li&gt;
&lt;li&gt;She also had access to some cloak-and-dagger shit that let her into all of the houses on the market.
Ever seen a lock-box on a for-sale house?
She could open that lock-box and get the key out with an app on her phone.&lt;&#x2F;li&gt;
&lt;li&gt;She also knew how to fill out the copious forms needed to put an offer on a house, but we&#x27;ll get to that in the next post.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;so-many-houses&quot;&gt;So. Many. Houses.&lt;&#x2F;h2&gt;
&lt;p&gt;In total we were house shopping for about 5 weeks.
We averaged visiting 10 houses per week, doing 1 to 2 trips per week and visiting 6 houses per trip.&lt;&#x2F;p&gt;
&lt;p&gt;We saw a lot of houses.
Some great houses in safe boring neighborhoods far from where we wanted to live.
Some terrible houses that people kept calling &quot;fixer-uppers&quot; like they were in the pocket of big shitty house.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of houses that were great except for like... one really important thing.
Some houses had a great location but were too small.
Or the house was the perfect size but too far from our target location.
Or the price and size were good but the neighbors were burning a literal pile of trash and they were like... very good at it, implying this wasn&#x27;t a one-off thing.&lt;&#x2F;p&gt;
&lt;p&gt;My point is, there were a lot of houses.
A lot that were good, many more that were non-starters.&lt;&#x2F;p&gt;
&lt;p&gt;The first week or two was basically a mulligan.
So many houses are so bad you start to think &lt;em&gt;all&lt;&#x2F;em&gt; houses are bad and you trick yourself into settling.
DO NOT SETTLE.
This is a huge freaking purchase, grind it out and you will find a house you like.
It might be at the upper end of your budget, or it might be a &lt;em&gt;little bit of a fixer upper&lt;&#x2F;em&gt;, but you&#x27;ll know the perfect house when you find it.
And you will &lt;em&gt;definitely&lt;&#x2F;em&gt; know when it&#x27;s &lt;em&gt;not&lt;&#x2F;em&gt; the right house.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-on-your-knees-and-asking-the-bank-for-a-pre-approval&quot;&gt;Getting on your knees and asking the bank for a pre-approval&lt;&#x2F;h2&gt;
&lt;p&gt;At this point in the story we haven&#x27;t bought any houses yet, but before you are allowed to &lt;em&gt;think&lt;&#x2F;em&gt; about buying a house you need to get a bank to say &quot;Yeah they&#x27;re good for it&quot;.
This requires asking a bank pretty please, giving them like 3 years of financial, employment, and credit records.
If you&#x27;re buying this with a partner they need to do the same thing.&lt;&#x2F;p&gt;
&lt;p&gt;In our case we tried to get a super cheap loan but we were told our offer might get rejected if we didn&#x27;t have a &quot;local loan&quot; meaning a loan provided by a local Oregon company -- what year is it 1980?
In the end all of our loan options were super cheap, even the local ones, so we shrugged and told ourselves the cheapest loan probably had a bunch of closing fees that would basically cancel out the higher mortgage rate.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;em&gt;fun fact&lt;&#x2F;em&gt; about the loan process is that you get pre-approved for a loan up to some amount, which is used to put an offer on a house
Once the offer is accepted you get the &lt;em&gt;real&lt;&#x2F;em&gt; loan for whatever the final loan amount ends up being.
But we&#x27;re getting ahead of ourselves.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-offer-process&quot;&gt;The offer process&lt;&#x2F;h2&gt;
&lt;p&gt;At some point you&#x27;ll make an offer on a house.
This might &lt;em&gt;sound&lt;&#x2F;em&gt; like we&#x27;re buying a house, but trust me there are a lot more offers on houses than there are sales on houses.&lt;&#x2F;p&gt;
&lt;p&gt;When you put in an offer on a house you basically roll for initiative and if you get a Nat-20 it gets accepted.
You should still treat every offer as if it were to be accepted, because you can roll a Nat-20 on a persuasion check with a rat just as often as slaying a dragon.
Offers are accepted and rejected basically at random, but each one is important and should be treated as &quot;the one&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;When putting an offer on a house you fill out a bunch of complicated legal-ese forms with your realtor.
Taking your pre-approval you decide on an offer up to your pre-approval limit.
In Portland right now we need to offer &lt;em&gt;way more&lt;&#x2F;em&gt; than the asking price which is bullshit and I hate
it.&lt;&#x2F;p&gt;
&lt;p&gt;You also fill out a bunch of details like when you want the sale to be complete (30 days), weather you&#x27;re planning on doing inspections (yes), and how much money you can put up &lt;em&gt;before your down payment&lt;&#x2F;em&gt;.
That pre-down-payment is called Earnest Money and it&#x27;s often between 2k and 10k, it counts toward your down payment, and it can be refunded if the deal falls through.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-s-a-marathon-pace-yourself&quot;&gt;It&#x27;s a marathon, pace yourself&lt;&#x2F;h2&gt;
&lt;p&gt;Lucy went into this expecting that buying a house was like buying anything else.
You find what you like, offer a fair (or listed) price, and boom you get it.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately housing is not like buying a phone, or basically anything else most people spend money on.
In Portland at least supply does not match demand, so prices are not only higher than they ought to be, but the prices are also &lt;em&gt;full of lies&lt;&#x2F;em&gt;.
The asking price is often 10% below the final price -- if you&#x27;re lucky!
Plus your offer on a house may be rejected for mysterious reasons.
More than once we were asked to re-submit an offer and to give our &quot;highest and best&quot; offer whatever the fuck that means.&lt;&#x2F;p&gt;
&lt;p&gt;Be prepared to visit at &lt;strong&gt;dozens&lt;&#x2F;strong&gt; of houses.
Be prepared to make an offer on multiple houses.
You will have your heart broken when you find the perfect house, just to have it swiped out of your hands by a bank, somebody paying all in cash, somebody waiving inspections, or just some jerk that got an offer in half an hour before you did -- that bastard.&lt;&#x2F;p&gt;
&lt;p&gt;Take your time.
This is a big purchase.
It will pay off.
It will get better.
Your patience will be rewarded.&lt;&#x2F;p&gt;
&lt;p&gt;Good luck.
See you in the &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;buying-a-house-02-show-me-the-money&#x2F;&quot;&gt;part 2&lt;&#x2F;a&gt; where we get to buy a freaking house!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Nuggit: Manually change your default branch name</title>
        <published>2021-07-07T00:00:00+00:00</published>
        <updated>2021-07-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/git-main-branch/"/>
        <id>https://elijah.run/blog/git-main-branch/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/git-main-branch/">&lt;p&gt;So I was on my laptop running an ancient release of Linux called Fedora 30 -- so old COVID wasn&#x27;t even a twinkle in a bat&#x27;s eye when it was released.&lt;&#x2F;p&gt;
&lt;p&gt;On this ancient OS I&#x27;m have &lt;code&gt;git 2.21.3&lt;&#x2F;code&gt; which is like 13 versions behind.
I ask yum -- err &lt;em&gt;dnf&lt;&#x2F;em&gt; -- if there is an upgrade and it&#x27;s like &quot;nope&quot;.
Nothing makes me feel older than software.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve gotten into the habit of naming my default branches &lt;code&gt;main&lt;&#x2F;code&gt; instead of &lt;code&gt;master&lt;&#x2F;code&gt; because every time I say &quot;master&quot; I need to take a shower.
I&#x27;m pretty sure the latest git names the default branch &lt;code&gt;main&lt;&#x2F;code&gt; out of the box, but git from April 2019 was not aware of problematic language choices.&lt;&#x2F;p&gt;
&lt;p&gt;So as one does I&#x27;m starting a new repo and I decide before updating &lt;code&gt;git&lt;&#x2F;code&gt;, which is gonna require like 3 Fedora upgrades, I&#x27;m just going to rename the branch.
I know I&#x27;ll get woke-git if I upgrade Fedora, but I want to write this post first so we&#x27;re gonna find a workaround.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;[branch:master]$ git branch -m main
&lt;&#x2F;span&gt;&lt;span&gt;error: refname refs&#x2F;heads&#x2F;master not found
&lt;&#x2F;span&gt;&lt;span&gt;fatal: Branch rename failed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hmm.
So on a bare repo you can&#x27;t rename the starting branch because there&#x27;s no objects in the repo... or something like that &lt;em&gt;waves hands&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Umm... I guess we&#x27;ll go spelunking into the &lt;code&gt;.git&lt;&#x2F;code&gt; directory to see if we can manually force our &lt;code&gt;main&lt;&#x2F;code&gt; branch naming.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;[branch:master]$ cd .git
&lt;&#x2F;span&gt;&lt;span&gt;[.git]$ tree -F
&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;├── branches&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── config
&lt;&#x2F;span&gt;&lt;span&gt;├── description
&lt;&#x2F;span&gt;&lt;span&gt;├── HEAD
&lt;&#x2F;span&gt;&lt;span&gt;├── hooks&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── A bunch of sample scripts
&lt;&#x2F;span&gt;&lt;span&gt;├── info&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   └── exclude
&lt;&#x2F;span&gt;&lt;span&gt;├── objects&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── info&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   └── pack&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;└── refs&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    ├── heads&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    └── tags&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well unsurprisingly we have a bunch of empty directories and some sample scripts.&lt;&#x2F;p&gt;
&lt;p&gt;The only files that &lt;em&gt;might&lt;&#x2F;em&gt; be worth looking at are &lt;code&gt;config&lt;&#x2F;code&gt;, &lt;code&gt;description&lt;&#x2F;code&gt;, and &lt;code&gt;HEAD&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&#x2F;&#x2F; config
&lt;&#x2F;span&gt;&lt;span&gt;[core]
&lt;&#x2F;span&gt;&lt;span&gt;    repositoryformatversion = 0
&lt;&#x2F;span&gt;&lt;span&gt;    filemode = true
&lt;&#x2F;span&gt;&lt;span&gt;    bare = false
&lt;&#x2F;span&gt;&lt;span&gt;    logallrefupdates = true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems to be config options for this repo, none of which mention branch naming so it&#x27;s a skip for me.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&#x2F;&#x2F; description
&lt;&#x2F;span&gt;&lt;span&gt;Unnamed repository; edit this file &amp;#39;description&amp;#39; to name the repository.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I had no idea this feature existed.
I have never seen it be used -- but fun facts!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&#x2F;&#x2F; HEAD
&lt;&#x2F;span&gt;&lt;span&gt;ref: refs&#x2F;heads&#x2F;master
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the money shot. Let&#x27;s change that bad boy to &lt;code&gt;refs&#x2F;heads&#x2F;main&lt;&#x2F;code&gt; and see if my magical git prompt picks it up:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;[.git]$ cd ..&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;[branch:main]$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Heyo!
There you have it. How to manually change the name of your main branch in a fresh git repo.&lt;&#x2F;p&gt;
&lt;p&gt;Sanity check, this won&#x27;t fuck up if we commit right?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ cargo init .
&lt;&#x2F;span&gt;&lt;span&gt;$ git add . &amp;amp;&amp;amp; git commit -m &amp;quot;initial commit&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;[main (root-commit) ebecbee] initial commit
&lt;&#x2F;span&gt;&lt;span&gt; 3 files changed, 12 insertions(+)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 .gitignore
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 Cargo.toml
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;main.rs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;note&quot;&gt;Note...&lt;&#x2F;h2&gt;
&lt;p&gt;After anxiously upgrading to Fedora 34 I confirmed that git fixed a lot of this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;[pop@lappy foo]$ git init
&lt;&#x2F;span&gt;&lt;span&gt;hint: Using &amp;#39;master&amp;#39; as the name for the initial branch. This default branch name
&lt;&#x2F;span&gt;&lt;span&gt;hint: is subject to change. To configure the initial branch name to use in all
&lt;&#x2F;span&gt;&lt;span&gt;hint: of your new repositories, which will suppress this warning, call:
&lt;&#x2F;span&gt;&lt;span&gt;hint:
&lt;&#x2F;span&gt;&lt;span&gt;hint:   git config --global init.defaultBranch &amp;lt;name&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;hint:
&lt;&#x2F;span&gt;&lt;span&gt;hint: Names commonly chosen instead of &amp;#39;master&amp;#39; are &amp;#39;main&amp;#39;, &amp;#39;trunk&amp;#39; and
&lt;&#x2F;span&gt;&lt;span&gt;hint: &amp;#39;development&amp;#39;. The just-created branch can be renamed via this command:
&lt;&#x2F;span&gt;&lt;span&gt;hint:
&lt;&#x2F;span&gt;&lt;span&gt;hint:   git branch -m &amp;lt;name&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And yes, &lt;code&gt;git branch -m &amp;lt;name&amp;gt;&lt;&#x2F;code&gt; does work on an empty repo.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Circular Imports</title>
        <published>2021-01-31T00:00:00+00:00</published>
        <updated>2021-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/circular-imports/"/>
        <id>https://elijah.run/blog/circular-imports/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/circular-imports/">&lt;p&gt;Don&#x27;t you hate when you&#x27;re writing a python program and you get hit with one of these?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;a.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    from b import g
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;pop&#x2F;Projects&#x2F;src&#x2F;localhost&#x2F;circular&#x2F;b.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    from a import f
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;pop&#x2F;Projects&#x2F;src&#x2F;localhost&#x2F;circular&#x2F;a.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    from b import g
&lt;&#x2F;span&gt;&lt;span&gt;ImportError: cannot import name &amp;#39;g&amp;#39; from partially initialized module &amp;#39;b&amp;#39; (most likely due to a circular import) (&#x2F;home&#x2F;pop&#x2F;Projects&#x2F;src&#x2F;localhost&#x2F;circular&#x2F;b.py)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What a drag.&lt;&#x2F;p&gt;
&lt;p&gt;Circular imports are of course the literal devel in programming, but in a Godel Escher Bach sort of way they are all around us.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;welcome-to-my-ted-talk&quot;&gt;welcome to my ted talk&lt;&#x2F;h2&gt;
&lt;p&gt;There are a lot of problems in the world that everybody agrees are problems&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but we can sometimes disagree about what the solution is.&lt;&#x2F;p&gt;
&lt;p&gt;Many of these problems stem can be thought of as emergent properties of other phenomena.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example, plastic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuck-plastic&quot;&gt;fuck plastic&lt;&#x2F;h2&gt;
&lt;p&gt;Remember the good old days in America when women tended to the house while PTSD ridden white men worked a 40 minute drive away and the ethnically, racially, sexually, abally discriminated minorities were repressed?&lt;&#x2F;p&gt;
&lt;p&gt;Well something that actually was pretty sweet was milk delivery.&lt;&#x2F;p&gt;
&lt;p&gt;Milk, delivered regularly in reusable glass bottles had incredibly ecological benefits compared with how we get milk&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; today.&lt;&#x2F;p&gt;
&lt;p&gt;Deliveries are an incredibly efficient means of distriuting goods&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and re-using glass bottles requires far less energy than say, melting a bottle down or worse creating a plastic single-use bottle.&lt;&#x2F;p&gt;
&lt;p&gt;I really want to focus on the glass bottles because they are &lt;em&gt;so&lt;&#x2F;em&gt; efficient, why did we ever stop?&lt;&#x2F;p&gt;
&lt;p&gt;Lobbying.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-plastics-import-lobbying&quot;&gt;from plastics import lobbying&lt;&#x2F;h2&gt;
&lt;p&gt;That&#x27;s right: lobbying, not the free market, gave us the fucking horrific amount of single-use plastic we have today.&lt;&#x2F;p&gt;
&lt;p&gt;For sure there are a million things we need to cut the fuck out if we want this planet to be anything close to what we were born into in 100 years, but plastics are worth spending a few hundred words.&lt;&#x2F;p&gt;
&lt;p&gt;The plastics industry spent millions&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; lobbying to allow the use of single use plastics instead of reusable containers.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of identifying the inevitable crisis of too much fucking plastic and shutting that shit down, governments across the world wer just like &quot;yeah this is cool, pour up my dude&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Congress, given no external input, very well could have legislated against the use of single-use plastics, but because they were convinced... with money... otherwise here we are in a world full of single use plastics, and just like a virus it&#x27;s spread so far that it feels impossible to slow it&#x27;s spread.&lt;&#x2F;p&gt;
&lt;p&gt;So clearly we need to stop lobbying.
We need to think of some clever way to prevent corruptable government officials from being bought off to vote against the interests of their constituents, their country, and future generations...&lt;&#x2F;p&gt;
&lt;p&gt;Well that&#x27;s clearly impossible.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s dig deeper.
What causes lobbying?&lt;&#x2F;p&gt;
&lt;p&gt;Profit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-lobbying-import-profit&quot;&gt;from lobbying import profit&lt;&#x2F;h2&gt;
&lt;p&gt;It is clear that profit is the reason lobbying exists.&lt;&#x2F;p&gt;
&lt;p&gt;Some lobbying is good. If you own a farm and you hear about legislation that will like... just straight up dump a bunch of nuclear waste on your property, you&#x27;re probably going to knock on some doors and grease some palms to prevent that from happening.&lt;&#x2F;p&gt;
&lt;p&gt;Arithmetically it makes sense that lobbying is tied to profit.
If a piece of legislation is projected to decrease profits by 30 million USD, you&#x27;re probably willing to spend 2 million USD to prevent it from going through.&lt;&#x2F;p&gt;
&lt;p&gt;Lobbying, like swordfishing&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, is a targeted, and therefore monetarily effective, way to influence change.&lt;&#x2F;p&gt;
&lt;p&gt;Maximizing profit has a lot of other problems&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; like supressing wages despite productivity going up, and cock-blocking public alternatives to private services like healthcare... Where was I?&lt;&#x2F;p&gt;
&lt;p&gt;Oh right, so this begs the question, where does profit come from?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-profit-import&quot;&gt;from profit import ???&lt;&#x2F;h2&gt;
&lt;h2 id=&quot;soapbox-intensifies&quot;&gt;soapbox intensifies&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;All &lt;em&gt;good faith actors&lt;&#x2F;em&gt; actors agree are a problem.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Yes, also mylks.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Citation needed?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;... &lt;em&gt;sigh&lt;&#x2F;em&gt; citation needed.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;The internet phishing scam not the oceanic activity.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;... citation... needed...?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Let&#x27;s Build a Game with Rust</title>
        <published>2020-11-13T00:00:00+00:00</published>
        <updated>2020-11-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/seagl-2020-lets-build-a-game-with-rust/"/>
        <id>https://elijah.run/blog/seagl-2020-lets-build-a-game-with-rust/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/seagl-2020-lets-build-a-game-with-rust/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is the outline for a talk I gave at the Seattle GNU Linux
conference (SeaGL) 2020. Once the video is posted I will link it here.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;The code for this post can be found at https:&#x2F;&#x2F;github.com&#x2F;pop&#x2F;lets-make-games-with-rust.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Like many of you, I really like games.
I enjoy playing games, talking about games, and a few times I&#x27;ve even tried making games.
I enjoy making games for a few reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Games are an interesting technical challenge.&lt;&#x2F;li&gt;
&lt;li&gt;They are a flexible artistic outlet.&lt;&#x2F;li&gt;
&lt;li&gt;I don&#x27;t make games in my day-job (yay hobbies).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;m also interested in this programming language called Rust!
You might have heard of it.
Rust is a maturing systems programming language which aims to be performant, reliable, and productive.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Performant in that it often goes head to head with C and C++ in benchmarks.&lt;&#x2F;li&gt;
&lt;li&gt;Reliable in that it refuses to compile memory unsafe code.&lt;&#x2F;li&gt;
&lt;li&gt;Productive because it includes &quot;zero cost abstractions&quot; (link &lt;code&gt;filter&lt;&#x2F;code&gt; and &lt;code&gt;map&lt;&#x2F;code&gt;) and awesome tooling.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The community is pretty good too!&lt;&#x2F;p&gt;
&lt;p&gt;This post is about bringing those two interests together.
Let&#x27;s learn how to build a videogame with the Rust programming language.&lt;&#x2F;p&gt;
&lt;div class=&quot;warning&quot;&gt;
    &lt;span class=&quot;warning-title&quot;&gt;
        Warning
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;warning-body&quot;&gt;
        &lt;p&gt;This post is for folks who have a passing familiarity with Rust.
If Rust is new to you, you get a little confused.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;re a smart cookie though, I&#x27;m sure you&#x27;ll keep up.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;making-games-entities-components-systems-gear&quot;&gt;Making Games: Entities, Components, Systems ⚙️&lt;&#x2F;h2&gt;
&lt;p&gt;Games are an incredibly fun and flexible type of project to work on.&lt;&#x2F;p&gt;
&lt;p&gt;At it&#x27;s core, all games need a &quot;game loop&quot;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Process input&lt;&#x2F;li&gt;
&lt;li&gt;Transforms state&lt;&#x2F;li&gt;
&lt;li&gt;Display new state&lt;&#x2F;li&gt;
&lt;li&gt;Repeat&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Outside of that, the possibilities are endless.
But while the &lt;em&gt;possibilities&lt;&#x2F;em&gt; are endless, there are a few &lt;em&gt;patterns&lt;&#x2F;em&gt; that lots of folks seem to gravitate toward.&lt;&#x2F;p&gt;
&lt;p&gt;You could write a whole book on game programming patterns (and somebody has, links at the bottom).
Today we&#x27;re going to talk about one popular pattern: &lt;strong&gt;ECS: Entity Component System&lt;&#x2F;strong&gt;.
Here&#x27;s what that looks like:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;components&quot;&gt;Components&lt;&#x2F;h3&gt;
&lt;p&gt;Pieces of data mixed, matched, and queried on.&lt;&#x2F;p&gt;
&lt;p&gt;Example: Some components needed to simulate physics might be &quot;Mass&quot;, &quot;Movable&quot;, and &quot;Friction&quot;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;entities&quot;&gt;Entities&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A Unique ID associated with a collection of Components.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Example: Potted plant you can break have the following components:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Sprite(&quot;&#x2F;path&#x2F;to&#x2F;plant.png&quot;)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Mass(6.8)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Movable(True)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Location((2, 5, 2))&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each of these components are reusable. Instead of creating a &quot;PottedPlant&quot; class in code, we can define each entity in a config file like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;potted-plant.txt:
&lt;&#x2F;span&gt;&lt;span&gt;Sprite &#x2F;path&#x2F;to&#x2F;plant.png
&lt;&#x2F;span&gt;&lt;span&gt;Mass 6.8
&lt;&#x2F;span&gt;&lt;span&gt;Movable True
&lt;&#x2F;span&gt;&lt;span&gt;Location 2 5 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This makes our engine much more reusable and separates our content from our logic.&lt;&#x2F;p&gt;
&lt;p&gt;But how do we use these components?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;systems&quot;&gt;Systems&lt;&#x2F;h3&gt;
&lt;p&gt;Functions that operate on entities with specific components.&lt;&#x2F;p&gt;
&lt;p&gt;A System queries for all entities with a specific subset of components and does some transformation on it.&lt;&#x2F;p&gt;
&lt;p&gt;Example: a system that applies fire damage to an entity might look like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;entities_on_fire = entities.query(on_fire=True, health &amp;gt; 0)
&lt;&#x2F;span&gt;&lt;span&gt;for entity in entities_on_fire:
&lt;&#x2F;span&gt;&lt;span&gt;    entity.health -= 5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is nice compared with a classes-based approach where we would need to manage inheritance to manually make sure everything interacted
correctly.
Here we define systems based on what features an entity has.
The resulting systems and components interact with eachother in interesting and potentially unexpected ways.&lt;&#x2F;p&gt;
&lt;p&gt;ECS is a popular pattern for creating interactive games and simulations.
Engines like Unity have some ECS patterns built in, and almost every big game engine uses ECS in some way.&lt;&#x2F;p&gt;
&lt;p&gt;Of course ECS isn&#x27;t a silver bullet, but for this blog post it&#x27;s good enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tools-of-the-trade-c-and-c-hammer-pick&quot;&gt;Tools of the Trade: C and C++ ⚒️&lt;&#x2F;h2&gt;
&lt;p&gt;C and C++ are very popular languages in games programming.
They are defacto in the industry and many large engines, both internal and licensed engines, are written in C++.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not here to bash on C and C++, but it can be useful to point out why you would bother using Rust if the norm is C++.&lt;&#x2F;p&gt;
&lt;p&gt;The usual arguments in favor of Rust go a little something like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust is memory safe; in Rust it is very difficult to reference freed memory, mutate memory in two threads, and dereference a null pointer.&lt;&#x2F;li&gt;
&lt;li&gt;Rust is expressive; a lot of functional-programming language features exist in Rust without the usual run-time cost of those languages.&lt;&#x2F;li&gt;
&lt;li&gt;Rust doesn&#x27;t have any of the C&#x2F;C++ legacy baggage but &lt;em&gt;can&lt;&#x2F;em&gt; inter-operate with C&#x2F;C++ codebases.&lt;&#x2F;li&gt;
&lt;li&gt;Rust has a kick-ass community and an ecosystem of battle-tested and safe code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So why does this all matter for games? I think of it it like this: Any project when it gets sufficiently complex benefits from Rust.
Rust, by preventing a whole class of memory bugs, makes it easier to maintain a complex codebase over time.
It might not be life or death, or as mission critical as security software, but completely avoiding null-pointer bugs, at essentially no performance cost, sounds like a huge weight off my shoulders.&lt;&#x2F;p&gt;
&lt;p&gt;Games are by their nature huge and sprawling codebases.
Many bugs in games are caught by a compiler, but even more errors would be caught by the Rust borrow-checker.
And being able to use some of the nice functional-programming features would be nice too.&lt;&#x2F;p&gt;
&lt;p&gt;Of course Rust is a relatively new language so your mileage may vary.
If I ran a big game studio I don&#x27;t think I would throw out my C++ code and start fresh with Rust, but I would definitely put some research and development into it for new projects (said the Rust fanboy).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rusty-games-hello-amethyst-gem&quot;&gt;Rusty Games: Hello Amethyst 💎&lt;&#x2F;h2&gt;
&lt;p&gt;Writing games in a safe, expressive, not C&#x2F;C++ language sounds great; where do I start?&lt;&#x2F;p&gt;
&lt;p&gt;You could write a game from scratch, but there are engines written in Rust you can use today!
Some of these focus on ease of use, some are for 2D games, some focus on compiling for the web.
Most of these engines require you to write Rust, as opposed to using a GUI, but even that is changing.&lt;&#x2F;p&gt;
&lt;p&gt;For a comprehensive list check out &lt;a href=&quot;https:&#x2F;&#x2F;www.arewegameyet.rs&quot;&gt;https:&#x2F;&#x2F;www.arewegameyet.rs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You could write this talk for almost any Rust Game Engine, but my personal favorite is Amethyst, so we&#x27;ll use that.
Amethyst has a solid API, very active community, and is a good mix of flexible, convenient, and powerful.&lt;&#x2F;p&gt;
&lt;p&gt;Amethyst checks off a few other boxes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Implements an ECS runtime. Register Components, create Entities, and run Systems in Amethyst.&lt;&#x2F;li&gt;
&lt;li&gt;Data driven design. Almost all data in Amethyst can be read in from a Config file.&lt;&#x2F;li&gt;
&lt;li&gt;Apache + MIT licensed. Free as in speech is always nice.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;step-0-join-the-cargo-cult&quot;&gt;Step 0: Join the Cargo Cult&lt;&#x2F;h3&gt;
&lt;p&gt;In this step we&#x27;re going to get Rust setup and create a &quot;hello world&quot; Rust project.&lt;&#x2F;p&gt;
&lt;p&gt;If you haven&#x27;t already, setup your Rust toolchain and start a Rust project.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;rustup&lt;&#x2F;code&gt;, the Rust toolchain manager.&lt;&#x2F;li&gt;
&lt;li&gt;Run &lt;code&gt;rustup toolchain install stable&lt;&#x2F;code&gt; to install the latest stable Rust.&lt;&#x2F;li&gt;
&lt;li&gt;Run &lt;code&gt;cargo new seagl-game&lt;&#x2F;code&gt; to create a &quot;hello world&quot; Rust application.&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to the new &lt;code&gt;seagl-game&lt;&#x2F;code&gt; folder.
Add this to the end of our project&#x27;s metadata file, &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# Cargo.toml
&lt;&#x2F;span&gt;&lt;span&gt;[dependencies.amethyst]
&lt;&#x2F;span&gt;&lt;span&gt;version = &amp;quot;0.15.1&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;features = [&amp;quot;vulkan&amp;quot;]  # &amp;quot;metal&amp;quot; on MacOS
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Run &lt;code&gt;cargo build&lt;&#x2F;code&gt; to build and cache our dependencies.
You should see a &lt;strong&gt;bunch&lt;&#x2F;strong&gt; of output like this:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo build
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;Compiling either v1.6.1
&lt;&#x2F;span&gt;&lt;span&gt;Compiling gimli v0.23.0
&lt;&#x2F;span&gt;&lt;span&gt;Compiling adler v0.2.3
&lt;&#x2F;span&gt;&lt;span&gt;Compiling object v0.22.0
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we have a &quot;hello world&quot; Rust project we can start building on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;step-1-draw-a-window-triangular-ruler&quot;&gt;Step 1: Draw a Window 📐&lt;&#x2F;h3&gt;
&lt;p&gt;Before we run, we need to walk.
And before we walk we crawl.
And before we crawl we draw a window.
This is, of course, a little harder than just asking your computer &quot;Please draw me a window&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;First we need to add a bunch of imports to our project:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;amethyst::{
&lt;&#x2F;span&gt;&lt;span&gt;    assets::{AssetStorage, Loader},
&lt;&#x2F;span&gt;&lt;span&gt;    core::{
&lt;&#x2F;span&gt;&lt;span&gt;        timing::Time,
&lt;&#x2F;span&gt;&lt;span&gt;        transform::{Transform, TransformBundle},
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    derive::SystemDesc,
&lt;&#x2F;span&gt;&lt;span&gt;    ecs::{
&lt;&#x2F;span&gt;&lt;span&gt;        Component, DenseVecStorage, Entities, Join, Read, ReadStorage, System, SystemData,
&lt;&#x2F;span&gt;&lt;span&gt;        WriteStorage,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    input::{InputBundle, InputHandler, StringBindings},
&lt;&#x2F;span&gt;&lt;span&gt;    prelude::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    renderer::{
&lt;&#x2F;span&gt;&lt;span&gt;        plugins::{RenderFlat2D, RenderToWindow},
&lt;&#x2F;span&gt;&lt;span&gt;        types::DefaultBackend,
&lt;&#x2F;span&gt;&lt;span&gt;        Camera, ImageFormat, RenderingBundle, SpriteRender, SpriteSheet, SpriteSheetFormat,
&lt;&#x2F;span&gt;&lt;span&gt;        Texture,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    utils::application_root_dir,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is every dependency we will need for the entire project, so if &lt;code&gt;cargo build|run&lt;&#x2F;code&gt; complains about unused dependencies, don&#x27;t worry... we&#x27;ll get there.&lt;&#x2F;p&gt;
&lt;p&gt;Here we are including a few useful&lt;&#x2F;p&gt;
&lt;p&gt;Then we need to add some boiler-plate to our &lt;code&gt;main&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; This is necessary to make Rust&amp;#39;s type-checker happy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Our main function technically returns an Amethyst Result
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; It can either return an Amethyst error or a unit value
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; amethyst::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Not required, but a logger very useful
&lt;&#x2F;span&gt;&lt;span&gt;    amethyst::start_logger(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span&gt;::default());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Declare some useful variables used to tell Amethyst where our asset files and config files live
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; app_root &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;application_root_dir&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; assets_dir &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; app_root.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;assets&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; display_config_path &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; app_root.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;display.ron&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Declare a renderer bundle
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Amethyst adds this collection of 2D Render systems to our game&amp;#39;s runtime
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; renderer &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;RenderingBundle::&amp;lt;DefaultBackend&amp;gt;::new()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_plugin&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;            RenderToWindow::from_config_path(display_config_path)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;?
&lt;&#x2F;span&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_clear&lt;&#x2F;span&gt;&lt;span&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1.00&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.33&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.00&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span&gt;]),
&lt;&#x2F;span&gt;&lt;span&gt;        ).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_plugin&lt;&#x2F;span&gt;&lt;span&gt;(RenderFlat2D::default());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Build the game&amp;#39;s systems
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; game_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;GameDataBuilder::default()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with_bundle&lt;&#x2F;span&gt;&lt;span&gt;(renderer)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Build our application, which includes our game data, where our assets live, and our starting state
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; game &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Application::new(assets_dir, SeaglState, game_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Run the game!
&lt;&#x2F;span&gt;&lt;span&gt;    game.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Nothing bad happened, so return `()`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That won&#x27;t compile because we haven&#x27;t defined our &lt;code&gt;SeaglState&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;error[E0425]: cannot find value `SeaglState` in this scope
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:17:49
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;30 |     let mut game = Application::new(assets_dir, SeaglState, game_data)?;
&lt;&#x2F;span&gt;&lt;span&gt;   |                                                 ^^^^^^^^^^ not found in this scope
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s add &lt;code&gt;SeaglState&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; States can store values, but for now we can use a unit-struct
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;SeaglState;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; We get a working state for free by rubber-stamping the &amp;quot;SimpleState&amp;quot; struct onto our SeaglState
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; We will implement our own logic for handling state start-up in the next step
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;SimpleState &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;SeaglState { }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will add some methods to &lt;code&gt;SeaglState&lt;&#x2F;code&gt; later, but for now this makes Rust and Amethyst happy enough to compile.&lt;&#x2F;p&gt;
&lt;p&gt;But if we run our code we get a wonderfully cryptic error message:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Compiling seagl-talk v0.1.0 (&#x2F;home&#x2F;pop&#x2F;seagl-talk)
&lt;&#x2F;span&gt;&lt;span&gt; Finished dev [unoptimized + debuginfo] target(s) in 24.81s
&lt;&#x2F;span&gt;&lt;span&gt;  Running `target&#x2F;debug&#x2F;seagl-talk`
&lt;&#x2F;span&gt;&lt;span&gt;Error: Error { inner: Inner { source: None, backtrace: None, error: File(Os { code: 2, kind: NotFound, message: &amp;quot;No such file or directory&amp;quot; }) } }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We get errors like this when we have an unhandled exception in our code.
In our &lt;code&gt;main&lt;&#x2F;code&gt; function, that is any place where we call a function with a &lt;code&gt;?&lt;&#x2F;code&gt;, e.g., &lt;code&gt;foo(...)?;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;TLDT (Too Long Didn&#x27;t Troubleshoot) this is because we haven&#x27;t created our display config file!&lt;&#x2F;p&gt;
&lt;p&gt;Add a new file &lt;code&gt;display.ron&lt;&#x2F;code&gt; in a new folder called &lt;code&gt;config&#x2F;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; config&#x2F;display.ron
&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    title: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;SeaGL!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    dimensions: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;)),
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when we &lt;code&gt;cargo run&lt;&#x2F;code&gt; we should get a wonderful orange window:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;seagl-2020&#x2F;blank-window.png&quot; alt=&quot;It worked! We drew a window.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;step-2-draw-a-seagl-dove&quot;&gt;Step 2: Draw a SeaGL 🕊️&lt;&#x2F;h3&gt;
&lt;p&gt;Alas, we have a window but no game! Let&#x27;s draw our first character to the screen.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;Did you know that SeaGL&#x27;s mascot is named Patch?
https:&#x2F;&#x2F;seagl.org&#x2F;news&#x2F;2020&#x2F;09&#x2F;10&#x2F;naming-contest.html&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;First we&#x27;ll create a Component for our Seagl.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Default)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Seagl;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Component &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Seagl {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Storage &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;DenseVecStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we&#x27;ll create a Seagl entity.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;SimpleState &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;SeaglState {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;on_start&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: StateData&amp;lt;GameData&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; transform &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Transform::default();
&lt;&#x2F;span&gt;&lt;span&gt;        transform.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;set_translation_xyz&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;50.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;50.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; seagl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Seagl::default();
&lt;&#x2F;span&gt;&lt;span&gt;        data.world
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;create_entity&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(seagl)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(transform)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a good start, but our Seagl is a spriteless ghost!&lt;&#x2F;p&gt;
&lt;div class=&quot;warning&quot;&gt;
    &lt;span class=&quot;warning-title&quot;&gt;
        Warning
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;warning-body&quot;&gt;
        &lt;p&gt;Seagull ghosts are terrifying.
Add a sprite!&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;First we need to load the spritesheet into memory.
Add this in our &lt;em&gt;on_start&lt;&#x2F;em&gt; function above where we added the seagl:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sprite_sheet_handle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; loader &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; data.world.read_resource::&amp;lt;Loader&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; texture_storage &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; data.world.read_resource::&amp;lt;AssetStorage&amp;lt;Texture&amp;gt;&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; texture_handle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; loader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;texture&#x2F;spritesheet.png&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ImageFormat::default(),
&lt;&#x2F;span&gt;&lt;span&gt;        (),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;texture_storage,
&lt;&#x2F;span&gt;&lt;span&gt;    );
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sprite_sheet_store &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; data.world.read_resource::&amp;lt;AssetStorage&amp;lt;SpriteSheet&amp;gt;&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    loader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;texture&#x2F;spritesheet.ron&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        SpriteSheetFormat(texture_handle),
&lt;&#x2F;span&gt;&lt;span&gt;        (),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;sprite_sheet_store,
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then modify our Seagl entity like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;++ main.rs
&lt;&#x2F;span&gt;&lt;span&gt;@@ impl SimpleState for SeaglState
&lt;&#x2F;span&gt;&lt;span&gt;@@ fn on_start(...)
&lt;&#x2F;span&gt;&lt;span&gt;  let mut transform = Transform::default();
&lt;&#x2F;span&gt;&lt;span&gt;  transform.set_translation_xyz(50.0, 50.0, 0.0);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+ let sprite = SpriteRender::new(sprite_sheet_handle.clone(), 0);
&lt;&#x2F;span&gt;&lt;span&gt;  let seagl = Seagl::default();
&lt;&#x2F;span&gt;&lt;span&gt;  data.world
&lt;&#x2F;span&gt;&lt;span&gt;      .create_entity()
&lt;&#x2F;span&gt;&lt;span&gt;      .with(seagl)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+     .with(sprite)
&lt;&#x2F;span&gt;&lt;span&gt;      .with(transform)
&lt;&#x2F;span&gt;&lt;span&gt;      .build();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s see.
We created a Seagl entity. Let&#x27;s try running this thing:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;thread &amp;#39;main&amp;#39; panicked at &amp;#39;Tried to fetch resource of type `MaskedStorage&amp;lt;Seagl&amp;gt;`[^1] from the `World`, but the resource does not exist.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;You may ensure the resource exists through one of the following methods:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;* Inserting it when the world is created: `world.insert(..)`.
&lt;&#x2F;span&gt;&lt;span&gt;* If the resource implements `Default`, include it in a system&amp;#39;s `SystemData`, and ensure the system is registered in the dispatcher.
&lt;&#x2F;span&gt;&lt;span&gt;* If the resource does not implement `Default`, insert it in the world during `System::setup`.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hmm.
It seems like our &lt;code&gt;Seagl&lt;&#x2F;code&gt; Component isn&#x27;t registered with Amethyst.
This happens implicitly when we add a system that uses our component, but until we write a System, we&#x27;ll have to explicitly register our Component with Amethyst.&lt;&#x2F;p&gt;
&lt;p&gt;Add this toward the top of our &lt;code&gt;on_start&lt;&#x2F;code&gt; method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;data.world.register::&amp;lt;Seagl&amp;gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s try running again:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;Error { inner: Inner { source: Some(Error { inner: Inner { source: None, backtrace: None,
&lt;&#x2F;span&gt;&lt;span&gt;error: Os { code: 2, kind: NotFound, message: &amp;quot;No such file or directory&amp;quot; } } }), backtrace: None,
&lt;&#x2F;span&gt;&lt;span&gt;error: StringError(&amp;quot;Failed to fetch metadata for \&amp;quot;&#x2F;home&#x2F;pop&#x2F;seagl-talk&#x2F;assets&#x2F;texture&#x2F;spritesheet.ron\&amp;quot;&amp;quot;) } }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ah, a different runtime error.
This time we forgot to add our spritesheet image and spritesheet config file.
Lets add those.&lt;&#x2F;p&gt;
&lt;p&gt;Add this code to a file in &lt;code&gt;assets&#x2F;texture&#x2F;spritesheet.ron&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; assets&#x2F;texture&#x2F;spritesheet.ron
&lt;&#x2F;span&gt;&lt;span&gt;List((
&lt;&#x2F;span&gt;&lt;span&gt;    texture_width: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    texture_height: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    sprites: [
&lt;&#x2F;span&gt;&lt;span&gt;        ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Seagl
&lt;&#x2F;span&gt;&lt;span&gt;            x: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            y: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            width: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            height: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ),
&lt;&#x2F;span&gt;&lt;span&gt;        ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; Burger
&lt;&#x2F;span&gt;&lt;span&gt;            x: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            y: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            width: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            height: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ),
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And save this image to &lt;code&gt;assets&#x2F;texture&#x2F;spritesheet.png&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;seagl-2020&#x2F;spritesheet.png&quot; alt=&quot;Seagl and Burger. 32x16. Pixel on LCD.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now if we run &lt;code&gt;cargo run&lt;&#x2F;code&gt; we get the same blank orange window.
This happened because we forgot to add a Camera to the scene!&lt;&#x2F;p&gt;
&lt;p&gt;Add this to the end of our &lt;code&gt;on_start&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; transform &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Transform::default();
&lt;&#x2F;span&gt;&lt;span&gt;transform.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;set_translation_xyz&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;50.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;50.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;data.world
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;create_entity&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(Camera::standard_2d(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;100.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;100.0&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(transform)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;seagl-2020&#x2F;window-with-seagl.png&quot; alt=&quot;That&amp;#39;s a nice looking Seagl there...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;It&#x27;s so beautifull...&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h3 id=&quot;step-3-move-around-horse-racing&quot;&gt;Step 3: Move Around 🏇&lt;&#x2F;h3&gt;
&lt;p&gt;Thinking back to our ECS discussion, we have two of the three ingredients: an Entity, some Components, but no Systems!&lt;&#x2F;p&gt;
&lt;p&gt;First, we need to create a System struct and implement &lt;code&gt;System&lt;&#x2F;code&gt; on it.&lt;&#x2F;p&gt;
&lt;p&gt;Our System&#x27;s run function looks like this in psuedocode:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;for every seagl that can move:
&lt;&#x2F;span&gt;&lt;span&gt;    If the user input was to move horizontal:
&lt;&#x2F;span&gt;&lt;span&gt;        Move the seagl horizontally
&lt;&#x2F;span&gt;&lt;span&gt;    If the user input was to move vertical:
&lt;&#x2F;span&gt;&lt;span&gt;        Move the seagl vertically
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This doesn&#x27;t look &lt;em&gt;exactly&lt;&#x2F;em&gt; the same in Rust, but it&#x27;s pretty close.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(SystemDesc)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MoveSystem;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; System&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MoveSystem {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;SystemData &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        WriteStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Transform&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ReadStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Seagl&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Read&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Time&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Read&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, InputHandler&amp;lt;StringBindings&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    );
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;mut transforms&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;seagls&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SystemData) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; speed: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;50.0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(_seagl, transform) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;seagls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span&gt; transforms).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(horizontal) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;axis_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;horizontal&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                transform.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;prepend_translation_x&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;                    horizontal &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; time.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;delta_seconds&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; speed  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32
&lt;&#x2F;span&gt;&lt;span&gt;                );
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            };
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(vertical) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;axis_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;vertical&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                transform.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;prepend_translation_y&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;                    vertical &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; time.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;delta_seconds&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; speed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;f32
&lt;&#x2F;span&gt;&lt;span&gt;                );
&lt;&#x2F;span&gt;&lt;span&gt;            };
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We declare a &lt;code&gt;SystemData&lt;&#x2F;code&gt; type which is a tuple of components.
The &lt;code&gt;Transform&lt;&#x2F;code&gt; component will be modified, so we require it as &lt;code&gt;mut&lt;&#x2F;code&gt;, but everything else is &lt;code&gt;Read&lt;&#x2F;code&gt; for stuff that Amethyst provides and &lt;code&gt;ReadStorage&lt;&#x2F;code&gt; for things we created.&lt;&#x2F;p&gt;
&lt;p&gt;We loop over every entity with the &lt;code&gt;Seagl&lt;&#x2F;code&gt; and &lt;code&gt;Transform&lt;&#x2F;code&gt; components, then we match against any user input:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If we had &quot;vertical&quot; input, move the entity on the x axis.&lt;&#x2F;li&gt;
&lt;li&gt;If we had &quot;horizontal&quot; input, move the entity on the y axis.&lt;&#x2F;li&gt;
&lt;li&gt;We don&#x27;t need to explicitly say &quot;move left&quot;&#x2F;&quot;move right&quot; because the horizontal&#x2F;vertical inputs can be positive or negative.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Next we need to register this system with out game.
Because we are using Inputs we also need to register the inputs bundle with the game.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ main.rs
&lt;&#x2F;span&gt;&lt;span&gt;@@ fn main() -&amp;gt; amethyst::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;     )
&lt;&#x2F;span&gt;&lt;span&gt;     .with_plugin(RenderFlat2D::default());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    let bindings_path = app_root.join(&amp;quot;config&amp;quot;).join(&amp;quot;bindings.ron&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    let inputs = InputBundle::&amp;lt;StringBindings&amp;gt;::new().with_bindings_from_file(bindings_path)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;     let game_data = GameDataBuilder::default()
&lt;&#x2F;span&gt;&lt;span&gt;         .with_bundle(transform)?
&lt;&#x2F;span&gt;&lt;span&gt;         .with_bundle(renderer)?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        .with_bundle(inputs)?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        .with(MoveSystem, &amp;quot;move_system&amp;quot;, &amp;amp;[&amp;quot;input_system&amp;quot;]);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;     let mut game = Application::new(assets_dir, SeaglState, game_data)?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have a dependency on the &lt;code&gt;input_system&lt;&#x2F;code&gt;, so Amethyst will ensure that system runs before &lt;code&gt;move_system&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Next we need to create a config file for our movement bindings.
Instead of hard-coding &quot;Up arrow means move up, down arrow means down&quot; we put that in config files:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; config&#x2F;bindings.ron
&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    axes: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;horizontal&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: Emulated(pos: Key(Right), neg: Key(Left)),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;vertical&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: Emulated(pos: Key(Up), neg: Key(Down)),
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    actions: {},
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;![It moves!](&#x2F;images&#x2F;seagl-2020&#x2F;SeaGL-move.gif&quot; class=&quot;align-center)&lt;&#x2F;p&gt;
&lt;p&gt;This is a good start, but you&#x27;ll notice the Seagl doesn&#x27;t turn left and right, this &lt;em&gt;totally&lt;&#x2F;em&gt; breaks my suspension of disbelief so we&#x27;re gonna need to fix that in our &lt;code&gt;run&lt;&#x2F;code&gt; method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;src&#x2F;main.rs b&#x2F;src&#x2F;main.rs
&lt;&#x2F;span&gt;&lt;span&gt;@@ impl&amp;lt;&amp;#39;s&amp;gt; System&amp;lt;&amp;#39;s&amp;gt; for MoveSystem
&lt;&#x2F;span&gt;&lt;span&gt;@@ run(...)
&lt;&#x2F;span&gt;&lt;span&gt;  if let Some(vertical) = input.axis_value(&amp;quot;vertical&amp;quot;) {
&lt;&#x2F;span&gt;&lt;span&gt;      transform.prepend_translation_x(
&lt;&#x2F;span&gt;&lt;span&gt;        horizontal * time.delta_seconds() * speed  as f32
&lt;&#x2F;span&gt;&lt;span&gt;      );
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+     if horizontal &amp;gt; 0.0 {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+       transform.set_rotation_y_axis(std::f32::consts::PI);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+     }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+     if horizontal &amp;lt; 0.0 {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+       transform.set_rotation_y_axis(0.0);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+     }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;  };
&lt;&#x2F;span&gt;&lt;span&gt;  if let Some(vertical) = input.axis_value(&amp;quot;vertical&amp;quot;) {
&lt;&#x2F;span&gt;&lt;span&gt;      transform.prepend_translation_y(
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In our &quot;horizontal&quot; check we added:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the input was greater than 0, flip our sprite on the Y axis.&lt;&#x2F;li&gt;
&lt;li&gt;If the input was less than 0, reset our sprite on the Y axis.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This makes it look like our Seagl is facing the direction they&#x27;re moving which should help boost our Metacritic score when we publish this at the end of the blogpost.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;We rotate by PI because our 2D sprite is in the 3D world and we&#x27;re rotating it in radians.&lt;&#x2F;p&gt;
&lt;p&gt;Do you ever feel like a 2D sprite in a 3D world? I know I do...&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;seagl-2020&#x2F;SeaGL-move-look.gif&quot; alt=&quot;It moves!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;step-4-eat-some-food-hamburger&quot;&gt;Step 4: Eat some food! 🍔&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m sure we could all get &lt;em&gt;minutes&lt;&#x2F;em&gt; of fun out of moving our seagl around the screen, but this game could really use something else... Something tastier.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s add burgers.&lt;&#x2F;p&gt;
&lt;p&gt;This will require us to do everything we just did, again:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Add a Food Compnent.&lt;&#x2F;li&gt;
&lt;li&gt;Create a Burger entity with the food component.&lt;&#x2F;li&gt;
&lt;li&gt;Add an Eat system.&lt;&#x2F;li&gt;
&lt;li&gt;Register our Eat system with the game.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;First we need to add a food Component.&lt;&#x2F;p&gt;
&lt;p&gt;Add this component anywhere that feels right:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Default)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Food;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Component &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Food {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Storage &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;DenseVecStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s structurally identical to our Seagl, but with a different &lt;code&gt;struct&lt;&#x2F;code&gt; it&#x27;s a totally different component.&lt;&#x2F;p&gt;
&lt;p&gt;With a Food component we can add our Burger entity.
Add this code to our &lt;code&gt;on_setup&lt;&#x2F;code&gt; function at the end:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; burger_sprite &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;SpriteRender::new(sprite_sheet_handle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; transform &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Transform::default();
&lt;&#x2F;span&gt;&lt;span&gt;transform.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;set_translation_xyz&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;75.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;75.0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;data.world
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;create_entity&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(Food::default())
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(burger_sprite)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(transform)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We create an entity spawning it at the point (75, 75, -1).&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;We spawn the burger at &lt;code&gt;z=-1&lt;&#x2F;code&gt; to ensure the Seagl sprite is closer to
the camera and thus is drawn on top of the burger.&lt;&#x2F;p&gt;
&lt;p&gt;Have you ever seen a Seagull &lt;em&gt;behind&lt;&#x2F;em&gt; a burger? That&#x27;s ridiculous.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;A few exercises left to the reader:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;How would you spawn multiple burgers?&lt;&#x2F;li&gt;
&lt;li&gt;How would you re-spawn burgers when one is eaten?&lt;&#x2F;li&gt;
&lt;li&gt;How would you keep track of how many burgers were eaten?&lt;&#x2F;li&gt;
&lt;li&gt;How would you display the number of burgers eaten?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I&#x27;ve only covered enough in this post to answer the first two.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;And finally an &quot;eat&quot; system.&lt;&#x2F;p&gt;
&lt;p&gt;This system&#x27;s pseudocode looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;For each seagl with a location:
&lt;&#x2F;span&gt;&lt;span&gt;    For each Food with a location:
&lt;&#x2F;span&gt;&lt;span&gt;        If the Seagl overlaps with the Food:
&lt;&#x2F;span&gt;&lt;span&gt;            Destory that food
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a bit of a hack.
If this were a real game we would keep track of how many burgers the Seagl ate, but for this demo, we&#x27;ll be lazy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;EatSystem;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; System&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;EatSystem {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;SystemData &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        ReadStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Transform&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ReadStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Seagl&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ReadStorage&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;, Food&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Entities&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    );
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;transforms&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;seagls&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;foods&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;entities&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SystemData) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(_seagl, seagl_pos) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;seagls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;transforms).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(_food, food_pos, entity) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;foods, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;transforms, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;entities).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Games&#x2F;Techniques&#x2F;2D_collision_detection
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(seagl_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; food_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;5.0&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;                   (seagl_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; food_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().x) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;                   (seagl_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; food_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;4.0&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;                   (seagl_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; food_pos.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span&gt;().y)
&lt;&#x2F;span&gt;&lt;span&gt;                {
&lt;&#x2F;span&gt;&lt;span&gt;                    entities.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;delete&lt;&#x2F;span&gt;&lt;span&gt;(entity).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And last but not least, we need to register this system with our game:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ main.rs
&lt;&#x2F;span&gt;&lt;span&gt;@@ fn main() -&amp;gt; amethyst::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;     let game_data = GameDataBuilder::default()
&lt;&#x2F;span&gt;&lt;span&gt;         .with_bundle(transform)?
&lt;&#x2F;span&gt;&lt;span&gt;         .with_bundle(renderer)?
&lt;&#x2F;span&gt;&lt;span&gt;         .with_bundle(inputs)?
&lt;&#x2F;span&gt;&lt;span&gt;         .with(MoveSystem, &amp;quot;move_system&amp;quot;, &amp;amp;[&amp;quot;input_system&amp;quot;])
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        .with(EatSystem, &amp;quot;eat_system&amp;quot;, &amp;amp;[&amp;quot;move_system&amp;quot;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;seagl-2020&#x2F;SeaGL-move-look-burger.gif&quot;
class=&quot;align-center&quot; alt=&quot;It moves!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;We did it. We made a lil&#x27; game. It had a Seagl and a burger. And we had
fun making it.&lt;&#x2F;p&gt;
&lt;p&gt;I wouldn&#x27;t say it&#x27;s &lt;em&gt;easy&lt;&#x2F;em&gt; to make games in Rust, but we are &lt;em&gt;very far&lt;&#x2F;em&gt;
from having to write games from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;If this post piqued your interest I hope you check out &lt;a href=&quot;https:&#x2F;&#x2F;arewegameyet.rs&quot;&gt;https:&#x2F;&#x2F;arewegameyet.rs&lt;&#x2F;a&gt; to learn more about the Rust Games ecosystem, and &lt;a href=&quot;https:&#x2F;&#x2F;amethyst.rs&quot;&gt;https:&#x2F;&#x2F;amethyst.rs&lt;&#x2F;a&gt; to learn more about this budding Game Engine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;SeaGL conference website: &lt;a href=&quot;https:&#x2F;&#x2F;seagl.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;seagl.org&#x2F;&lt;&#x2F;a&gt; (You should go if you&#x27;re in the Pacific Northwest)&lt;&#x2F;li&gt;
&lt;li&gt;The code for this post is avaliable at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pop&#x2F;lets-make-games-with-rust&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;pop&#x2F;lets-make-games-with-rust&lt;&#x2F;a&gt;. I even tagged each step so you can see exactly what we added!&lt;&#x2F;li&gt;
&lt;li&gt;Rust Language: &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Are We Game Yet?: &lt;a href=&quot;https:&#x2F;&#x2F;arewegameyet.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;arewegameyet.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Amethyst Game Engine website: &lt;a href=&quot;https:&#x2F;&#x2F;amethyst.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;amethyst.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Amethyst Game Engine book has a great introduction and overview: &lt;a href=&quot;https:&#x2F;&#x2F;book.amethyst.rs&#x2F;stable&#x2F;&quot;&gt;https:&#x2F;&#x2F;book.amethyst.rs&#x2F;stable&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Bevy Game Engine is an interesting iteration on Game Engines in Rust: &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;bevyengine.org&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;My Source that C++ is the defacto language in the games industry: &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;rX0ItVEVjHc&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;rX0ItVEVjHc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Game Programming Patterns is an awesome book with a free &amp;amp; legal copy online: &lt;a href=&quot;https:&#x2F;&#x2F;gameprogrammingpatterns.com&#x2F;&quot;&gt;https:&#x2F;&#x2F;gameprogrammingpatterns.com&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rustup&lt;&#x2F;code&gt; homepage for installation instructions: &lt;a href=&quot;https:&#x2F;&#x2F;rustup.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;rustup.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Kubernetes as an external service proxy</title>
        <published>2018-10-13T00:00:00+00:00</published>
        <updated>2018-10-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/kubernetes-as-an-external-service-proxy/"/>
        <id>https://elijah.run/blog/kubernetes-as-an-external-service-proxy/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/kubernetes-as-an-external-service-proxy/">&lt;p&gt;Say you have a firewall restriction that creates the following situation:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;App1 cannot communicate directly with App2.&lt;&#x2F;li&gt;
&lt;li&gt;App1 and App2 can both talk to a Kubernets cluster.&lt;&#x2F;li&gt;
&lt;li&gt;Neither app is hosted on the Kubernetes cluster.&lt;&#x2F;li&gt;
&lt;li&gt;How can you get messages between App1 and App2?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The way the problem is stated makes it pretty obvious that the solution &lt;em&gt;involves&lt;&#x2F;em&gt; using a Kubernetes cluster, but how exactly?&lt;&#x2F;p&gt;
&lt;p&gt;The naive solution might be to spin up a container which acts as a proxy; Nginx comes to mind.
This would definitely work, but I am exceedingly lazy and don&#x27;t want to learn how to configure Nginx.
In fact, the solution I came to doesn&#x27;t involve running any new pods!&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the code.
Below I&#x27;ll explain what&#x27;s happening here and why it works.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Endpoints
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;myapp-proxy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;subsets&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;addresses&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;2.3.4.5k &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# App2&amp;#39;s address
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8080 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# App2&amp;#39;s service port
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;myapp-proxy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;LoadBalancer
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;loadBalancerSourceRanges&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1.2.3.4&#x2F;32&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# App1&amp;#39;s address
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;TCP
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;80 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Redirect traffic hitting 80 to the app&amp;#39;s service port
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;targetPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Ingress
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;restaurant-proxy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;myapp-proxy.somehost.net
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;serviceName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;myapp-proxy
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;servicePort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;endpoints&quot;&gt;Endpoints&lt;&#x2F;h2&gt;
&lt;p&gt;Endpoints are the Kubernetes abstraction for IPs+Ports running the same application.
It&#x27;s how you group together N instances of an app into one pool.&lt;&#x2F;p&gt;
&lt;p&gt;Under the hood Endpoints get created as a pre-requisite for every Service you deploy.
You don&#x27;t usually need to deal with these directly as they are created implicitly whenever a Deployment gets applied.&lt;&#x2F;p&gt;
&lt;p&gt;By manually creating an endpoint we have imported our non-kubernetes app into Kubernetes.
That means we can do Kubernetes things with it like expose it via a Service or even put it behind an Ingress Pretty neat!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;service&quot;&gt;Service&lt;&#x2F;h2&gt;
&lt;p&gt;Services are how we expose an endpoint to the world.
Most cloud providers will give you a public IP address for a service and load balance across all of that service&#x27;s endpoints.&lt;&#x2F;p&gt;
&lt;p&gt;This is as far as we need to proxy traffic between our two Apps.
App1 makes a request to whatever IP Kubernetes gets for the &lt;code&gt;myapp-proxy&lt;&#x2F;code&gt; Service and relays it to the &lt;code&gt;myapp-proxy&lt;&#x2F;code&gt; endpoint, which ultimately routes the traffic to App2.
What&#x27;s really cool is that the endpoint that &lt;strong&gt;is&lt;&#x2F;strong&gt; App2 can be an self-hosted Virtual Machine, as long as the IP doesn&#x27;t change this proxy will continue to work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ingress&quot;&gt;Ingress&lt;&#x2F;h2&gt;
&lt;p&gt;Ingresses are my favorite part of Kubernetes.
They&#x27;re very convenient, incredibly powerful, and they work like... over half the time.&lt;&#x2F;p&gt;
&lt;p&gt;While not strictly necessary, this Ingress gives us some nice-to-haves.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Gives us an easy to manage host name via something like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes-incubator&#x2F;external-dns&quot;&gt;External DNS&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Could be extended to terminate SSL, again &quot;for free&quot;, with something like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jetstack&#x2F;cert-manager&quot;&gt;Cert Manager&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So that&#x27;s how we use Kubernetes to manage services (lower-case &#x27;s&#x27;) which aren&#x27;t running in Pods.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dynamic Attributes in Chef</title>
        <published>2018-06-23T00:00:00+00:00</published>
        <updated>2018-06-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/chef-dynamic-attributes/"/>
        <id>https://elijah.run/blog/chef-dynamic-attributes/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/chef-dynamic-attributes/">&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;&#x2F;h2&gt;
&lt;p&gt;You are trying to set a node attribute in a resource block but it isn&#x27;t working.&lt;&#x2F;p&gt;
&lt;p&gt;For example you have the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ruby&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-ruby &quot;&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span&gt;ruby_block &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;do
&lt;&#x2F;span&gt;&lt;span&gt;  block &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;do
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# some ruby
&lt;&#x2F;span&gt;&lt;span&gt;    node.override[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;  action &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;:run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; node[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  notifies &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;:run&lt;&#x2F;span&gt;&lt;span&gt;, some_resource[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;  notifies &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;:run&lt;&#x2F;span&gt;&lt;span&gt;, other_resource[whatever]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even though you&#x27;re setting &lt;code&gt;node[&#x27;var&#x27;]&lt;&#x2F;code&gt;, &lt;code&gt;other_resource[whatever]&lt;&#x2F;code&gt; is getting notified to &lt;code&gt;:run&lt;&#x2F;code&gt;.
What gives?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;&#x2F;h2&gt;
&lt;p&gt;To jump ahead, because you&#x27;re skimming this post for the answer, you&#x27;re going to want to do something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;# go-go-gadget diffs
&lt;&#x2F;span&gt;&lt;span&gt;# Chef Version 13.5.8
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  ruby_block &amp;#39;foo&amp;#39; do
&lt;&#x2F;span&gt;&lt;span&gt;    block do
&lt;&#x2F;span&gt;&lt;span&gt;      # some ruby
&lt;&#x2F;span&gt;&lt;span&gt;      node.override[&amp;#39;var&amp;#39;] = &amp;#39;value&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    end
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-   action :run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+   action :nothing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- end
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+ end.run_action(:run)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;if node[&amp;#39;var&amp;#39;] == &amp;#39;value&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  notifies :run, some_resource[name]
&lt;&#x2F;span&gt;&lt;span&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;  notifies :run, other_resource[whatever]
&lt;&#x2F;span&gt;&lt;span&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Basically you want to execute the &lt;code&gt;ruby_block&lt;&#x2F;code&gt; that sets your attribute &lt;strong&gt;now&lt;&#x2F;strong&gt; so the rest of your code can consume the value either later in the compilation phase or during the execution phase of the Chef run.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-why-did-that-work&quot;&gt;How&#x2F;why did that work?&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve read his far you&#x27;re actually reading.
Welcome to the post!
Let&#x27;s begin.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s dig into &lt;em&gt;exactly&lt;&#x2F;em&gt; what my problem was, because sometimes examples aren&#x27;t good enough.
You know... for fun.&lt;&#x2F;p&gt;
&lt;p&gt;I was trying to trigger an application upgrade based on the current installed version.
I was &lt;em&gt;not&lt;&#x2F;em&gt; installing a package-manager-managed package&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; so I couldn&#x27;t just pin the version a &lt;code&gt;yum&lt;&#x2F;code&gt; resource, I had to do this kludge of a solution.&lt;&#x2F;p&gt;
&lt;p&gt;So for me &lt;code&gt;some_resource[name]&lt;&#x2F;code&gt; was downloading the latest version of the app (a &lt;code&gt;.tar.gz2&lt;&#x2F;code&gt; file from GitHub) and &lt;code&gt;other_resource[whatever]&lt;&#x2F;code&gt; was a no-op. The as part of the package download I unconditionally trigger a &lt;code&gt;:delayed&lt;&#x2F;code&gt; service restart.
Chef was &#x27;upgrading&#x27; and restarting my app every thirty minutes which broke core functionality.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shit-i-tried-before-stumbling-upon-the-solution&quot;&gt;Shit I tried before stumbling upon the solution&lt;&#x2F;h2&gt;
&lt;p&gt;I tried a bunch of things, but they can all kinda be summed up in this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;# yay more diffs
&lt;&#x2F;span&gt;&lt;span&gt;  ruby_block &amp;#39;foo&amp;#39; do
&lt;&#x2F;span&gt;&lt;span&gt;    block do
&lt;&#x2F;span&gt;&lt;span&gt;      # some ruby
&lt;&#x2F;span&gt;&lt;span&gt;      node.override[&amp;#39;var&amp;#39;] = &amp;#39;value&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    end
&lt;&#x2F;span&gt;&lt;span&gt;    notifies :create, &amp;#39;tar[my-app]&amp;#39;, :immediately # Triggers tar[my-app] to run now
&lt;&#x2F;span&gt;&lt;span&gt;  end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- if node[&amp;#39;var&amp;#39;] == &amp;#39;value&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-   notify :run, some_resource[name]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-   notify :run, other_resource[whatever]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  tar &amp;#39;my-app&amp;#39; do
&lt;&#x2F;span&gt;&lt;span&gt;    action  :nothing # Unless triggered this does nothing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+   only_if { node[&amp;#39;var&amp;#39;] == &amp;#39;value&amp;#39; } # This should also do nothing if this isn&amp;#39;t true
&lt;&#x2F;span&gt;&lt;span&gt;    # The rest of the resource block
&lt;&#x2F;span&gt;&lt;span&gt;  end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which ultimately didn&#x27;t work either.&lt;&#x2F;p&gt;
&lt;p&gt;I... I have no idea why this didn&#x27;t work.&lt;&#x2F;p&gt;
&lt;p&gt;Something something Chef is complicated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-the-solution-works-and-the-other-stuff-didn-t&quot;&gt;Why the solution works (and the other stuff didn&#x27;t)&lt;&#x2F;h2&gt;
&lt;p&gt;The reason my ultimate solution &lt;em&gt;did&lt;&#x2F;em&gt; work is best summed up by this quote from the &lt;a href=&quot;https:&#x2F;&#x2F;docs.chef.io&#x2F;resource_common.html#run-action&quot;&gt;Chef Docs&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use &lt;code&gt;.run_action(:some_action)&lt;&#x2F;code&gt; at the end of a resource block to run
the specified action during the compile phase.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;My original code (read: broken code) was running the &lt;code&gt;if&lt;&#x2F;code&gt; block during the compilation phase (happens earlier) and running the &lt;code&gt;ruby_block&lt;&#x2F;code&gt; in the execution phase (happens later).
By telling it to run my &lt;code&gt;ruby_block&lt;&#x2F;code&gt; during the compilation phase we were ensuring it happened before the &lt;code&gt;if&lt;&#x2F;code&gt; block, and in a way running it like you would &#x27;expect&#x27; a script to run.&lt;&#x2F;p&gt;
&lt;p&gt;It ain&#x27;t idiomatic but it gets the job done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Say that three times fast.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The service was in question was Prometheus.
When Chef ran every 30 minutes, it killed the Prometheus process and thus killed all of our pending alerts.
TLDR we didn&#x27;t get any alerts that took more than 30 minutes to trigger We also &lt;em&gt;kept&lt;&#x2F;em&gt; getting alerts that should taken a few hours to re-notify.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I. Fucking. Graduated.</title>
        <published>2017-12-12T00:00:00+00:00</published>
        <updated>2017-12-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/graduation/"/>
        <id>https://elijah.run/blog/graduation/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/graduation/">&lt;p&gt;Today I checked my grades for the last time.
I can safely say that I have &lt;strong&gt;finally&lt;&#x2F;strong&gt; gotten a gorramn undergraduate degree in Computer Science, with a minor in Mathematics, from Oregon State University.[^1]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I hear that this happens on the reg&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; but I&#x27;m sure that every single person who &lt;em&gt;actually graduates&lt;&#x2F;em&gt; feels amazing when they do.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not amazing because graduation is a Herculean feat.
I know I&#x27;m not a 60 year old grandmother who dreamt of getting a college degree for 45 years and finally scraped together the cash and time in retirement.
I&#x27;m also not a refugee that escaped a war-torn country for an education and a better life.
I&#x27;m just another white dude that checked all the boxes.&lt;&#x2F;p&gt;
&lt;p&gt;It wasn&#x27;t hard for me. I just had to put my head down and do the work.
But it did take a long ass time.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly my story is exactly like &lt;em&gt;most&lt;&#x2F;em&gt; college graduation stories.
I went to kindergarten, then elementary school, then middle school, then high school, then college, and now life.
I plugged away at school, did what I needed to pass my classes, stressed and lamented, studied hard and eventually the system said &quot;Cool.You&#x27;re done.&quot; Along the way I learned how to &quot;play the game&quot;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, albeit a bit late compared to a lot of my peers.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m thankful to be in a field which doesn&#x27;t require a masters or PHD to get a jorb.
Heck my field doesn&#x27;t really require the degree I got; a surprising number of my friends got well paying jobs sans-degree.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m also thankful to graduate without debt.
This came from some kickass parents + grandparents, some work during school, and some bad stuff that happened which ended up paying for abou half of my tuition.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m thankful to graduate with wonderful friends, a job, and some passions which make my work-related decisions simple and profitable.&lt;&#x2F;p&gt;
&lt;p&gt;Last, I&#x27;m thankful to be &lt;em&gt;done&lt;&#x2F;em&gt;. Now I can finally focus on &lt;em&gt;learning&lt;&#x2F;em&gt;, my real passion.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m gonna have a &lt;a href=&quot;https:&#x2F;&#x2F;10barrel.com&#x2F;beer&#x2F;crush-cucumber-sour&#x2F;&quot;&gt;Cucumber Sour&lt;&#x2F;a&gt; and celebrate.
Thanks for reading.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I don&#x27;t claim to have the best sources, but at least it&#x27;s not Yahoo Answers: &lt;a href=&quot;https:&#x2F;&#x2F;www.reference.com&#x2F;education&#x2F;many-people-graduate-college-year-8b0ccf821050d39e&quot;&gt;https:&#x2F;&#x2F;www.reference.com&#x2F;education&#x2F;many-people-graduate-college-year-8b0ccf821050d39e&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Go beavs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m 99% sure I graduated.
Something horribly kafkaesque might still happen, but fuckit.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;This is shorthand for tips and tricks to get through school.&lt;&#x2F;p&gt;
&lt;p&gt;School isn&#x27;t really focused on making sure you &lt;em&gt;learned&lt;&#x2F;em&gt;, it&#x27;s mostly designed to make sure you can pass tests.
Once you figure this out you can focus on learning for the test instead of trying to grok the material.
I believe the kids call it a &quot;life hack&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Not that you shouldn&#x27;t try to grok the material, that just happens to take &lt;em&gt;way&lt;&#x2F;em&gt; longer than test-based learning.
So if you want a personal life, learn for the test; if you want a PHD, learn for the material.&lt;&#x2F;p&gt;
&lt;p&gt;I didn&#x27;t figure this system out until about Junior year of High School, too late to apply this zen skill to the ACT and SAT, but it was useful in college.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Independent Crypto Conclusion</title>
        <published>2017-11-27T00:00:00+00:00</published>
        <updated>2017-11-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/independent-crypto-conclusion/"/>
        <id>https://elijah.run/blog/independent-crypto-conclusion/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/independent-crypto-conclusion/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent Study on cryptography at Oregon State University.
To read all of the posts, check out the &#x27;Independent Crypto&#x27; tag.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Wait, is it over already? It feels like we just started! Those 10 weeks always fly by, and this term was no exception.&lt;&#x2F;p&gt;
&lt;p&gt;Independent Crypto has been a thrill, an honor, and of course immensely educational.
It&#x27;s been a blast to say the least.
The weekly check-ins with my mentor &lt;a href=&quot;http:&#x2F;&#x2F;web.engr.oregonstate.edu&#x2F;~rosulekm&#x2F;&quot;&gt;Mike Rosulek&lt;&#x2F;a&gt;, forcing myself to engage with academic papers and online lectures, and finally having complex topics like Garbled Circuits and Elliptic Curves &quot;make sense&quot;, it was all very enjoyable.
I am very fortunate to have been given the opportunity to both create this course and take it.
Excited as I was before it began, it turned out even better than I could have hoped.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s reflect on the some of the things we learned...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;elliptic-curve-cryptography&quot;&gt;Elliptic Curve Cryptography&lt;&#x2F;h2&gt;
&lt;p&gt;We learned that Elliptic Curves look like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-1.png&quot; alt=&quot;A straight forward ECC.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;and this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-3.png&quot; alt=&quot;ECC with the line L illustrated&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We also learned that you can implement a version of the Diffie-hellman key exchange protocol by &quot;adding&quot; points on an Elliptic Curve over a finite field.&lt;&#x2F;p&gt;
&lt;p&gt;We also learned that despite how weird Elliptic Curve Cryptography sounds when you describe it, it can be used in very secure and efficient crypto.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-hard-functions&quot;&gt;Memory Hard Functions&lt;&#x2F;h2&gt;
&lt;p&gt;We learned that Memory Hard Functions (MHFs) are a solution to the arms race that is hash-cracking hardware.
Importantly, it relies on the fact that while there are specialized hashing processors, there is no specialized RAM for the same task (or any task really).&lt;&#x2F;p&gt;
&lt;p&gt;The goal of an MHF is to make it as hard (or harder) for an adversary to compute a given hash as it was for you, assuming you&#x27;re running on non-specialized hardware and they have specialized hash-cracking hardware.&lt;&#x2F;p&gt;
&lt;p&gt;We learned that there are two types of MHF&#x27;s: data-dependent and data-independent.
Data-dependent MFHs (dMHFs) have predictable memory usage patterns so they may be susceptible to cache-timing attacks.
Data-independent MHFs (iMHFs) are not susceptible to this attack as their memory patterns are not predictable.
While there are dMHFs in the wild, like scrypt which performs exceptionally well, there are not any any proven iMHFs in use.&lt;&#x2F;p&gt;
&lt;p&gt;We also learned that this is what it looks like to &quot;Pebble an iMHF Directed Acyclic Graph&quot;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;dag-animated.gif&quot; alt=&quot;Animated DAG traversal.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We also learned that the way to attack an iMHF is by performing a breadth-first search on the graph, then once you hit a wall, fill in the
necessary nodes (pebbles) until you can compute the next node.
Much of the active research into iMHFs is in figuring out the best graphs, or types of graphs, to combat these kinds of feather&#x2F;balloon attacks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;garbled-circuits&quot;&gt;Garbled Circuits&lt;&#x2F;h2&gt;
&lt;p&gt;We learned that Garbled Circuits are a way of achieved two-party secure function evaluation.&lt;&#x2F;p&gt;
&lt;p&gt;Alice and Bob agree on a circuit (program) to garble.
One party encrypts the circuit by encrypting each logic-gate.
Both parties obfuscate their inputs and evaluate the garbled circuit.
This gives both parties the result of the original program without either party knowing the exact inputs.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t a fool-proof security measure.
Sometimes it is good to ask the party garbling said circuits to create a few extras.
The evaluating party opens some of them to make sure they&#x27;re on the up-and-up.
The other party evaluates the remaining circuits and verifies that the outputs are consistent.&lt;&#x2F;p&gt;
&lt;p&gt;We also learned that this game is surprisingly fun for only having &lt;strong&gt;four levels&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;iframe src=&quot;&#x2F;garbled-circuits-game.html&quot; height=&quot;400px&quot; width=&quot;100%&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;Permalink: &lt;a href=&quot;http:&#x2F;&#x2F;elijah.run&#x2F;garbled-circuits-game.html&quot;&gt;http:&#x2F;&#x2F;elijah.run&#x2F;garbled-circuits-game.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;remote-timing-attacks&quot;&gt;Remote Timing Attacks&lt;&#x2F;h2&gt;
&lt;p&gt;And now for something completely different!
We broke from the math and theory to focus on a problem involving real tangible bits!&lt;&#x2F;p&gt;
&lt;p&gt;Based on response timing differences an adversary can sometimes determine private information &lt;strong&gt;like your OpenSSL Private Keys&lt;&#x2F;strong&gt;.
This is scary, but the problem has mostly been fixed and now there are standards the crypto community follows to write code which is secure against these attacks.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re writing crypto and you know what you&#x27;re doing, make sure you&#x27;re using the defacto constant-time libraries for bit-wise comparisons, mathematical operations, and pretty much anything involving secrets.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;&#x2F;h2&gt;
&lt;p&gt;I personally gained a lot from this course.
I wrote annotated bibliographies, read academic papers, implemented a remote timing attack, and made a fun little game which was totally relevant and 100% not just an excuse to play around making games.&lt;&#x2F;p&gt;
&lt;p&gt;Despite sinking hours into this course I barely scratched the surface of every topic.
I&#x27;ve got &lt;em&gt;loads&lt;&#x2F;em&gt; more I could cover if I was inclined to do so.
I&#x27;m not saying I&#x27;m &lt;em&gt;going&lt;&#x2F;em&gt; to get a graduate degree, but if it&#x27;s anything like this I&#x27;d be up for it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Remote Timing Attacks</title>
        <published>2017-11-20T00:00:00+00:00</published>
        <updated>2017-11-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/remote-timing-attacks/"/>
        <id>https://elijah.run/blog/remote-timing-attacks/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/remote-timing-attacks/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent
Study on cryptography at Oregon State University. To read all of the
posts, check out the &#x27;Independent Crypto&#x27; tag.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Fade in.&lt;&#x2F;p&gt;
&lt;p&gt;It is 2002.&lt;&#x2F;p&gt;
&lt;p&gt;You are a Linux system administrator.
You and thousands of other admins are running OpenSSL on you battle tested Linux servers.
You trust that your data is transfered securely from host to host because... why wouldn&#x27;t it be?!
OpenSSL makes things secure.
Duh.&lt;&#x2F;p&gt;
&lt;p&gt;A few months into running that server you figure out that your private keys have been compromised!
They were stolen somehow but you can&#x27;t figure out what happened.
You check the logs to see if somebody hacked into your system, but nothing obvious catches your eye.&lt;&#x2F;p&gt;
&lt;p&gt;Combing through the logs you do see an IP address that tried (and failed) hundreds of thousands of times to authenticate with your OpenSSL server. It attempted authentication over and over and failed relentlessly until suddenly, after about two days, it stopped.
Weird.&lt;&#x2F;p&gt;
&lt;p&gt;A year later you read an academic paper from Stanford.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
It clicks.
You&#x27;ve you&#x27;ve been Remote Timing Attacked!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;definition&quot;&gt;Definition&lt;&#x2F;h2&gt;
&lt;p&gt;Remote Timing Attacks are a special brand of Side Channel Attack where adversaries use differences in response times to determine private information.
Creepy I know.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of code and Statistics&lt;sup&gt;TM&lt;&#x2F;sup&gt; goes into figuring out secret information based on this, but let&#x27;s start small.
Take the following comparison which lives in a hypothetical SSL library:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(recieved_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;KeyLengthError
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;recieved_key &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span&gt;expected_key:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Thing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;UnknownKeyError
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This might seem innocent enough but as it turns out this leaks information!
The &lt;code&gt;==&lt;&#x2F;code&gt; operator does not &lt;em&gt;always&lt;&#x2F;em&gt; take the same amount of time to return a response.
In fact, this operator tends to compare two inputs bit-by-bit.
When it finds a difference it short-circuits and returns True or False.
If &lt;code&gt;recieved_key&lt;&#x2F;code&gt; shares the first N bits with &lt;code&gt;expected_key&lt;&#x2F;code&gt;, the program will return slightly sooner than if they only shared the first N-1 bits.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s the timing difference if it&#x27;s just returning one or two cycles earlier; does it really matter?
As it turns out, there is &lt;em&gt;enough&lt;&#x2F;em&gt; of a difference to break security and enable an adversary to decrypt entire private keys!&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This is put well by an article on chosenplaintext.ca:&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now, it may not seem significant that an attacker can see how many bytes of their key were a match, but it can actually be &lt;strong&gt;fatal&lt;&#x2F;strong&gt; to security.
The attacker can crack the first byte of the key by trying all 256 possibilities, and observing which one caused the comparison to take longer.
Now, armed with the first byte, they can do the same with the second byte, and the third, and so on, until they have recovered the entire key.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;With a lot of patience an adversary can recover secret information from an OpenSSL processes on the same host OS, an OpenSSL processes on a Virtual Machine on the same host OS, and even an OpenSSL on a separate host processes across a network.
It gets harder (read: more time consuming) to hack the farther away adversary, but they&#x27;re all possible with sufficient patience, compute power, and Statistics&lt;sup&gt;TM&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;oh-god-fix-it-please&quot;&gt;Oh god fix it please&lt;&#x2F;h2&gt;
&lt;p&gt;Clam down!
We&#x27;ve come a long way since 2003 when this was proven to be a viable attack.
Most SSL libraries have fixed this vulnerability so you&#x27;re fine as long as you updated in the past decade.&lt;&#x2F;p&gt;
&lt;p&gt;If you &lt;em&gt;haven&#x27;t&lt;&#x2F;em&gt; updated in the past decade... burn that server.
Even the silicon atoms are compromised. It&#x27;s not even worth trying a fresh install.
The thing is just too far gone, start fresh.
Goodnight, sweet prince.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;constant-time-algorithms&quot;&gt;Constant-time Algorithms&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;How did the crypto libraries solve this problem?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Constant-time Algorithms&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Oh fancy, tell me more.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Constant-time Algorithms are a way of implementing an algorithm in a way that always takes the same amount of time to compute regardless of the input.&lt;&#x2F;p&gt;
&lt;p&gt;Specifically, these perform in constant-time while processing &lt;em&gt;secret&lt;&#x2F;em&gt; information.
This distinction means processing a secret key &lt;em&gt;always&lt;&#x2F;em&gt; takes N cycles while checking that a configuration file is correctly formatted might take a M cycles or maybe M+5.&lt;&#x2F;p&gt;
&lt;p&gt;There are a lot of coding practices to be aware of in crypto which help us to avoid leaking information for Remote Timing Attacks.
Let&#x27;s go over a few.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;limit-conditionals-on-secrets&quot;&gt;Limit conditionals on secrets&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Avoid conditioning on secret information to avoid (among other things)
CPU branch predictions.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Take this code for example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;usually_true:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;do_usual_thing&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Path A
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;do_weird_thing&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Path B
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The CPU eventually will recognize that Path A is going to happen more than Path B so it will try to optimize for that path, making the &quot;usual thing&quot; faster.
This makes sense from a CPU designer standpoint&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but it leaks information about which branch is being taken.
When the &quot;unusual thing&quot; happens the CPU has to backpedal before continuing, which takes a notable amount of time.
This backpedaling gives an adversary enough information to craft an attack the path they&#x27;re on and extrapolate secret information based on that path-awareness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;This type of attack (conditioning on private information) is explored in the Constant Time Algorithm example and Remote Timing Attack demo near the end of the post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;division-multiplication-tricky-stuff&quot;&gt;Division&#x2F;Multiplication: tricky stuff&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Multiplication is not always constant-time.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Take this piece of code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;t1_a = current_time
&lt;&#x2F;span&gt;&lt;span&gt;small_number_a * small_number_b
&lt;&#x2F;span&gt;&lt;span&gt;t2_a = current_time
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;t1_b = current_time
&lt;&#x2F;span&gt;&lt;span&gt;big_number_a * big_number_b
&lt;&#x2F;span&gt;&lt;span&gt;t2_b = current_time
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;assert(t2_a - t1_a == t2_b - t1_b)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Believe it or not, even though the first and second blocks are just multiplying two numbers together they can take different amounts of time depending on your CPU and compiler.&lt;&#x2F;p&gt;
&lt;p&gt;This is triggered by some CPUs just not being equipped to handle large numbers, so they have to perform the large number multiplication in software.
Other CPUs optimize for small numbers since those get handled more frequently than large numbers.
These are pretty old hardware limitations, and the issue has mostly been resolved in newer 64-bit CPUs.
That said... you know... still something to lookout for.&lt;&#x2F;p&gt;
&lt;p&gt;The same goes for division. Many CPUs don&#x27;t have hardware support for division so the compiler needs to handle the operation in software.&lt;&#x2F;p&gt;
&lt;p&gt;TLDR: the same piece of code which is constant-time on one architecture (X86_64) might not be constant-time on another piece of hardware (x86_32 for example).&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compilers-and-undefined-behavior&quot;&gt;Compilers and undefined behavior&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Watch out for compiler&#x27;s &quot;undefined behavior&quot;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The C programming language, and &lt;em&gt;most&lt;&#x2F;em&gt; programming languages, have a formal specification of some kind.
This formal specification gives the programmer a good idea about what their code will do when they compile and run it.&lt;&#x2F;p&gt;
&lt;p&gt;For example if I wrote the following C:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;20
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;it &lt;em&gt;should&lt;&#x2F;em&gt; run and return &lt;code&gt;30&lt;&#x2F;code&gt;, because the specification tells us that the &lt;code&gt;+&lt;&#x2F;code&gt; operator adds two numbers and &lt;code&gt;return&lt;&#x2F;code&gt; returns a given value from a function.
It also says that &lt;code&gt;main&lt;&#x2F;code&gt; returns a given integer as the exit status.&lt;&#x2F;p&gt;
&lt;p&gt;If I ran that code and it returned &lt;code&gt;-1&lt;&#x2F;code&gt; I&#x27;d be very confused; that breaks specification!
Compiler authors know this and follow the specification of the C language very carefully to make sure specified inputs produce specified outputs.&lt;&#x2F;p&gt;
&lt;p&gt;But what about behavior the specification &lt;em&gt;doesn&#x27;t&lt;&#x2F;em&gt; mention?&lt;&#x2F;p&gt;
&lt;p&gt;Take for instance this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;214748300 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;214745000&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This might not be explicitly covered by the specification because it&#x27;s pretty weird.
214748300 and 214745000 are close to the signed integer maximum, so when multiplied together what happens?
Will the program print an unsigned integer value of 4611686014132420609 or does it return a signed integer which has overflowed but is still signed?&lt;&#x2F;p&gt;
&lt;p&gt;This kind headache is called Undefined Behavior and it basically means the compiler, or rather the compiler&#x27;s authors, &lt;em&gt;choose&lt;&#x2F;em&gt; which behavior they think is best because the language spec didn&#x27;t say what should happen.&lt;&#x2F;p&gt;
&lt;p&gt;Another side effect hinted at is that while you can be confident what the end behavior of your code will be you can&#x27;t predict how that behavior is achieved.
This didn&#x27;t used to be an issue when C compilers were just 1:1 mapping your C loops and functions to sane assembly.
Fortunately compilers have gotten much better at producing fast and efficient executables.
&lt;strong&gt;Unfortunately&lt;&#x2F;strong&gt;, we aren&#x27;t easily able to predict the runtime of our code because our compilers are liable to pour some black-magic voodoo on any and all binaries it produces.&lt;&#x2F;p&gt;
&lt;p&gt;These points are condensed really well by the BearSSL website:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The C programming language is defined to run in an abstract machine under the &quot;as if&quot; rule, so the compiler is free to translate your code in any sequence of instructions that yield the expected result, with execution time not being part of the observable elements that must be preserved.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Even though we know that a function will always &lt;em&gt;work&lt;&#x2F;em&gt;, the C language (and compiler spec) doesn&#x27;t care about &lt;em&gt;how&lt;&#x2F;em&gt; it gets done.&lt;&#x2F;p&gt;
&lt;p&gt;When you&#x27;re trying to write crypto code this can feel like you&#x27;re a parent telling your kid to clean their room.
They&#x27;ll make it look clean, but they just shoved everything under the bed.
Technically they did what you wanted, the room looks cleaner, but they missed the point.
Something about building character in constant-time.&lt;&#x2F;p&gt;
&lt;p&gt;So what do we do? We need to trick the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;There are a handful of tricks to&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to get the compiler to (a) avoid
unknown behavior and (b) enforce a specific assembly output.
These are tricks include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Using a bit-wise operations instead of the equivalent mathematical operation.&lt;&#x2F;li&gt;
&lt;li&gt;Mark important &lt;em&gt;secret&lt;&#x2F;em&gt; variables as volatile.&lt;&#x2F;li&gt;
&lt;li&gt;Manually zero out important &lt;em&gt;secret filled&lt;&#x2F;em&gt; memory.&lt;&#x2F;li&gt;
&lt;li&gt;Use multiple sources of entropy; as many as you can get your hands on.&lt;&#x2F;li&gt;
&lt;li&gt;Read the output assembly and become a Jedi.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are very high-level solutions to some of the problems, solutions I&#x27;m only going to hand-wavily describe, but honestly that&#x27;s because I don&#x27;t really grok the solutions and don&#x27;t want to lead you astray.
Check out the end of this post for further reading by really smart people that get paid to do this stuff.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-can-t-i-just&quot;&gt;&quot;Why can&#x27;t I just...&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;Just &lt;em&gt;wait&lt;&#x2F;em&gt;? If only.&lt;&#x2F;p&gt;
&lt;p&gt;So the first thought I had (and every other crypto novice has) is something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;do time sensitive operation
&lt;&#x2F;span&gt;&lt;span&gt;sleep N seconds
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This doesn&#x27;t work because this just shifts the amount of time it takes to do an operation, literally &lt;em&gt;just&lt;&#x2F;em&gt; making your crypto take longer.
Then the &lt;em&gt;second&lt;&#x2F;em&gt; thought I and every other crypto novice has is something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;record start time
&lt;&#x2F;span&gt;&lt;span&gt;do time sensitive operation
&lt;&#x2F;span&gt;&lt;span&gt;record end time
&lt;&#x2F;span&gt;&lt;span&gt;sleep (expected time - elapsed time) seconds
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is &lt;em&gt;better&lt;&#x2F;em&gt; but you&#x27;ll never &lt;em&gt;nail&lt;&#x2F;em&gt; the expected time.
It&#x27;ll either be too long or too short This means that either some amount of information is leaked, when &lt;code&gt;expected time&lt;&#x2F;code&gt; is too short, or the crypto is needlessly slow, which is just a silly compromise.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We &lt;em&gt;can&lt;&#x2F;em&gt; make it algorithmically secure without this &lt;code&gt;sleep&lt;&#x2F;code&gt; hack, so we &lt;em&gt;will&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practical-solutions-to-timing-attacks&quot;&gt;Practical Solutions to Timing Attacks&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re implementing crypto, STOP.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re implementing crypto and you know what you&#x27;re doing, your language of choice &lt;em&gt;probably&lt;&#x2F;em&gt; has a constant-time library which implements some primitives that you can take advantage of for simple tasks like comparisons. Those can be found at the end of this post in Errata. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#CTLibs&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After looking into constant-time-ifying your code, do some reading and testing!
There have been a lot of developments in analyzing program constant-time-ness and much of this work is Open Source!
These are implemented using a lot of Statistics&lt;sup&gt;TM&lt;&#x2F;sup&gt;, code inspection, and even Valgrind.[^8][^9]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
If you&#x27;re really concerned that &lt;em&gt;Your Crypto Library&lt;&#x2F;em&gt; isn&#x27;t secure against Remote Timing Attacks, take one of those tools on a test drive and see what happens.
It&#x27;s pretty likely that you&#x27;ll find a &lt;em&gt;notable&lt;&#x2F;em&gt; timing difference based on different inputs and you&#x27;ll probably need to make changes for your library to be secure against timing attacks.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s for the greater good. Because of your contributions the crypto community is even stronger.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-crazy-idea-constant-time-language-spec&quot;&gt;A crazy idea: constant time language spec&lt;&#x2F;h3&gt;
&lt;p&gt;My crazy idea, for my &lt;em&gt;very&lt;&#x2F;em&gt; hypothetical grad-school studies would be to implement a Constant-time &lt;em&gt;compiler&lt;&#x2F;em&gt; and&#x2F;or &lt;em&gt;language&lt;&#x2F;em&gt;.
This would perform transformations to your code in an attempt to make it constant-time or warning you when your code isn&#x27;t going to run in constant-time when it ought to.&lt;&#x2F;p&gt;
&lt;p&gt;Of course this would take a very long time, and honestly I haven&#x27;t thought it through entirely, but I imagine something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;regular code
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ct {
&lt;&#x2F;span&gt;&lt;span&gt;    thing that needs to be constant-time.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;regular code
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where you tell the compiler &quot;This needs to be constant-time&quot;.
The compiler does it&#x27;s best to convert loops and statements into constant-time and when it&#x27;s done it tells you if it was able to convert your code into constant-time execution or not.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s probably overkill; you don&#x27;t usually just willy-nilly write constant-time code.
That said, just like C and Python help produce less error prone code than writing straight Assembly, so too might a constant-time language help produce code that hits less of the tricky pitfalls of implementing Constant-time algorithms.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;constant-time-algorithm-example&quot;&gt;Constant-time Algorithm example&lt;&#x2F;h2&gt;
&lt;p&gt;Take our code block from the beginning, the one that did the leaky comparison.
That takes different amounts of time when processing a given key against a known private key.
How would we write &lt;em&gt;that&lt;&#x2F;em&gt; in constant-time?&lt;&#x2F;p&gt;
&lt;p&gt;Something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Short circuit based on user input, does not leak private information
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(recieved_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;KeyLengthError
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;recvied_bits  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;(recieved_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Taken to be constant-time
&lt;&#x2F;span&gt;&lt;span&gt;expected_bits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;(expected_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Taken to be constant-time
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Thing
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;recieved_bits[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span&gt;expected_bits[i]:
&lt;&#x2F;span&gt;&lt;span&gt;        ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;KeyLengthError &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# This sets the output, but the loop does not break
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;ret
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is similar to our original code but it does a few things differently:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We convert our keys to a variable which can be operated on bit-wise.&lt;&#x2F;li&gt;
&lt;li&gt;We manually compare each bit of the inputs. This is what the &lt;code&gt;==&lt;&#x2F;code&gt; operator does, but instead of returning when we get a difference we essentially set a switch. &lt;code&gt;ret = Error&lt;&#x2F;code&gt; from &lt;code&gt;ret = Thing&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Outside of the loop we return our response after processing all of our bits.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Behaviorally this is almost identical to our original code, but it does not return earlier or later depending on the user&#x27;s input.&lt;&#x2F;p&gt;
&lt;p&gt;Yet another implementation avoids the direct comparison:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Short circuit based on user input, does not leak private information
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(recieved_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;KeyLengthError
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;recvied_bits  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;(recieved_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Taken to be constant-time
&lt;&#x2F;span&gt;&lt;span&gt;expected_bits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;bits&lt;&#x2F;span&gt;&lt;span&gt;(expected_key) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Taken to be constant-time
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;matching_bits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;_ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    matching_bits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;xor&lt;&#x2F;span&gt;&lt;span&gt;(recieved_bits[i], expected_bits[i]))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;matching_bits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;PRIVATE_KEY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;thing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;KeyLengthError
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;remote-timing-attack-demo&quot;&gt;Remote Timing Attack demo&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Examples are fine, but what about a demo!
You said this was a real threat!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;True, I did say that... so we&#x27;ll do a small demonstration.&lt;&#x2F;p&gt;
&lt;p&gt;Below is a bit of Python code that checks a user&#x27;s input against some hard-coded secret.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# secret.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;time &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sleep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Used to exaggerate time difference.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;sys &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;argv   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Used to read user input.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;is_equal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Custom `==` operator&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Fail if the strings aren&amp;#39;t the right length
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(a) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(b):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;False
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(a)):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Short-circuit if the strings don&amp;#39;t match
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;a[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span&gt;b[i]:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;False
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0.15&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# This exaggerates it just enough for our purposes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Hard-coded secret globals FOR DEMONSTRATIONS ONLY
&lt;&#x2F;span&gt;&lt;span&gt;secret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;l33t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# This is python for &amp;quot;If someone uses you as a script, do this&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;__main__&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# The user got it right!
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;is_equal&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;(argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]), secret):
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;You got the secret!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# The user got it wrong
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Try again!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# The user forgot to enter a guess.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IndexError&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Usage: python secret.py yourguess&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;The secret may consist of characters in [a-z0-9] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;and is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt; characters long.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(secret)))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The thing that makes the above code particularly useful for our purposes is that it exaggerates the time it takes to evaluate the &lt;code&gt;is_equal&lt;&#x2F;code&gt; function.
Think of this as the &#x27;backpedaling&#x27; the CPU does... turned up to 11. Most important &lt;em&gt;for the author&lt;&#x2F;em&gt; we don&#x27;t need to use Statistics&lt;sup&gt;TM&lt;&#x2F;sup&gt; to figure the secret, evaluating each input multiple times and collecting&#x2F;processing that timing data, it already takes about one magnitude longer to evaluate a matching letter than it does to evaluate a non-matching letter.&lt;&#x2F;p&gt;
&lt;p&gt;Next we&#x27;ve got the attack code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# attack.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;time &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;time &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Used to get a timing difference.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;ascii_lowercase &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# All lowercase characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;digits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# All digits as strings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;subprocess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;call &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# used to exec a secret.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;os &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;devnull  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Suppress output of secret.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;current     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;aaaa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Initial guess
&lt;&#x2F;span&gt;&lt;span&gt;characters  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ascii_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;digits &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# All possible characters in the secret
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# We know the string is the same length as our initial guess
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(current)):
&lt;&#x2F;span&gt;&lt;span&gt;    guess_times &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Keep track of execution times
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;characters:
&lt;&#x2F;span&gt;&lt;span&gt;        current[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Swap the current letter with the current guess
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Uncomment the following line for fun debug output
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# print(&amp;#39;Making guess {}&amp;#39;.format(&amp;#39;&amp;#39;.join(current)))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Execute `secret.py` and time it
&lt;&#x2F;span&gt;&lt;span&gt;        start &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;call&lt;&#x2F;span&gt;&lt;span&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;python&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;secret.py&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(current)], &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(devnull, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;wb&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;        end   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Add that time to the list
&lt;&#x2F;span&gt;&lt;span&gt;        guess_times.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(end&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;start)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Uncomment the following line for fun debug output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# print(&amp;#39;max {} min {}&amp;#39;.format(max(guess_times), min(guess_times)))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# This is a hackey-looking way of getting the outlier time.
&lt;&#x2F;span&gt;&lt;span&gt;    current[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;characters[guess_times.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;(guess_times))]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(i, current[i]))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Uncomment the following line for fun debug output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# print(guess_times.index(max(guess_times)))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Final guess is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(current)))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s a bit convoluted in parts but if you stare at it for a while and read the enlightening comments you should see why this gets the right answer.&lt;&#x2F;p&gt;
&lt;p&gt;I encourage you to copy that code into two files, &lt;code&gt;secret.py&lt;&#x2F;code&gt; and &lt;code&gt;attack.py&lt;&#x2F;code&gt; and run it like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ time python attack.py
&lt;&#x2F;span&gt;&lt;span&gt;character 0 is l
&lt;&#x2F;span&gt;&lt;span&gt;character 1 is 3
&lt;&#x2F;span&gt;&lt;span&gt;character 2 is 3
&lt;&#x2F;span&gt;&lt;span&gt;character 3 is t
&lt;&#x2F;span&gt;&lt;span&gt;Final guess is l33t
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;real  0m35.176s
&lt;&#x2F;span&gt;&lt;span&gt;user  0m1.300s
&lt;&#x2F;span&gt;&lt;span&gt;sys 0m0.485s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$ python secret.py l33t
&lt;&#x2F;span&gt;&lt;span&gt;You got the secret!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll need a working Python installation and probably a shell of some kind.
I&#x27;m on CentOS Linux but any *nix system will &lt;em&gt;probably&lt;&#x2F;em&gt; work.
With some fiddling you can probably get it to work on Windows ;-)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This isn&#x27;t a real threat! You exaggerated the problem!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Hush now.
It demonstrates the principles of the attack.
Besides, the post is over.
We&#x27;ve only got time for the conclusion and then you&#x27;re off to bed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;constant-time-blogpost&quot;&gt;Constant-time blogpost&lt;&#x2F;h2&gt;
&lt;p&gt;This topic has been a break from the theory&#x2F;math-heavy term thus far.
Honestly I&#x27;m jazzed about it.&lt;&#x2F;p&gt;
&lt;p&gt;We learned that something as small as a comparison (a &lt;em&gt;comparison&lt;&#x2F;em&gt;!) can leak information to an adversary.
Your algorithm might be secure, but if you&#x27;re not careful you can leak information in the most menial code.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t a lost cause.
We don&#x27;t need to throw this &lt;em&gt;security&lt;&#x2F;em&gt; thing out the window.
If we&#x27;re aware of the gotchas we can craft code that solves these problems.
It&#x27;s hard work but the peace of mind should make it worth it.&lt;&#x2F;p&gt;
&lt;p&gt;Learning about this seemingly obscure (&lt;em&gt;terrifying&lt;&#x2F;em&gt;) exploit in algorithmically secure code is just the kind of headache I enjoy in Computer Science.
Although I don&#x27;t feel like I did Remote Timing Attacks justice, I could probably spend weeks on it, I had to call it quits.
I could keep working on this for &lt;em&gt;another 10 weeks&lt;&#x2F;em&gt;, but it&#x27;s over.
Just walk away.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;annotated-bibliography&quot;&gt;Annotated Bibliography&lt;&#x2F;h2&gt;
&lt;p&gt;BearSSL[^11]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#12&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: BearSSL is a project which aims to make an architecture-independent constant-time implementation of various Crypto Libraries, largely mirroring compatibility with OpenSSL and related Open Source crypro libraries.
Not only is the project interesting but a handful of blogposts and analysis are posted on the website covering topics like how to implement RSA in constant-time to the compatibility of various CPU models with assumptions about constant-time operations (e.g., multiplication).&lt;&#x2F;p&gt;
&lt;p&gt;Remote Timing Attacks are Practical&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#13&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: This paper was very easy to read for an academic article and covered the creation of various timing attacks in practical conditions (e.g., hacking an RSA private key across a network).&lt;&#x2F;p&gt;
&lt;p&gt;Beginner focused blogs[^14]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#15&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: These were two blogposts which laid out what timing attack, why they were viable, and how you can avoid them.
Protip: never assume a library you&#x27;re using is constant-time.&lt;&#x2F;p&gt;
&lt;p&gt;Adam Langley&#x27;s blog[^16]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#17&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: Adam Langley has great Intermediate-level blogposts about the Lucky13 attack and analyzing code for constant-time execution.
These aren&#x27;t for the weak of heart, but are much more accessible than a lot of academic articles on similar topics.&lt;&#x2F;p&gt;
&lt;p&gt;CryptoCoding.net Coding Rules&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#18&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: This wiki outlines some common pitfalls when writing constant-time code and how to avoid it.
It assumes you&#x27;re writing C code, but many of the principles carry to more exotic languages.&lt;&#x2F;p&gt;
&lt;p&gt;Constant Time Testing Papers[^19]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#20&quot;&gt;15&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
: These academic papers outline tools developed for studying how constant-time a program is and analyzes various programs with these tools.
They&#x27;re a great (surprisingly recent) survey of this topic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;CTLibs&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;crypto&#x2F;subtle&#x2F;&quot;&gt;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;crypto&#x2F;subtle&#x2F;&lt;&#x2F;a&gt; -
&lt;a href=&quot;https:&#x2F;&#x2F;cryptography.io&#x2F;en&#x2F;latest&#x2F;hazmat&#x2F;primitives&#x2F;constant-time&#x2F;&quot;&gt;https:&#x2F;&#x2F;cryptography.io&#x2F;en&#x2F;latest&#x2F;hazmat&#x2F;primitives&#x2F;constant-time&#x2F;&lt;&#x2F;a&gt; -
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;isislovecruft&#x2F;subtle&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;isislovecruft&#x2F;subtle&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Remote Timing Attacks are Pratical; David Brumley, Dan Boneh;
&lt;a href=&quot;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&quot;&gt;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Remote Timing Attacks are Pratical; David Brumley, Dan Boneh;
&lt;a href=&quot;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&quot;&gt;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Chosen Plaintext: A beginner&#x27;s guide to contant-time cryptography;
&lt;a href=&quot;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&quot;&gt;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;As Sonic the Hedgehog always says, Gotta Go Fast!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;BearSSL: Constant Time Multiplication
&lt;a href=&quot;https:&#x2F;&#x2F;bearssl.org&#x2F;ctmul.html&quot;&gt;https:&#x2F;&#x2F;bearssl.org&#x2F;ctmul.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Cryptography Coding Standards: Coding rules;
&lt;a href=&quot;https:&#x2F;&#x2F;cryptocoding.net&#x2F;index.php&#x2F;Coding_rules&quot;&gt;https:&#x2F;&#x2F;cryptocoding.net&#x2F;index.php&#x2F;Coding_rules&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Chosen Plaintext: A beginner&#x27;s guide to contant-time cryptography;
&lt;a href=&quot;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&quot;&gt;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;16&lt;&#x2F;sup&gt;
&lt;p&gt;Dude, is my code constant-time? Oscar Reparaz, josep Balasch,
Ingrid Vebauwhede; &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;1123.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;1123.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;17&lt;&#x2F;sup&gt;
&lt;p&gt;Veryfying Constnat-Time Implementations, via Usenix;
&lt;a href=&quot;http:&#x2F;&#x2F;haslab.uminho.pt&#x2F;jba&#x2F;files&#x2F;16usenix.pdf&quot;&gt;http:&#x2F;&#x2F;haslab.uminho.pt&#x2F;jba&#x2F;files&#x2F;16usenix.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;Lucky Thirteen attack on TLS CBC Adam langley via ImperialViolet;
&lt;a href=&quot;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&quot;&gt;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;11&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;18&lt;&#x2F;sup&gt;
&lt;p&gt;BearSSL: Constant Time Multiplication
&lt;a href=&quot;https:&#x2F;&#x2F;bearssl.org&#x2F;ctmul.html&quot;&gt;https:&#x2F;&#x2F;bearssl.org&#x2F;ctmul.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;12&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;BearSSL: Why Consant-Time Crypto?
&lt;a href=&quot;https:&#x2F;&#x2F;bearssl.org&#x2F;constanttime.html&quot;&gt;https:&#x2F;&#x2F;bearssl.org&#x2F;constanttime.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;13&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;Remote Timing Attacks are Pratical; David Brumley, Dan Boneh;
&lt;a href=&quot;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&quot;&gt;http:&#x2F;&#x2F;crypto.stanford.edu&#x2F;~dabo&#x2F;pubs&#x2F;papers&#x2F;ssl-timing.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;14&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;19&lt;&#x2F;sup&gt;
&lt;p&gt;Chosen Plaintext: A beginner&#x27;s guide to contant-time
cryptography;
&lt;a href=&quot;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&quot;&gt;https:&#x2F;&#x2F;www.chosenplaintext.ca&#x2F;articles&#x2F;beginners-guide-constant-time-cryptography.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;15&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;A Lesson In Timing Attacks (or, Don&#x27;t use
&lt;code&gt;MessageDigest.isEquals&lt;&#x2F;code&gt;); Coda Hale;
&lt;a href=&quot;https:&#x2F;&#x2F;codahale.com&#x2F;a-lesson-in-timing-attacks&#x2F;&quot;&gt;https:&#x2F;&#x2F;codahale.com&#x2F;a-lesson-in-timing-attacks&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;16&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;20&lt;&#x2F;sup&gt;
&lt;p&gt;Checking that functions are constant-time with Valgrind; Adam
langley via ImperialViolet;
&lt;a href=&quot;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2010&#x2F;04&#x2F;01&#x2F;ctgrind.html&quot;&gt;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2010&#x2F;04&#x2F;01&#x2F;ctgrind.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;17&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;13&lt;&#x2F;sup&gt;
&lt;p&gt;Lucky Thirteen attack on TLS CBC Adam langley via ImperialViolet;
&lt;a href=&quot;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&quot;&gt;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;18&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;14&lt;&#x2F;sup&gt;
&lt;p&gt;Cryptography Coding Standards: Coding rules;
&lt;a href=&quot;https:&#x2F;&#x2F;cryptocoding.net&#x2F;index.php&#x2F;Coding_rules&quot;&gt;https:&#x2F;&#x2F;cryptocoding.net&#x2F;index.php&#x2F;Coding_rules&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;19&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;21&lt;&#x2F;sup&gt;
&lt;p&gt;Veryfying Constnat-Time Implementations, via Usenix;
&lt;a href=&quot;http:&#x2F;&#x2F;haslab.uminho.pt&#x2F;jba&#x2F;files&#x2F;16usenix.pdf&quot;&gt;http:&#x2F;&#x2F;haslab.uminho.pt&#x2F;jba&#x2F;files&#x2F;16usenix.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;20&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;15&lt;&#x2F;sup&gt;
&lt;p&gt;Dude, is my code constant-time? Oscar Reparaz, josep Balasch,
Ingrid Vebauwhede; &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;1123.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;1123.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Memory Hard Functions</title>
        <published>2017-10-17T00:00:00+00:00</published>
        <updated>2017-10-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/memory-hard-functions/"/>
        <id>https://elijah.run/blog/memory-hard-functions/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/memory-hard-functions/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent
Study on cryptography at Oregon State University. To read all of the
posts, check out the &#x27;Independent Crypto&#x27; tag.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h2 id=&quot;problem-storing-passwords-is-hard&quot;&gt;Problem: storing passwords is hard&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;re a system administrator and -- oh no! A hacker stole your database!&lt;&#x2F;p&gt;
&lt;p&gt;Well, not yet... but they &lt;em&gt;could&lt;&#x2F;em&gt;.
Once you get popular enough it&#x27;s bound to happen.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Can you make sure your users data is safe &lt;strong&gt;when&lt;&#x2F;strong&gt; that happens?&lt;&#x2F;p&gt;
&lt;p&gt;When you store passwords in a database you never store them in plain text.
Instead, you store a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hash_function&quot;&gt;hash&lt;&#x2F;a&gt; of that password.
For example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Password: 12345678
&lt;&#x2F;span&gt;&lt;span&gt;sha256sum (hash): 2634c3097f98e36865f0c572009c4ffd73316bc8b88ccfe8d196af35f46e2394
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The hash is generated when the user tries to login.
The &lt;em&gt;hash&lt;&#x2F;em&gt; of the password the user sends at login is compared against the corresponding password hash for that user.
If it matches that means the user sent the right password and so they are authenticated.&lt;&#x2F;p&gt;
&lt;p&gt;What happens if the hacker pre-computes a bunch of popular passwords?
This might sound crazy, but there are lots of people that re-use passwords, like &lt;code&gt;123456&lt;&#x2F;code&gt;.
The hacker can pre-compute the hash for the 1,000,000 most popular passwords and more or less reverse-search for any user&#x27;s password once they have a database dump.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-1-add-salt&quot;&gt;Solution 1: add salt&lt;&#x2F;h2&gt;
&lt;p&gt;Our first naive solution to solve this problem is to make the adversary&#x27;s life harder by adding &lt;em&gt;salt&lt;&#x2F;em&gt; to our passwords.
This is a piece of known information which is added to the password so adversaries can&#x27;t pre-compute a hash-table, they have to compute this after they have the database and figure out the salt.
For example:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Password: 12345678
&lt;&#x2F;span&gt;&lt;span&gt;Salt: cryptoHeckYeah!
&lt;&#x2F;span&gt;&lt;span&gt;New Password: 12345678cryptoHeckYeah!
&lt;&#x2F;span&gt;&lt;span&gt;sha256sum: 6e8a7780df48a0b687e9e272e8d082f5f4c0c3a8c43b63461c3f62618b111e9d
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately we live in 2017 and Graphics processors and &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Application-specific_integrated_circuit&quot;&gt;ASICs&lt;&#x2F;a&gt; are cheap and can compute sha256sums &lt;strong&gt;super fast&lt;&#x2F;strong&gt; for &lt;strong&gt;really cheap&lt;&#x2F;strong&gt;.
This means that it might be more of a pain, but the adversary can still crack a password with relative ease and efficiency because they&#x27;ve got a computer &lt;em&gt;designed&lt;&#x2F;em&gt; to generate lots of hashes.
Curses.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-2-h-h-h-x&quot;&gt;Solution 2: H(H(..H(x)..)&lt;&#x2F;h2&gt;
&lt;p&gt;Computing a single sha256sum is easy, but what if the hacker had to compute like... 1000 sha256sums for each password!
That sounds pretty hard... right?
If we compute the hash of the hash of the hash (etc) it would take like... 1000x longer to compute each user&#x27;s password.
Something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;p = &amp;#39;12345678cryptoHeckYeah!&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;for x in 1..1000
&lt;&#x2F;span&gt;&lt;span&gt;  p = sha256sum( p )
&lt;&#x2F;span&gt;&lt;span&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;return p
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Result: 47c76630def739ede9c05fd974065b1200d4712aa2421eefb1f6b241a1ca6bea
&lt;&#x2F;span&gt;&lt;span&gt;Time: 0m1.547s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately this hurts more than it helps.&lt;&#x2F;p&gt;
&lt;p&gt;In bash on non-specialized hardware, this took about 1.6 seconds.
On specialized hardware, written in a systems programming language, and implemented in parallel it&#x27;d be much less costly for an adversary to crack passwords hashed this way.&lt;&#x2F;p&gt;
&lt;p&gt;Worst of all, this is &lt;em&gt;easier for an adversary to compute than it is for the the &quot;good guys&quot;&lt;&#x2F;em&gt; because the non-malicious actor is using generalized hardware and the adversary is using specialized hardware to compute the hashes.
It&#x27;s like trying to beat a Roadster in a drag race when you&#x27;re behind the wheel of a Minivan; the Minivan (&quot;good guys&quot;) &lt;em&gt;can&#x27;t win&lt;&#x2F;em&gt; because they weren&#x27;t built for drag races.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-3-memory-hard-functions&quot;&gt;Solution 3: Memory Hard Functions&lt;&#x2F;h2&gt;
&lt;p&gt;The big problem we have is that CPUs can be specialized to crack passwords &lt;em&gt;very quickly&lt;&#x2F;em&gt;.
No matter how fast your AWS EC2 instance is, or even that top of the line IBM server you just bought, it will &lt;em&gt;never&lt;&#x2F;em&gt; be faster than a cheap custom designed ASIC.
At around 3000$&#x2F;box it won&#x27;t break the adversary&#x27;s bank to break into yours.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While there specialized hash-cracking CPUs &lt;strong&gt;do&lt;&#x2F;strong&gt; exist, specialized hash-cracking &lt;em&gt;memory&lt;&#x2F;em&gt; does &lt;strong&gt;not&lt;&#x2F;strong&gt; exist.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
If we were to create an algorithm which depends on lots of memory, instead of lots of CPU cycles, we could &quot;level the playing field&quot;.
This should help stop adversaries from reversing passwords as fast as they currently can.&lt;&#x2F;p&gt;
&lt;p&gt;This theoretical hash-function is called a Memory Hard Function (MHF).
These are difficult to perform unless you have a certain threshold of memory.
As a result non-malicious actors can perform a hash in M seconds and it will take a malicious actor &lt;em&gt;at least&lt;&#x2F;em&gt; M seconds to perform the same hash.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;TLDR: We want a hash function that takes as long for an adversary to
compute as it does for the &quot;good guys&quot; to compute. Since nobody has
specialized hash-cracking RAM we should be able to create a hash
function which is memory-intensive and fits our criteria. If we have a
function that fits this we will have got a &lt;em&gt;Memory hard Function&lt;&#x2F;em&gt; (MHF).&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h2 id=&quot;scrypt-a-wild-mhf&quot;&gt;scrypt: a wild MHF&lt;&#x2F;h2&gt;
&lt;p&gt;scrpyt is a key derivation function &lt;a href=&quot;http:&#x2F;&#x2F;www.tarsnap.com&#x2F;scrypt.html&quot;&gt;developed for the Tarsnap project&lt;&#x2F;a&gt;.
It was designed explicitly to solve this problem and has some pretty impressive results.
Some especially impressive results include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;scrypt is about 2&lt;sup&gt;5&lt;&#x2F;sup&gt; times more expensive to attack for logins than bcrypt.&lt;&#x2F;li&gt;
&lt;li&gt;scrypt is about 2&lt;sup&gt;15&lt;&#x2F;sup&gt; times more espensive to attack for logins than MD5 CRYPT.&lt;&#x2F;li&gt;
&lt;li&gt;scrypt is about 2&lt;sup&gt;37&lt;&#x2F;sup&gt; times more expensive to attack for file encryption than MD5.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;scrypt also happens to be a MHF.
Yay we found one!&lt;&#x2F;p&gt;
&lt;p&gt;So... how does it work?&lt;&#x2F;p&gt;
&lt;p&gt;Given a hash function H, an input B, and an integer N, compute:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;V&lt;sub&gt;i&lt;&#x2F;sub&gt; = H&lt;sup&gt;i&lt;&#x2F;sup&gt;(B), given 0 ≤ i &amp;lt; N,&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;and&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;X = H&lt;sup&gt;N&lt;&#x2F;sup&gt;(B)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;then iterate&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;j &amp;lt;- Integrify(X) mod N&lt;&#x2F;li&gt;
&lt;li&gt;X &amp;lt;- H(X ⊕ V&lt;sub&gt;j&lt;&#x2F;sub&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;N times; and output X&lt;&#x2F;p&gt;
&lt;p&gt;The function Integrify can be any bijection&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; from {0,1}&lt;sup&gt;k&lt;&#x2F;sup&gt;
to {0...2&lt;sup&gt;k&lt;&#x2F;sup&gt; - 1}.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Breaking that down a bit:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The function is given a different hash function (H), an input to compute the hash of (B), and a modulus (N).&lt;&#x2F;li&gt;
&lt;li&gt;N hashes are generated with variations of H and the input B called V&lt;sub&gt;0..N&lt;&#x2F;sub&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;X is initialized with a hash value and a loop begins:
&lt;ol&gt;
&lt;li&gt;j is set to a psuedo-random integer mod N.&lt;&#x2F;li&gt;
&lt;li&gt;X is set to the hash of the existing X value xor&#x27;d with one of the V values.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Loop N times and output the final X.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One of the biggest gripes with scrypt is that it has a very predictable runtime.
This means that the running of the function is predictable based on the user&#x27;s input and so can be victim to a cache-timing side-channel attack.
We won&#x27;t be able to get into what this attack means, but basically you can say &quot;scrypt is good, but not perfect&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-independent-mhfs-imhfs&quot;&gt;Data-independent MHFs (iMHFs)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;DAG.gif&quot; alt=&quot;A directed acyclic graph map.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;iMHFs are supposed to solve the problem that scrypt has (side-channel attacks) by have unpredictable runtimes which still result in the same output.&lt;&#x2F;p&gt;
&lt;p&gt;iMHFs can be thought of as Directed Acyclic Graphs (DAGs) which are traversed during runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Some specifics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The function depends on a random oracle H: {0,1}&lt;sup&gt;2k&lt;&#x2F;sup&gt; -&amp;gt; {0,1}&lt;sup&gt;k&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function provides a Directed Acyclic Graph Directed Acyclic Graph (DAG) G used to encode data-dependencies&lt;&#x2F;li&gt;
&lt;li&gt;The initial input is a password and a salt.&lt;&#x2F;li&gt;
&lt;li&gt;Each other node is labeled with the hash of it&#x27;s parent nodes.&lt;&#x2F;li&gt;
&lt;li&gt;The output is the hash of the value of the last node.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As mentioned before, a very nice feature of iMHFs is that their memory usage pattern does not depend on the user&#x27;s input (password) and so is not vulnerable to side-channel attacks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pebbling-a-directed-acyclic-graph-dag&quot;&gt;Pebbling a Directed Acyclic Graph (DAG)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;dag-animated.gif&quot; alt=&quot;A directed acyclic graph traversal.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can think of the process of computing the output of an iMHF as pebbling a graph where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Computing the value of a node is to pebble it.&lt;&#x2F;li&gt;
&lt;li&gt;There are rules about which nodes can be pebbled at any time.&lt;&#x2F;li&gt;
&lt;li&gt;When a pebble is removed from a node it is freed from memory.&lt;&#x2F;li&gt;
&lt;li&gt;Our goal is to pebble the last node.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Rules:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can only place a pebble on a node if we have pebbles on all of it&#x27;s parents nodes.&lt;&#x2F;li&gt;
&lt;li&gt;Our goal is to get to the sink node (exit node).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The naive pebbling algorithm, the one the &#x27;good guy&#x27; user would utilize is as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Only one pebble can be placed per time-step.&lt;&#x2F;li&gt;
&lt;li&gt;The graph is pebbled in in topological order.&lt;&#x2F;li&gt;
&lt;li&gt;Pebbles (calculated nodes) are never discarded until the end of the function.&lt;&#x2F;li&gt;
&lt;li&gt;Expected cost: scales with n&lt;sup&gt;2&lt;&#x2F;sup&gt; where n is the number of nodes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This does take up considerable resources, but it isn&#x27;t prohibitive for users on commodity hardware.
This means it won&#x27;t take &lt;em&gt;too long&lt;&#x2F;em&gt; to get your account authenticated.
More importantly, it will take about as long for the bad guys to calculate a token as it took you to calculate a token, as opposed to a small fraction it would take if this was a &quot;normal&quot; hash function.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attacks-on-imhfs&quot;&gt;Attacks on iMHFs&lt;&#x2F;h2&gt;
&lt;p&gt;An attack is defined as when cost of calculating a hash from an iMHF is lower than via the nieve approach.&lt;&#x2F;p&gt;
&lt;p&gt;The general idea of an iMHF attack is that it has two phases: light phase and balloon phase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;light-phase&quot;&gt;Light Phase&lt;&#x2F;h3&gt;
&lt;p&gt;In the light phase the algorithm races through the DAG discarding as many pebbles as possible, essentially performing a breadth first search for the end of the graph, computing nodes in parallel when possible.
Once a node is computed and it isn&#x27;t immediately needed it is discarded.&lt;&#x2F;p&gt;
&lt;p&gt;If the DAG were a straight line from beginning to end this would be fairly memory efficient.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;balloon-phase&quot;&gt;Balloon Phase&lt;&#x2F;h3&gt;
&lt;p&gt;In the balloon phase the algorithm has &#x27;hit a wall&#x27; and back-computes the nodes it needs to compute the next node whose parent&#x27;s have already been discarded.
This causes a slow-down.&lt;&#x2F;p&gt;
&lt;p&gt;An attack described like this has the following complexity:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;E&lt;sub&gt;R&lt;&#x2F;sub&gt;(A) = O(en + √(n&lt;sup&gt;3&lt;&#x2F;sup&gt;d))&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For small values of e and d this results in an attack as:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;E&lt;sub&gt;R&lt;&#x2F;sub&gt;(A) = O(n&lt;sup&gt;2&lt;&#x2F;sup&gt;) for e,d = O(n)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Preventing against this type of attack is where much of the research into iMHF&#x27;s is focused.
An ideal iMHF DAG minimize the disparity between the attackers compute time and the &quot;good guy&#x27;s&quot; compute time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This has been a rough overview of Memory Hard functions, how they work, and how variations of MHFs differ.&lt;&#x2F;p&gt;
&lt;p&gt;MHFs are functions which remove the advantage that adversaries have to crack passwords by depending heavily on memory.
This reduces the adversary&#x27;s advantage if they have an ASIC or GPU processor(s) to brute-force a password crack and ought to make it very difficult (ideally &lt;em&gt;impractical&lt;&#x2F;em&gt;) for adversaries to crack a password hashed with an MHF.&lt;&#x2F;p&gt;
&lt;p&gt;Some existing MHFs, like scrypt, are vulnerable to side-channel attacks so iMHFs have been theorized which do not have a predictable runtime and so are not vulnerable to side-channel attacks.
No iMHFs exist yet, however many functions have been developed with get &lt;em&gt;close&lt;&#x2F;em&gt; and offer many of the benefits of iMFHs.
Some of these include Argon2i, Catena, and Balloon hashing, which we did not cover in this post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;annotated-bibliography&quot;&gt;Annotated Bibliography&lt;&#x2F;h2&gt;
&lt;p&gt;Conference Presentations by Jeremiah Blocki[^5][^6]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; The video presentations online by Jeremiah were a very important resource for getting a grasp on what MHFs are, and more specifically what iMHFS and how they worked.
The three videos cited in this post cover largely the same content and present the material, including the problem, naive solution, MHF solution, iMFH solution, and possible attacks against iMHFs in about 30 minutes.
I like to think I&#x27;m pretty good at public speaking, but this material was very complicated and presented in a very digestible format.&lt;&#x2F;p&gt;
&lt;p&gt;I cannot stress enough how useful these videos were.
I learned an incredible amount from these videos and referenced them for the majority of this content.&lt;&#x2F;p&gt;
&lt;p&gt;Strict Memory Hard Hashing Functions&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This paper was very short and presented some essential knowledge to discuss the differences between MHFs and iMHFs.
I didn&#x27;t directly use or reference this content, however it did present an easily understandable academic definition and comparison of iMHF compared to MHFs.&lt;&#x2F;p&gt;
&lt;p&gt;Practical Graphs for Optimal Side-Channel Resistant Memory-Hard Functions&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This paper was used in the writing of this post, however it was very long and dense, so it was never directly cited.&lt;&#x2F;p&gt;
&lt;p&gt;scrypt: A new key derivation function&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This was the soul reference for the scrypt section of this post.
There is an academic paper published too, but the slides were simple and presented all of the same knowledge (I think) sans any proofs.&lt;&#x2F;p&gt;
&lt;p&gt;If I feel an existential hole in my heart I might read the proofs, but in the interest of time I chose not to right now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;haveibeenpwned.com&#x2F;PwnedWebsites&quot;&gt;https:&#x2F;&#x2F;haveibeenpwned.com&#x2F;PwnedWebsites&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Antminer &quot;Bitcoin Miner&quot; &lt;a href=&quot;http:&#x2F;&#x2F;a.co&#x2F;2E20HW8&quot;&gt;http:&#x2F;&#x2F;a.co&#x2F;2E20HW8&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Yet.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Bijection: A function which creates a 1-to-1 relationship between inputs and outputs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;Efficiently Computing Data Independent Memory Hard Functions (Video) Joël Alwen and Jeremiah Blocki, Crypto 2016, September 26, 2016, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ujpvPtn_N5Y&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;ujpvPtn_N5Y&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Towards a Theory of Data-Independent Memory Hard Functions (Video), Jeremiah Blocki with Joel Alwen, Krzysztof Pietrzak 2017, Real World Crypto conference, February 1, 2017, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;YtfVLzUkwME&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;YtfVLzUkwME&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Memory Hard Functions and Password Hashings (Video), CERIAS Symposium 2017 - TechTalk, Jeremiah M. Blocki - Assistant Professor, Computer Science - Purdue University, May 1, 2017, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;9yX4v89m5oo&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;9yX4v89m5oo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Strict Memory Hard Hashing Functions, Sergio Demian Lerner, (Preliminary v0.3, 01-19-14), &lt;a href=&quot;http:&#x2F;&#x2F;www.hashcash.org&#x2F;papers&#x2F;memohash.pdf&quot;&gt;http:&#x2F;&#x2F;www.hashcash.org&#x2F;papers&#x2F;memohash.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Practical Graphs for Optimal Side-Channel Resistant Memory-Hard Functions Joel Alwen, Jeremiah Blocki, Ben Harsha IACR Cryptography ePrint Archive, 2017, &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2017&#x2F;443.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2017&#x2F;443.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;scrypt: A new key derivation function (variable subtitles) Colin Percival, May 9, 2009, &lt;a href=&quot;http:&#x2F;&#x2F;www.tarsnap.com&#x2F;scrypt&#x2F;scrypt-slides.pdf&quot;&gt;http:&#x2F;&#x2F;www.tarsnap.com&#x2F;scrypt&#x2F;scrypt-slides.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Garbled Circuits</title>
        <published>2017-10-10T00:00:00+00:00</published>
        <updated>2017-10-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/garbled-circuits/"/>
        <id>https://elijah.run/blog/garbled-circuits/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/garbled-circuits/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent Study on cryptography at Oregon State University.
To read all of the posts, check out the &#x27;Independent Crypto&#x27; tag.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Let&#x27;s imagine you are a billionaire.
You want to know if you have more money than your billionaire friend Bob, but for some reason it&#x27;s &lt;em&gt;very&lt;&#x2F;em&gt; faux pas to let anybody know how much money you have, even your good friend Bob.&lt;&#x2F;p&gt;
&lt;p&gt;But you&#x27;re a billionaire!
You&#x27;re not used to the phrase &quot;that isn&#x27;t possible&quot;.
In your frustration you try to figure out if you can use some of your billions to find a solution.&lt;&#x2F;p&gt;
&lt;p&gt;The first solution you come up with is Trusty Tina.
You tell Tina how much you make, Bob tells Tina how much he makes, and then Tina tells both of you who makes more.&lt;&#x2F;p&gt;
&lt;p&gt;The only problem is that Tina isn&#x27;t &lt;em&gt;that&lt;&#x2F;em&gt; trustworthy, her parent&#x27;s just named her that.
Like... you wouldn&#x27;t trust her with your life or anything.
You could pay her to keep your assets secret but Bob might pay her a bit more reveal your number to him.
Tina reminds you of this so you have to pay her &lt;em&gt;more&lt;&#x2F;em&gt; to keep the secret, and eventually you have an arms-race type situation at hand.
With your cunning accountant skills you can already tell that Tina might be more trouble than she&#x27;s worth.&lt;&#x2F;p&gt;
&lt;p&gt;If you won&#x27;t tell Bob directly, and you can&#x27;t depend on Manipulative Tina, is there &lt;em&gt;any&lt;&#x2F;em&gt; way to determine out who has more money?&lt;&#x2F;p&gt;
&lt;p&gt;Yes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-party-secure-function-evaluation&quot;&gt;2-Party Secure Function Evaluation&lt;&#x2F;h2&gt;
&lt;p&gt;The problem above is the Millionaires problem&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and it is solved by the use of 2-party secure function evaluation (SFE).
The general idea&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; is that you have a function &lt;code&gt;f&lt;&#x2F;code&gt; which takes as input &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt;.
This function is garbled by one of the two parties into &lt;code&gt;f&#x27;&lt;&#x2F;code&gt; and the inputs are garbled into &lt;code&gt;x&#x27;&lt;&#x2F;code&gt; and &lt;code&gt;y&#x27;&lt;&#x2F;code&gt; by each of the parties.
&lt;code&gt;f&#x27;(x&#x27;, y&#x27;) == f(x,y)&lt;&#x2F;code&gt; but does not leak any of the inputs, because &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; were obfuscated.&lt;&#x2F;p&gt;
&lt;p&gt;In other words...&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice and Bob agree on a function (i.e., circuit) &lt;code&gt;f(a,b)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice garbles the function (&lt;em&gt;cough&lt;&#x2F;em&gt; circuit) &lt;code&gt;f&lt;&#x2F;code&gt; and her input &lt;code&gt;a&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice sends &lt;code&gt;f&#x27;&lt;&#x2F;code&gt; and &lt;code&gt;a&#x27;&lt;&#x2F;code&gt; to Bob.&lt;&#x2F;li&gt;
&lt;li&gt;Bob gets his input &lt;code&gt;b&lt;&#x2F;code&gt; garbled into &lt;code&gt;b&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Bob evaluates &lt;code&gt;f&#x27;(a&#x27;, b&#x27;)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;This reveals the result of &lt;code&gt;f(a,b)&lt;&#x2F;code&gt; to Bob, but does not reveal
Alice&#x27;s input.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;The first half of this post focuses on honest garbled circuit uses,
meaning both parties are acting honestly (and don&#x27;t pull any fast-ones).&lt;&#x2F;p&gt;
&lt;p&gt;The latter portion focuses on problems with that &#x27;vanilla&#x27; garbled
circuit implementation and potential solutions.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h2 id=&quot;garbling-a-gate&quot;&gt;Garbling a gate&lt;&#x2F;h2&gt;
&lt;p&gt;How does Alice actually... &#x27;garble&#x27; a circuit?
It sounds kinda dirty.&lt;&#x2F;p&gt;
&lt;p&gt;Each gate (OR, AND, XOR, etc) has two inputs.
Stick with me.
Each input is encrypted.
Keeping up?
So you need a &lt;em&gt;key&lt;&#x2F;em&gt; to use &lt;em&gt;each gate&lt;&#x2F;em&gt;.
It gets better.
But if you have the keys, you don&#x27;t know which key corresponds with a &lt;code&gt;1&lt;&#x2F;code&gt; or a &lt;code&gt;0&lt;&#x2F;code&gt; so you can compute a function without knowing the actual values you put in.
Whoa.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s use the OR gate as an example.&lt;&#x2F;p&gt;
&lt;p&gt;Remember truth-tables for OR? Here&#x27;s a reminder:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;OR&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;0&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;0&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This table is going to be important for Alice&#x27;s part of this dance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alice-s-circuit-input&quot;&gt;Alice&#x27;s circuit &amp;amp; input&lt;&#x2F;h3&gt;
&lt;p&gt;Alice definitely does the heavy lifting in this transaction.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice generates 4 keys &lt;code&gt;Kx0&lt;&#x2F;code&gt;, &lt;code&gt;Kx1&lt;&#x2F;code&gt;, &lt;code&gt;Ky0&lt;&#x2F;code&gt;, and &lt;code&gt;Ky1&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice creates four variables corresponding with the four values in the OR table:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;OR&lt;&#x2F;th&gt;&lt;th&gt;0&lt;&#x2F;th&gt;&lt;th&gt;1&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;0&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;B00&lt;&#x2F;code&gt; = 0&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;B01&lt;&#x2F;code&gt; = 1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;B10&lt;&#x2F;code&gt; = 1&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;B11&lt;&#x2F;code&gt; = 1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Each box is encrypted with the two keys:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;OR&lt;&#x2F;th&gt;&lt;th&gt;0&lt;&#x2F;th&gt;&lt;th&gt;1&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;0&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;`E(Kx0&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;`E(Kx1&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Alice sends these ciphertexts (unordered) to Bob.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;bob-s-input&quot;&gt;Bob&#x27;s input&lt;&#x2F;h3&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Bob gets Alice&#x27;s input, key &lt;code&gt;KxA&lt;&#x2F;code&gt;, from Alice.&lt;&#x2F;li&gt;
&lt;li&gt;Bob uses oblivious transfer&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to get his input &lt;code&gt;KyB&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;With these two keys Bob is able to process the circuit (an OR gate).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Bob has enough information to get one of the four possible outputs of the circuit, but doesn&#x27;t know if Alice&#x27;s input is a 1 or a 0.&lt;&#x2F;p&gt;
&lt;p&gt;Importantly, while Bob can share the output of the circuit, he should &lt;strong&gt;not&lt;&#x2F;strong&gt; share his input. That would make using OT (step 6) obtuse.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;extending-the-garbled-gate&quot;&gt;Extending the garbled gate&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;garbled-circuit.jpg&quot; alt=&quot;Garbled circuit example diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;The UTF-8 Padlock symbol doesn&#x27;t render on my browser because I seem to
have gone back in the time to the late 90s. Being stuck in the past, we
have to comprmise. The ⛨ symbol is meant to represent a lock and the ⚿
represents a key.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Multiple gates can be connected together to build more complicated
circuits. One important difference is that while each intermediate
circuit still has four cipher-texts, for the four outcomes of a
truth-table, those decrypt to a &lt;em&gt;key&lt;&#x2F;em&gt; and not a 1 or 0. The only gates
which decrypt to a plain-text of 0 or 1 are output gates, not the
intermediate gates.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;&lt;em&gt;PSST&lt;&#x2F;em&gt; Check out the end of this post for a &lt;strong&gt;GAME&lt;&#x2F;strong&gt;!&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h2 id=&quot;problems-with-garbled-circuits&quot;&gt;Problems with garbled circuits&lt;&#x2F;h2&gt;
&lt;p&gt;There are a few important flaws in the &lt;em&gt;security&lt;&#x2F;em&gt; of garbled circuits as
they have been described. The first is that although Alice and Bob agree
on a circuit to garble there is no guarantee that the circuit one is
evaluating (if you&#x27;re Bob) is the circuit you agreed upon.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice and Bob &#x27;agree&#x27; on a function &lt;code&gt;f(a,b)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice creates her own function &lt;code&gt;g(a,b)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice garbles &lt;code&gt;g&lt;&#x2F;code&gt; and her input &lt;code&gt;a&lt;&#x2F;code&gt; and sends it to Bob as &lt;code&gt;f&#x27;&lt;&#x2F;code&gt; and &lt;code&gt;a&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Bob evaluates &lt;code&gt;g&#x27;(a&#x27;,b&#x27;)&lt;&#x2F;code&gt; and reveals the output to Alice.
Alice now knows something other than than Bob agreed to.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;improvements-on-garbled-circuit-security&quot;&gt;Improvements on garbled circuit security&lt;&#x2F;h2&gt;
&lt;p&gt;To prevent the above adversarial attack we do something called &quot;Cut-and-Choose&quot;.
This is when Bob checks Alice&#x27;s work to make sure she&#x27;s not cheating.&lt;&#x2F;p&gt;
&lt;p&gt;Remember that Alice and Bob agreed on a given circuit.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice generates M garbled circuits for the agreed upon function where M &amp;gt; 1.&lt;&#x2F;li&gt;
&lt;li&gt;All secrets for a randomly chosen N circuits are revealed where 1 ≤ N &amp;lt; M, the circuits are &quot;opened&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Bob selects one of the remaining M-N circuits to evaluate as outlined earlier.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This ensures that Alice is not nefarious to some statistical certainty.
She had control over how the circuits were garbled but she does not have control over which are revealed or evaluated.
If she made one (or two or three...) nefarious circuits that bad behavior is &lt;em&gt;probably&lt;&#x2F;em&gt; revealed in step 2, if all the checked circuits are good Alice is &lt;em&gt;probably&lt;&#x2F;em&gt; being honest.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn&#x27;t break garbled circuits for the following reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;While Alice reveals the secrets of the N circuits, she doesn&#x27;t reveal anything about her input.
We are only un-garbling the circuit not the inputs (revealing all possible inputs, not Alice&#x27;s).&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re not un-garbling the M-N circuits which may be evaluated, so those are still secret.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As M grows and N approaches M this method gets more secure at the cost of computation cycles and bandwidth in transferring the garbled circuits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-free-xor-optimization&quot;&gt;The &quot;Free XOR&quot; Optimization&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m definitely not a circuits person.
You can show me a circuit diagram and I&#x27;ll say
&quot;Yep, that&#x27;s a circuit. What&#x27;s it do?&quot;
I couldn&#x27;t even even identify which gate is which without Wikipedia.&lt;&#x2F;p&gt;
&lt;p&gt;I was told during my research for this post that XOR gates are very popular with garbled circuit design, and more broadly circuit design in
general.
This was shared to me in the form of a cryptic hint so I figured I&#x27;d investigate and share my findings here.&lt;&#x2F;p&gt;
&lt;p&gt;As it turns out the Wikipedia page notes that this XOR optimization exists and even cites the original paper published on the topic.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The jist of this optimization is that one can very efficiently garble an XOR gate such that the output of the gate is encoded as the XOR of the keys used to unlock the gate and some known global constant.
This is in contrast with the implementations discussed in the beginning where each gate had to be decrypted with two cipher-texts and revealed another key.&lt;&#x2F;p&gt;
&lt;p&gt;Basically using XOR, which is pretty fast, we can avoid generating four keys per gate and instead craft 1 key which is produced as the result of &#x27;unlocking&#x27; a gate.&lt;&#x2F;p&gt;
&lt;p&gt;Put a bit more formally:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given a gate G with input wires A and B and output wire C and a random string R, the garbled gate is obtained by XORing the garbled gates inputs C&lt;sup&gt;1&lt;&#x2F;sup&gt; = C&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;C&lt;sup&gt;0&lt;&#x2F;sup&gt; = A&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ B&lt;sup&gt;0&lt;&#x2F;sup&gt; = (A&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R ) ⊕ (B&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R) = A&lt;sup&gt;1&lt;&#x2F;sup&gt; ⊕ B&lt;sup&gt;1&lt;&#x2F;sup&gt;
C&lt;sup&gt;1&lt;&#x2F;sup&gt; = C&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R = A&lt;sup&gt;0&lt;&#x2F;sup&gt; (B&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R) = A&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ B&lt;sup&gt;1&lt;&#x2F;sup&gt; = (A&lt;sup&gt;0&lt;&#x2F;sup&gt; ⊕ R) ⊕ B&lt;sup&gt;0&lt;&#x2F;sup&gt; = A&lt;sup&gt;1&lt;&#x2F;sup&gt; ⊕ B&lt;sup&gt;0&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;LETTER&lt;sup&gt;{0,1}&lt;&#x2F;sup&gt; is short-hand for the True or False output of the
given gate.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;This isn&#x27;t super intuitive, and honestly I just put those equations up there to prove that I read a paper about this.&lt;&#x2F;p&gt;
&lt;p&gt;The main takeaway is that &#x27;free XOR&#x27; saves us computation generating and processing cryptographic keys by simply performing the XOR operation.
This optimization is so powerful that using &lt;em&gt;mostly&lt;&#x2F;em&gt; XOR gates makes garbled circuits notably faster and more useful for secure computation.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;annotated-bibliography&quot;&gt;Annotated Bibliography&lt;&#x2F;h2&gt;
&lt;p&gt;Foundations of Garbled Circuits&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; This is by far the most thorough academic source I have.
If I had a better foundation in academic reading this might be the perfect paper but most of it went way over my head.
That said the overview of each section was fairly human-readable and gave me a good rough overview for many of the topics covered in this post.&lt;&#x2F;p&gt;
&lt;p&gt;A Brief History of Practical Garbled Circuits&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; This was the first source I checked out to get a feel for how difficult garbled circuits are as a topic.
It quickly glanced at the basics of garbled circuits and then quickly went into the optimizations on garbled circuits.
This was overwhelming, but as I started to learn more about garbled circuits and filled in the knowledge gaps it gained significant value.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a great talk about Garbled Circuits which wasn&#x27;t ideal for beginners, but did give me a good breadth of the topic and what I could dive into.&lt;&#x2F;p&gt;
&lt;p&gt;Improved garbled Circuit: Free XOR Gates and Applications&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This paper was useful in giving me an academic preview of the XOR optimization in Garbled Circuits.
I quickly started looking at the many other papers referenced by this one, kind of like following down the Wikipedia wormhole, but with more PDFs and less pictures.&lt;&#x2F;p&gt;
&lt;p&gt;SFE: Yao&#x27;s Garbled Circuit&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This slide-deck was very useful as a reference for basic GCs and securing GC&#x27;s with cut-and-choose.
It wasn&#x27;t a great initial source for this material, but it was useful &lt;em&gt;after&lt;&#x2F;em&gt; I had a basic understanding of a topic to solidify it with pretty pictures and Comic Sans.&lt;&#x2F;p&gt;
&lt;p&gt;Mike Rosulek on Stack Exchange[^10]&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#11&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This is more of a shout-out than a citation.
Mike Rosulek&#x27;s posts on crypto.stackexchange.com were very helpful in breaking down core concepts like what garbled circuits are and why XOR is &quot;free&quot;.
They also provided a good list of further reading which was helpful in addition to the resources provided in the syllabus.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;iframe src=&quot;&#x2F;garbled-circuits-game.html&quot; height=&quot;400px&quot; width=&quot;100%&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;Yes, the name is a misnomer. The goal is to &lt;em&gt;evaluate&lt;&#x2F;em&gt; a garbled
circuit, but that just doesn&#x27;t roll off the tongue the same.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The original problem was developed in the 80&#x27;s.
This post adjusts the scenario for inflation.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;To completely level with you, it&#x27;s been anecdotally proven that there is at least 1 definition of Garbled Circuits for each paper on the topic.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Oblivious Transfer has been described to me as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Alice sends two possible options to a box labeled OT.&lt;&#x2F;li&gt;
&lt;li&gt;Bob sends a choice to the box labeled OT.&lt;&#x2F;li&gt;
&lt;li&gt;Bob gets back one of the two options, without knowledge of the
other.&lt;&#x2F;li&gt;
&lt;li&gt;Alice does not know which option Bob got.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is a cryptographic primitive which is very useful for tasks like generating Bob&#x27;s input to the garbled circuit &lt;code&gt;f&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Improved garbled Circuit: Free XOR Gates and Applications, Written by Vladimir Kolesnikov and Thomas Shneider, Published July 2008. &lt;a href=&quot;http:&#x2F;&#x2F;www.cs.toronto.edu&#x2F;~vlad&#x2F;papers&#x2F;XOR_ICALP08.pdf&quot;&gt;http:&#x2F;&#x2F;www.cs.toronto.edu&#x2F;~vlad&#x2F;papers&#x2F;XOR_ICALP08.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;A Brief History of Practical Garbled Circuit Optimizations, Presented by Mike Rosulek, Published by the Simons Institute, June 15, 2015. &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Foundations of Garbled Circuits, Written by Mihir Bellare, Viet tung Hoang, and Phillip Rogaway, Published October, 2012. &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2012&#x2F;265.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2012&#x2F;265.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;A Brief History of Practical Garbled Circuit Optimizations, Presented by Mike Rosulek, Published by the Simons Institute, June 15, 2015. &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;Improved garbled Circuit: Free XOR Gates and Applications, Written by Vladimir Kolesnikov and Thomas Shneider, Published July 2008. &lt;a href=&quot;http:&#x2F;&#x2F;www.cs.toronto.edu&#x2F;~vlad&#x2F;papers&#x2F;XOR_ICALP08.pdf&quot;&gt;http:&#x2F;&#x2F;www.cs.toronto.edu&#x2F;~vlad&#x2F;papers&#x2F;XOR_ICALP08.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;SFE: Yao&#x27;s Garbled Circuit, Published by engr.illinois.edu, for the course CS 598, Fall 2009. &lt;a href=&quot;https:&#x2F;&#x2F;courses.engr.illinois.edu&#x2F;cs598man&#x2F;fa2009&#x2F;slides&#x2F;ac-f09-lect16-yao.pdf&quot;&gt;https:&#x2F;&#x2F;courses.engr.illinois.edu&#x2F;cs598man&#x2F;fa2009&#x2F;slides&#x2F;ac-f09-lect16-yao.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;What exactly is a &quot;garbled circuit&quot;? Asked by user Ella Rose, Answered by user Mikero on on July 27, 2016. &lt;a href=&quot;https:&#x2F;&#x2F;crypto.stackexchange.com&#x2F;a&#x2F;37993&quot;&gt;https:&#x2F;&#x2F;crypto.stackexchange.com&#x2F;a&#x2F;37993&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;11&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Why XOR and NOT is free in garbled circuits Asked by user Jason, Answered by user Mikero on February 28, 2017. &lt;a href=&quot;https:&#x2F;&#x2F;crypto.stackexchange.com&#x2F;a&#x2F;44278&quot;&gt;https:&#x2F;&#x2F;crypto.stackexchange.com&#x2F;a&#x2F;44278&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Elliptic Curve Cryptography</title>
        <published>2017-10-04T00:00:00+00:00</published>
        <updated>2017-10-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/elliptic-curve-cryptography/"/>
        <id>https://elijah.run/blog/elliptic-curve-cryptography/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/elliptic-curve-cryptography/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent
Study on cryptography at Oregon State University. To read all of the
posts, check out the &#x27;Independent Crypto&#x27; tag.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;div class=&quot;warning&quot;&gt;
    &lt;span class=&quot;warning-title&quot;&gt;
        Warning
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;warning-body&quot;&gt;
        &lt;p&gt;This post is jumps around a bit. We&#x27;ll start by showing how Elliptic
Curve Cryptography works at a high level, then create a list of
questions about how&#x2F;why Elliptic Curve Cryptography works and how it is
useful to cryptogrpahy. Once those questions are answered we will end
with a recap. Hopefully we will zero in on what Elliptic Curves are and
what Elliptic Curve Cryptography is.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;diffie-hellman-key-exchange&quot;&gt;Diffie-Hellman key exchange ++&lt;&#x2F;h2&gt;
&lt;p&gt;You find yourself day-dreaming during a walk around campus wondering if there is an alternative cryptography system to the very popular RSA.
You want something that has improved computational and network efficiency.
You want smaller keys that are harder to crack.
Could such a system exist?&lt;&#x2F;p&gt;
&lt;p&gt;You share this fantasy with a friend, you share all of your crypto fantasies with this friend, and they tell you that Elliptic Curve Cryptography is promising and it perfectly fits your needs.
... but how does it work?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;diffie-hellman-key-exchange-a-recap&quot;&gt;Diffie-Hellman key exchange (a recap)&lt;&#x2F;h3&gt;
&lt;p&gt;To create a useful crypto out of Elliptic Curves we need to implement &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Diffie%E2%80%93Hellman_key_exchange&quot;&gt;Diffie–Hellman key exchange&lt;&#x2F;a&gt; (DHKE).
Once we have DHKE we more or less have a valid crypto system which we can build upon to encrypt and decrypt private information.&lt;&#x2F;p&gt;
&lt;p&gt;The reader (you) is assumed to be familiar with DHKE.
While DHKE is fairly simple, it is not unforgettable, so here is quick reminder:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice and Bob agree on a public modulus (p) and a base (g).&lt;&#x2F;li&gt;
&lt;li&gt;Alice and Bob both choose secret integers (a and b).&lt;&#x2F;li&gt;
&lt;li&gt;Alice sends Bob g&lt;sup&gt;a&lt;&#x2F;sup&gt; (mod p) (we call it A) and Bob sends Alice g&lt;sup&gt;b&lt;&#x2F;sup&gt; (mod p) (we call it B).&lt;&#x2F;li&gt;
&lt;li&gt;Alice computes B&lt;sup&gt;a&lt;&#x2F;sup&gt; (mod p) and Bob computes A&lt;sup&gt;b&lt;&#x2F;sup&gt; (mod p).
These are equivalent (mod p).
This is Alice and Bob&#x27;s shared secret.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;How do we use Elliptic Curves get a similar &#x27;shared secret&#x27;?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;elliptic-diffie-hellman-key-exchange&quot;&gt;Elliptic Diffie-Hellman key exchange&lt;&#x2F;h3&gt;
&lt;p&gt;At a (very) high level the algorithm is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Alice and Bob agree to use a given Elliptic Curve over a finite field, E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;), and a public point P ∈ E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Alice chooses a secret integer n&lt;sub&gt;A&lt;&#x2F;sub&gt; and Bob choose secret integers n&lt;sub&gt;B&lt;&#x2F;sub&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alice computes Q&lt;sub&gt;A&lt;&#x2F;sub&gt; = n&lt;sub&gt;A&lt;&#x2F;sub&gt;P and Bob computes Q&lt;sub&gt;B&lt;&#x2F;sub&gt; = n&lt;sub&gt;B&lt;&#x2F;sub&gt;P.
These are the &quot;Public Keys&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Alice sends Bob her public key, Bob send Alice his public key.&lt;&#x2F;li&gt;
&lt;li&gt;Alice computes n&lt;sub&gt;A&lt;&#x2F;sub&gt;Q&lt;sub&gt;B&lt;&#x2F;sub&gt;, Bob computes n&lt;sub&gt;B&lt;&#x2F;sub&gt;Q&lt;sub&gt;A&lt;&#x2F;sub&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The shared secret value is n&lt;sub&gt;A&lt;&#x2F;sub&gt;Q&lt;sub&gt;B&lt;&#x2F;sub&gt; = n&lt;sub&gt;A&lt;&#x2F;sub&gt;(n&lt;sub&gt;B&lt;&#x2F;sub&gt;P) = n&lt;sub&gt;B&lt;&#x2F;sub&gt;(n&lt;sub&gt;A&lt;&#x2F;sub&gt;P) = n&lt;sub&gt;B&lt;&#x2F;sub&gt;Q&lt;sub&gt;A&lt;&#x2F;sub&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It looks similar to the given DHKE algorithm, and seems promising, but... how does it work?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;elliptic-curves-and-elliptic-curve-cryptography-q-a&quot;&gt;Elliptic Curves and Elliptic Curve Cryptography Q&amp;amp;A&lt;&#x2F;h2&gt;
&lt;p&gt;To answer that we are going to answer the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What are Elliptic Curves?&lt;&#x2F;li&gt;
&lt;li&gt;What does an Elliptic Curve look like?&lt;&#x2F;li&gt;
&lt;li&gt;What does it mean to multiply P by n?&lt;&#x2F;li&gt;
&lt;li&gt;What about a finite field?&lt;&#x2F;li&gt;
&lt;li&gt;How are the pubic keys used? Why are these a shared secret?&lt;&#x2F;li&gt;
&lt;li&gt;Why is Elliptic Curve Cryptography useful?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;what-are-elliptic-curves&quot;&gt;What are Elliptic Curves?&lt;&#x2F;h3&gt;
&lt;p&gt;A Elliptic Curve is the set of solutions to an equation of the form&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;y&lt;sup&gt;2&lt;&#x2F;sup&gt; = x&lt;sup&gt;3&lt;&#x2F;sup&gt; + AX + B&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;what-does-an-elliptic-curve-look-like&quot;&gt;What does an Elliptic Curve look like?&lt;&#x2F;h3&gt;
&lt;p&gt;Two examples of Elliptic Curves are as follows:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-1.png&quot; alt=&quot;A simple elliptic curve&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;and:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-2.png&quot; alt=&quot;Another simple elliptic curve&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adding-p-and-q&quot;&gt;Adding P and Q&lt;&#x2F;h3&gt;
&lt;p&gt;Multiplication is &lt;em&gt;just&lt;&#x2F;em&gt; repeated addition.
Oh shoot we haven&#x27;t said how &quot;addition&quot; happens on an Elliptic Curve. Let&#x27;s do that.&lt;&#x2F;p&gt;
&lt;p&gt;Addition is the process of drawing a line L between P and Q.
The third point that the line L intersects is point R. When R is reflected over the X axis we call this R&#x27;.
The result of P ⊕ Q (read: P &#x27;plus&#x27; Q) is R&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;We can enumerate these steps as:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Take two points P and Q on the Elliptic Curve E.&lt;&#x2F;li&gt;
&lt;li&gt;Draw a line L which passes through these two points.&lt;&#x2F;li&gt;
&lt;li&gt;L should ultimately pass through &lt;em&gt;three&lt;&#x2F;em&gt; points: P, Q, and R.&lt;&#x2F;li&gt;
&lt;li&gt;Multiply the Y coordinate of R by -1, this is R&#x27;.&lt;&#x2F;li&gt;
&lt;li&gt;P ⊕ Q = R&#x27;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here&#x27;s a visualization of straight forward addition.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-3.png&quot; alt=&quot;Annotated curve E with points P, Q, R, R&amp;#39; and line L labeled.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You might think &quot;What happens when P is tangent a point on E?&quot; In that
case we say P = Q, so R = P ⊕ P, or R = 2P. It looks like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-4.png&quot; alt=&quot;Annotated curve E with points P, R, R&amp;#39; and line L labeled. P is tangent to the curve.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Wait a second, 2P looks like n*P which was one of the questions we had!
Don&#x27;t worry, we&#x27;ll get there soon.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;that-thing-about-finite-fields&quot;&gt;That thing about Finite Fields&lt;&#x2F;h3&gt;
&lt;p&gt;In practice we bound the curve over a field F&lt;sub&gt;p&lt;&#x2F;sub&gt; with p ≥ 3.
We input {1, 2, ..., p-1} as the value of X in E and select the results which are squares modulo 13.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;E : y&lt;sup&gt;2&lt;&#x2F;sup&gt; = x&lt;sup&gt;3&lt;&#x2F;sup&gt; + 3X + 8 over F&lt;sub&gt;13&lt;&#x2F;sub&gt;
X = 1
1 + 3 + 8 = 12
12 is a square (mod 13)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Repeating this gives us the set of points in E(F&lt;sub&gt;13&lt;&#x2F;sub&gt;):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;E(F&lt;sub&gt;13&lt;&#x2F;sub&gt;) = {O, (1,5), (1,8), (2,3), (2,10), (9,6), (9,7),
(12,2), (12,11)}&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In practice this bounds the graph of E and forces us to draw a strange modulus graph shown below:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;independent-crypto&#x2F;ecc-5.gif&quot; alt=&quot;Elliptic Curves illustrated where each point is a valid coordinate. There are no curves.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Image source: A (relatively easy to understand) primer on elliptic curve cryptography&lt;&#x2F;em&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multiplying-p-by-an-integer-with-the-double-and-add-algorithm&quot;&gt;Multiplying P by an integer with The Double-and-Add Algorithm&lt;&#x2F;h3&gt;
&lt;p&gt;To &quot;multiply&quot; P by n we need to use the Double-and-Add Algorithm.
Here&#x27;s how that looks:&lt;&#x2F;p&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;Take a point P ∈ E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;) and an integer n ≥ 1.&lt;&#x2F;li&gt;
&lt;li&gt;Set Q = P and R = O.&lt;&#x2F;li&gt;
&lt;li&gt;Loop while n &amp;gt; 0.
3.  If n ≡ 1 (mod 2), set R = R + Q
4.  Set Q = 2Q and n = floor(n&#x2F;2).&lt;&#x2F;li&gt;
&lt;li&gt;Return the point R, which equals nP.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;em&gt;Recall that the algorithm for finding point 2Q was covered in the above section&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;elliptic-curve-cryptography&#x2F;#adding-p-and-q&quot;&gt;Adding P and Q&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-is-the-shared-secret&quot;&gt;What &lt;em&gt;is&lt;&#x2F;em&gt; the shared secret?&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s review.
The shared secret is the second point n&lt;sub&gt;A&lt;&#x2F;sub&gt;n&lt;sub&gt;B&lt;&#x2F;sub&gt;P, which is a point on the public curve E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;).
This point can be used to encrypt information as it is a shared secret (necessary for DHKE).
How exactly it is used to encrypt information is left as an exercise for readers in charge of cryptographic implementation standards.&lt;&#x2F;p&gt;
&lt;p&gt;The reason this is a shared secret is because an adversary needs to solve the following Elliptic Curve Discrete Logarithm Problem&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;nP = Q&lt;sub&gt;A&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Which is a very hard problem, as mentioned in the next section.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-example-of-elliptic-curve-cryptography&quot;&gt;An example of Elliptic Curve Cryptography&lt;&#x2F;h2&gt;
&lt;p&gt;This sounds good in theory, but let&#x27;s give it a test drive.&lt;&#x2F;p&gt;
&lt;p&gt;Alice and Bob are given the following shared information:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;p = 3851, E: y&lt;sup&gt;2&lt;&#x2F;sup&gt; = x&lt;sup&gt;3&lt;&#x2F;sup&gt; + 324X + 1287, P = (920, 303) ∈ E(F&lt;sub&gt;3851&lt;&#x2F;sub&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Alice and Bob choose their secret integers:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;n&lt;sub&gt;A&lt;&#x2F;sub&gt; = 1194
n&lt;sub&gt;B&lt;&#x2F;sub&gt; = 1759&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Alice and Bob then compute their public keys:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Alice computes Q&lt;sub&gt;A&lt;&#x2F;sub&gt; = 1194P = (2067, 2178) ∈ E(F&lt;sub&gt;3851&lt;&#x2F;sub&gt;)
Bob computes Q&lt;sub&gt;B&lt;&#x2F;sub&gt; = 1759P = (3684, 3125) ∈ E(F&lt;sub&gt;3851&lt;&#x2F;sub&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;Remember that we use the Double-and-Add algorithm to compute
Q&lt;sub&gt;A&lt;&#x2F;sub&gt; and Q&lt;sub&gt;B&lt;&#x2F;sub&gt;. This invloves iteratively computing the
tangent line at a point, the intersection with E at that intersection,
and reflecting that point over the X axis.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Alice and Bob trade public keys and calculate their shared secret:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Alice computes n&lt;sub&gt;A&lt;&#x2F;sub&gt;Q&lt;sub&gt;B&lt;&#x2F;sub&gt; = 1194(3684, 3125) = (3347, 1242) ∈ E(F&lt;sub&gt;3851&lt;&#x2F;sub&gt;)
Bob computes n&lt;sub&gt;B&lt;&#x2F;sub&gt;Q&lt;sub&gt;A&lt;&#x2F;sub&gt; = 1759(2067, 2178) = (3347, 1242) ∈ E(F&lt;sub&gt;3851&lt;&#x2F;sub&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Therefore (3347, 1242) is the shared secret.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-elliptic-curve-cryptography-is-useful&quot;&gt;Why Elliptic Curve Cryptography is useful&lt;&#x2F;h2&gt;
&lt;p&gt;While it is harder than simply multiplying mod p for Alice to compute her shared secret (which is the case in RSA), it is &lt;em&gt;even harder&lt;&#x2F;em&gt; for a
malicious actor to figure out that same shared secret.
This point is best put by the source &lt;em&gt;A (relatively easy to understand) primer on elliptic curve cryptography&lt;&#x2F;em&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can compute how much energy is needed to break a cryptographic algorithm and compare that with how much water that energy could boil.
This is a kind of a cryptographic carbon footprint. By this measure, breaking a 228-bit RSA key requires less energy than it takes to boil a teaspoon of water.
Comparatively, breaking a 228-bit elliptic curve &amp;gt; key requires enough energy to boil all the water on earth.
For this &amp;gt; level of security with RSA, you&#x27;d need a key with 2,380 bits.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So an Elliptic Curve Cryptography key can be one magnitude smaller in size and offer the same level of security as RSA.&lt;&#x2F;p&gt;
&lt;p&gt;We can put this in more concrete terms: the fastest algorithm to solve the Elliptic Curve Discrete Logarithm Problem, which Elliptic DHKE security is built upon, in E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;) takes √p steps.
This is much more difficult than the &#x27;vanilla&#x27; Discrete Logarithm Problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;notes-and-edge-cases&quot;&gt;Notes and edge cases&lt;&#x2F;h2&gt;
&lt;p&gt;Elliptic Curve Cryptography, much like the rest of Cryptography, deals heavily with &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Number_theory&quot;&gt;Number Theory&lt;&#x2F;a&gt;.
Despite my best efforts most of the nitty-gritty Number Theory in this topic went &lt;em&gt;way&lt;&#x2F;em&gt; over my head.
As a result I didn&#x27;t include much of that kind of stuff and instead focused on the things I &lt;em&gt;could&lt;&#x2F;em&gt; share and sound smart about.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some other things about Elliptic Curve Cryptography I didn&#x27;t cover that deserve more air time:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Elliptic Curve chosen must meet a special set of criteria; any old Elliptic Curve won&#x27;t do.
This was the cause of a cryptographic breach with Elliptic Curve Cryptography a few years ago that triggered doubts about Elliptic Curve Cryptography as a whole.&lt;&#x2F;li&gt;
&lt;li&gt;Some primes cause solving the Elliptic Curve Discrete Logarithm Problem for E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;) to be easier than the Discrete Logarithm Problem, these primes can be computed and should be avoided.&lt;&#x2F;li&gt;
&lt;li&gt;If you want a deeper understanding of the theory of Elliptic Curves (addition of points on these curves, etc) you should look into &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Algebraic_geometry&quot;&gt;algebraic geometry&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;annotated-bibliography&quot;&gt;Annotated Bibliography&lt;&#x2F;h2&gt;
&lt;p&gt;An Introduction to Mathematical Cryptography&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; The chapter in this textbook on Elliptic Curves in Cryptography established the bedrock understanding of the topic of Elliptic Curve Cryptography.
This ended up being the main resource for this post and offered a great median between &quot;Regular Joe&#x27;s guide to Elliptic Curve Cryptography&quot; and &quot;The graduate student&#x27;s guide to Elliptic Curve Cryptography&quot; which were my other two resources.
It was also the source of all examples, which were very useful in gaining an intuitive understanding of the material.&lt;&#x2F;p&gt;
&lt;p&gt;A (relatively easy to understand) primer on elliptic curve cryptography&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; This blog post was my &lt;em&gt;second&lt;&#x2F;em&gt; source and did a good job of taking the proofs and dense material in Intro to Math Cyrpto (above) and boiled it down to the important stuff.
It drastically improved further readings of the original textbook and provided that great animated image of adding P ⊕ Q in E(F&lt;sub&gt;p&lt;&#x2F;sub&gt;). It didn&#x27;t cover any of the Number Theory, but explained the historical context of Elliptic Curve Cryptography, roughly how&#x2F;why it works, and did a good job of describing it&#x27;s impact in our world today.&lt;&#x2F;p&gt;
&lt;p&gt;Cryptography: An Introduction&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
This wasn&#x27;t a resource I actually &lt;em&gt;used&lt;&#x2F;em&gt;, but I did read the chapter on Elliptic Curve Cryptography (chapter 2!).
It gave me an appreciation for the previous two sources and some exposure to the other ways Elliptic Curves can be taught.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;A (relatively easy to understand) primer on elliptic curve cryptography, October 24, 2013, Nick Sullivan, Cloudflare blog, reposted on Ars Technica, &lt;a href=&quot;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&quot;&gt;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;A (relatively easy to understand) primer on elliptic curve cryptography, October 24, 2013, Nick Sullivan, Cloudflare blog, reposted on Ars Technica, &lt;a href=&quot;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&quot;&gt;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;An Introduction to Mathematical Cryptography, 2008, Jeffery Hoffstein, Jill Pipher, Joseph H. Silverman, Springer Publishing, ISBN 978-0-387-77993-5&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;A (relatively easy to understand) primer on elliptic curve cryptography, October 24, 2013, Nick Sullivan, Cloudflare blog, reposted on Ars Technica, &lt;a href=&quot;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&quot;&gt;https:&#x2F;&#x2F;arstechnica.com&#x2F;information-technology&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Cryptography: An Introduction (Third Edition), May 19, 2016, Nigel Smart, &lt;a href=&quot;https:&#x2F;&#x2F;www.cs.umd.edu&#x2F;~waa&#x2F;414-F11&#x2F;IntroToCrypto.pdf&quot;&gt;https:&#x2F;&#x2F;www.cs.umd.edu&#x2F;~waa&#x2F;414-F11&#x2F;IntroToCrypto.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Independent Crypto Course syllabus</title>
        <published>2017-07-10T00:00:00+00:00</published>
        <updated>2017-07-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/independent-crypto/"/>
        <id>https://elijah.run/blog/independent-crypto/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/independent-crypto/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This is a part of a series of blog posts I wrote for an Independent Study on cryptography at Oregon State University.
To read all of the posts, check out the &#x27;Independent Crypto&#x27; tag.
{% end() %}&lt;&#x2F;p&gt;
&lt;p&gt;{% warning() %}
This syllabus was written by an Oregon State University undergraduate student and not by an Oregon State University staff member.
This should explain any irregularities in the structure and substance of the document.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;The purpose of this course (&quot;Independent Crypto&quot;) is to give students an opportunity to dive deeper into interesting topics of Cryptography.&lt;&#x2F;p&gt;
&lt;p&gt;By the end of this course you should &lt;em&gt;grok&lt;&#x2F;em&gt; the following topics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Elliptic curve cryptography&lt;&#x2F;li&gt;
&lt;li&gt;Memory hard functions&lt;&#x2F;li&gt;
&lt;li&gt;Garbled circuits&lt;&#x2F;li&gt;
&lt;li&gt;An topic of your choosing (get creative!)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each of these should take about 40 hours of work to complete.
An overview of what that means is outlined below.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This course is designed to be a 4 credit hour independent study.&lt;&#x2F;p&gt;
&lt;p&gt;As is standard Oregon State University policy, this corresponds with 160
hours of work over a 10 week period.
Plan accordingly.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Each topic ought to take about 40 hours of work to complete over the course of a 10 week term.
If you schedule your time well this will be a piece of cake at just 16 hours per week.
That&#x27;s 2.28 hours per day, 3.2 hours per week-day, or 16 hours the day before your check-in is due!&lt;&#x2F;p&gt;
&lt;p&gt;The basic structure is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Research a topic.
Read papers, watch informative videos, ask questions and learn as much as you can about a given topic.&lt;&#x2F;li&gt;
&lt;li&gt;Maintain an &lt;em&gt;annotated bibliography&lt;&#x2F;em&gt;.
This should include materials found while studying a given topic, a summary of each of the materials, and a final summary of the topic as a whole.&lt;&#x2F;li&gt;
&lt;li&gt;Meet weekly with the mentoring professor.&lt;&#x2F;li&gt;
&lt;li&gt;Repeat.&lt;&#x2F;li&gt;
&lt;li&gt;???&lt;&#x2F;li&gt;
&lt;li&gt;Profit.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The end goal, in addition to learning about a breadth of topics in modern security, is to produce an annotated bibliography.
This will exercise the student&#x27;s ability to read and process academic topics, journals, and videos.&lt;&#x2F;p&gt;
&lt;p&gt;Of course if you are particularly passionate about a topic you are encouraged to go further: implementing things of interest, investigating new questions, and generally &#x27;digging deeper&#x27; as you gain interest in different topics.&lt;&#x2F;p&gt;
&lt;p&gt;The following topics do not &lt;em&gt;need&lt;&#x2F;em&gt; to be completed in order, however doing so will result in an optimal &#x27;difficulty curve&#x27; as the kids say.
The kids do still say that right?&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;Included are a few resources grabbed in a quick internet search.
These are meant to be starting places for each topic, generating questions and providing external resources.
You will need to find additional resources for each topic.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;h2 id=&quot;elliptic-curve-cryptography&quot;&gt;Elliptic Curve Cryptography&lt;&#x2F;h2&gt;
&lt;p&gt;Weeks 0-2 will be dedicated to Elliptic Curve Cryptography.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kickoff-resources&quot;&gt;Kickoff Resources&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;A (relatively easy to understand) primer on Elliptic Curve Cryptography: &lt;a href=&quot;https:&#x2F;&#x2F;arstechnica.com&#x2F;security&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&quot;&gt;https:&#x2F;&#x2F;arstechnica.com&#x2F;security&#x2F;2013&#x2F;10&#x2F;a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Elliptic Curve Cryptography in Practice: &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2013&#x2F;734.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2013&#x2F;734.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Elliptic Curve Cryptography, a gentle introduction: &lt;a href=&quot;http:&#x2F;&#x2F;andrea.corbellini.name&#x2F;2015&#x2F;05&#x2F;17&#x2F;elliptic-curve-cryptography-a-gentle-introduction&#x2F;&quot;&gt;http:&#x2F;&#x2F;andrea.corbellini.name&#x2F;2015&#x2F;05&#x2F;17&#x2F;elliptic-curve-cryptography-a-gentle-introduction&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;kickoff-questions&quot;&gt;Kickoff Questions&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;What are elliptic curves?&lt;&#x2F;li&gt;
&lt;li&gt;How do elliptic curves relate to cryptography?&lt;&#x2F;li&gt;
&lt;li&gt;How are Elliptic Curve Cryptography functions different from similar ones like RSA?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;memory-hard-functions&quot;&gt;Memory-hard functions&lt;&#x2F;h2&gt;
&lt;p&gt;Weeks 3 and 4 of the course should be dedicated to the topic of Memory Hard Functions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kickoff-resources-1&quot;&gt;Kickoff Resources&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Memory-hard functions and tradeoff cryptanalysis with applications to password hashing, cryptocurrencies, and white-box cryptography: &lt;a href=&quot;https:&#x2F;&#x2F;www.cryptolux.org&#x2F;images&#x2F;d&#x2F;d1&#x2F;Tradeoff-slides.pdf&quot;&gt;https:&#x2F;&#x2F;www.cryptolux.org&#x2F;images&#x2F;d&#x2F;d1&#x2F;Tradeoff-slides.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Strict Memory Hard Hashing Functions: &lt;a href=&quot;http:&#x2F;&#x2F;www.hashcash.org&#x2F;papers&#x2F;memohash.pdf&quot;&gt;http:&#x2F;&#x2F;www.hashcash.org&#x2F;papers&#x2F;memohash.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;kickoff-questions-1&quot;&gt;Kickoff Questions&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;What are Memory-hard functions?&lt;&#x2F;li&gt;
&lt;li&gt;What purposes are Memory-hard functions used for?&lt;&#x2F;li&gt;
&lt;li&gt;What are some examples of Memory-hard functions and how do they work?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;garbled-circuits&quot;&gt;Garbled circuits&lt;&#x2F;h2&gt;
&lt;p&gt;Weeks 5-7 should be dedicated to garbled circuits.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kickoff-resources-2&quot;&gt;Kickoff Resources&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Garbled Circuits: &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;TxCu1L_tzlU&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;TxCu1L_tzlU&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Foundations of Garbled Circuits: &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2012&#x2F;265.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2012&#x2F;265.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Faster Secure Two-Party Computation Using Garbled Circuits: &lt;a href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;legacy&#x2F;event&#x2F;sec11&#x2F;tech&#x2F;full_papers&#x2F;Huang.pdf&quot;&gt;https:&#x2F;&#x2F;www.usenix.org&#x2F;legacy&#x2F;event&#x2F;sec11&#x2F;tech&#x2F;full_papers&#x2F;Huang.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;SFE: Yao’s Garbled Circuit: &lt;a href=&quot;https:&#x2F;&#x2F;courses.engr.illinois.edu&#x2F;cs598man&#x2F;fa2009&#x2F;slides&#x2F;ac-f09-lect16-yao.pdf&quot;&gt;https:&#x2F;&#x2F;courses.engr.illinois.edu&#x2F;cs598man&#x2F;fa2009&#x2F;slides&#x2F;ac-f09-lect16-yao.pdf&lt;&#x2F;a&gt; (bonus points if you find the talk for these slides).&lt;&#x2F;li&gt;
&lt;li&gt;Garbled Circuts, Cryptowiki, &lt;a href=&quot;http:&#x2F;&#x2F;cryptowiki.net&#x2F;index.php?title=Garbled_circuits&quot;&gt;http:&#x2F;&#x2F;cryptowiki.net&#x2F;index.php?title=Garbled_circuits&lt;&#x2F;a&gt; (probably don&#x27;t cite this one in a paper)&lt;&#x2F;li&gt;
&lt;li&gt;Amortizing Garbled Circuits: &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2015&#x2F;081.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2015&#x2F;081.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;independent-study&quot;&gt;Independent study&lt;&#x2F;h2&gt;
&lt;p&gt;In the last seven or so weeks you&#x27;ve learned a lot.
You&#x27;ve read papers, watch informative lectures, and had insightful conversations with peers and mentors.
Many of these probably sparked your attention in a particular topic.
Use these last few weeks to investigate one of those sparks that you&#x27;ve been itching to learn more about.&lt;&#x2F;p&gt;
&lt;p&gt;If you truly feel uninspired you can use this time to learn about Private Set Intersection.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kickoff-resources-for-private-set-intersection&quot;&gt;Kickoff Resources for Private Set Intersection&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;BIU Winter School on Cryptography on Youtube.&lt;&#x2F;li&gt;
&lt;li&gt;CSCI E-127, Introduction to Cryptography &lt;a href=&quot;http:&#x2F;&#x2F;cm.dce.harvard.edu&#x2F;2014&#x2F;01&#x2F;14301&#x2F;publicationListing.shtml&quot;&gt;http:&#x2F;&#x2F;cm.dce.harvard.edu&#x2F;2014&#x2F;01&#x2F;14301&#x2F;publicationListing.shtml&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;generic-kickoff-questions&quot;&gt;Generic Kickoff Questions&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;What topic are you investigating?&lt;&#x2F;li&gt;
&lt;li&gt;How does this relate to Cryptography?&lt;&#x2F;li&gt;
&lt;li&gt;How would you explain this topic to your friends or parents?&lt;&#x2F;li&gt;
&lt;li&gt;Why is this topic important?&lt;&#x2F;li&gt;
&lt;li&gt;What interests you about this topic?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;additional-resources&quot;&gt;Additional resources&lt;&#x2F;h2&gt;
&lt;p&gt;OSU Professor &lt;a href=&quot;http:&#x2F;&#x2F;web.engr.oregonstate.edu&#x2F;~rosulekm&#x2F;&quot;&gt;Mike Rosulek&lt;&#x2F;a&gt; volunteered the following additional resources:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Scrypt is maximally memory-hard, &lt;a href=&quot;http:&#x2F;&#x2F;www.cs.bu.edu&#x2F;fac&#x2F;reyzin&#x2F;papers&#x2F;BostonCryptoDayTalk-Leo.pptx&quot;&gt;http:&#x2F;&#x2F;www.cs.bu.edu&#x2F;fac&#x2F;reyzin&#x2F;papers&#x2F;BostonCryptoDayTalk-Leo.pptx&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Practical Graphs for Optimal Side-Channel Resistant Memory-Hard Functions, &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2017&#x2F;443.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2017&#x2F;443.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Efficiently Computing Data Independent Memory Hard Functions, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ujpvPtn_N5Y&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;ujpvPtn_N5Y&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Memory hard Functions and Password Hashing, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;9yX4v89m5oo&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;9yX4v89m5oo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Towards a Theory of Data-Independent Memory Hard Functions, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;YtfVLzUkwME&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;YtfVLzUkwME&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Depth-Robust Graphs and Their Cumulative Memory Complexity, &lt;a href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;875.pdf&quot;&gt;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;875.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Practical Garbled Circuit Optimizations, &lt;a href=&quot;http:&#x2F;&#x2F;web.engr.oregonstate.edu&#x2F;~rosulekm&#x2F;pubs&#x2F;gc-survey-talk.pdf&quot;&gt;http:&#x2F;&#x2F;web.engr.oregonstate.edu&#x2F;~rosulekm&#x2F;pubs&#x2F;gc-survey-talk.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Pratical Garbled Circuit Optimizations, &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&quot;&gt;https:&#x2F;&#x2F;youtu.be&#x2F;FTxh908u9y8&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Cache-timing attacks on AES, &lt;a href=&quot;http:&#x2F;&#x2F;cr.yp.to&#x2F;antiforgery&#x2F;cachetiming-20050414.pdf&quot;&gt;http:&#x2F;&#x2F;cr.yp.to&#x2F;antiforgery&#x2F;cachetiming-20050414.pdf&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Lucky Thirteen attack on TLS CBC, &lt;a href=&quot;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&quot;&gt;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2013&#x2F;02&#x2F;04&#x2F;luckythirteen.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Deploying Buildbot on Kubernetes</title>
        <published>2016-12-12T00:00:00+00:00</published>
        <updated>2016-12-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/buildbot-on-kubernetes/"/>
        <id>https://elijah.run/blog/buildbot-on-kubernetes/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/buildbot-on-kubernetes/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;kubernetes-logo.png&quot; alt=&quot;kubernetes logo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TLDR:&lt;&#x2F;strong&gt; If you just want to see the end-result of this post, the results can be found at this GitHub Repository: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;preamble&quot;&gt;Preamble&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m learning Kubernetes (K8s) for work and decided to try my hand at deploying Buildbot with K8s because we all know the universal law discovered made by Science McSmartyPants in the 1758 which stated: &lt;strong&gt;doing cool shit &amp;gt; reading docs&lt;&#x2F;strong&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#docs-should&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
I would describe K8s and Buildbot, but they each already did that:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Buildbot is an open-source framework for automating software build, test, and release processes.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;- &lt;a href=&quot;http:&#x2F;&#x2F;buildbot.net&#x2F;&quot;&gt;Buildbot.net&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;Kubernetes is an open-source system for automating deployment,
scaling, and management of containerized applications.&lt;&#x2F;p&gt;
&lt;p&gt;- &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes.io&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If that still didn&#x27;t make sense, don&#x27;t worry you should keep reading.
This is a fun post.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; As you read this post keep in mind: &lt;em&gt;it might walk like a
tutorial, quack like a tutorial, and even read like a tutorial, but I
promise you that it is in fact&lt;&#x2F;em&gt; &lt;strong&gt;not&lt;&#x2F;strong&gt; &lt;em&gt;a tutorial.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;This post is an adventure.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;squad-goals&quot;&gt;Squad Goals&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s a quick rundown of what I want to achieve:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Deploy an instance of Buildbot on K8s.&lt;&#x2F;li&gt;
&lt;li&gt;Have that instance scale it&#x27;s number of workers automagically
depending on the amount of work being asked of it.&lt;&#x2F;li&gt;
&lt;li&gt;Share all relevant storage between replicated containers (e.g.,
databases, builds, etc).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h3&gt;
&lt;p&gt;I have never deployed Buildbot ever for anything. I have also not really
worked with K8s until starting my recent jorb at
&lt;a href=&quot;https:&#x2F;&#x2F;coreos.com&quot;&gt;CoreOS&lt;&#x2F;a&gt;. Why Buildbot and why K8s?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I have to learn K8s sooner or later for work.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I want to deploy something a little more complicated than Nginx. As
fun as that is, every K8s tutorial uses that as an example and it&#x27;s
getting &lt;em&gt;oooooold&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Buildbot seems like a good K8s challenge b&#x2F;c:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It has 3 moving parts (master, worker, database)&lt;&#x2F;li&gt;
&lt;li&gt;It could benefit from the fancy-dancy auto-scaling features
built into K8s (e.g., high workload -&amp;gt; add more workers)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Anyway, let&#x27;s get started.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;my-sick-rig&quot;&gt;My sick rig&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m using the latest version of K8s and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;minikube#minikube&quot;&gt;Minikube&lt;&#x2F;a&gt;, which is
backed by Virtualbox on a 2014 MacBook Pro running OSX.&lt;&#x2F;p&gt;
&lt;p&gt;Minikube version and associated OS:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ minikube version
&lt;&#x2F;span&gt;&lt;span&gt;minikube version: v0.13.1
&lt;&#x2F;span&gt;&lt;span&gt;$ minikube ssh
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;Boot2Docker version 1.11.1, build master : 901340f - Fri Jul  1 22:52:19 UTC 2016
&lt;&#x2F;span&gt;&lt;span&gt;Docker version 1.11.1, build 5604cbe
&lt;&#x2F;span&gt;&lt;span&gt;docker@minikube:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s some Minikube-specific semantics in this post, but you can
probably get by with whatever K8s back-end you want&#x2F;have lying around.&lt;&#x2F;p&gt;
&lt;p&gt;Kubernetes version:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl version
&lt;&#x2F;span&gt;&lt;span&gt;Client Version: version.Info{Major:&amp;quot;1&amp;quot;, Minor:&amp;quot;4&amp;quot;, GitVersion:&amp;quot;v1.4.6&amp;quot;, GitCommit:&amp;quot;e569a27d02001e343cb68086bc06d47804f62af6&amp;quot;, GitTreeState:&amp;quot;clean&amp;quot;, BuildDate:&amp;quot;2016-11-12T05:22:15Z&amp;quot;, GoVersion:&amp;quot;go1.7.1&amp;quot;, Compiler:&amp;quot;gc&amp;quot;, Platform:&amp;quot;darwin&#x2F;amd64&amp;quot;}
&lt;&#x2F;span&gt;&lt;span&gt;Server Version: version.Info{Major:&amp;quot;1&amp;quot;, Minor:&amp;quot;4&amp;quot;, GitVersion:&amp;quot;v1.4.6&amp;quot;, GitCommit:&amp;quot;e569a27d02001e343cb68086bc06d47804f62af6&amp;quot;, GitTreeState:&amp;quot;clean&amp;quot;, BuildDate:&amp;quot;1970-01-01T00:00:00Z&amp;quot;, GoVersion:&amp;quot;go1.7.1&amp;quot;, Compiler:&amp;quot;gc&amp;quot;, Platform:&amp;quot;linux&#x2F;amd64&amp;quot;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Between finishing editing and pushing this post the above versions will
probably be out of date. &lt;em&gt;SHRUG&lt;&#x2F;em&gt;. What are you gonna do. Software,
amirite?&lt;&#x2F;p&gt;
&lt;p&gt;Virtualbox version:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ virtualbox --help
&lt;&#x2F;span&gt;&lt;span&gt;Oracle VM VirtualBox Manager 5.1.6
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;OSX Version and hardware:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ sw_vers
&lt;&#x2F;span&gt;&lt;span&gt;ProductName:    Mac OS X
&lt;&#x2F;span&gt;&lt;span&gt;ProductVersion: 10.10.5
&lt;&#x2F;span&gt;&lt;span&gt;BuildVersion:   14F1912
&lt;&#x2F;span&gt;&lt;span&gt;$ system_profiler
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    Hardware Overview:
&lt;&#x2F;span&gt;&lt;span&gt;      Model Name: MacBook Pro
&lt;&#x2F;span&gt;&lt;span&gt;      Model Identifier: MacBookPro11,1
&lt;&#x2F;span&gt;&lt;span&gt;      Processor Name: Intel Core i5
&lt;&#x2F;span&gt;&lt;span&gt;      Processor Speed: 2.6 GHz
&lt;&#x2F;span&gt;&lt;span&gt;      Number of Processors: 1
&lt;&#x2F;span&gt;&lt;span&gt;      Total Number of Cores: 2
&lt;&#x2F;span&gt;&lt;span&gt;      ...
&lt;&#x2F;span&gt;&lt;span&gt;      Memory: 16 GB
&lt;&#x2F;span&gt;&lt;span&gt;      ...
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The hardware and Virtualbox versions are a little less important, but
might as well be included for completeness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-pass&quot;&gt;First Pass&lt;&#x2F;h2&gt;
&lt;p&gt;The Buildbot project is nice enough to provide &lt;a href=&quot;https:&#x2F;&#x2F;docs.buildbot.net&#x2F;current&#x2F;tutorial&#x2F;docker.html&quot;&gt;some Buidlbot Docker
infrastructure&lt;&#x2F;a&gt;
to start working with. It uses a &lt;a href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;compose&#x2F;&quot;&gt;Docker
Compose&lt;&#x2F;a&gt; YAML file to deploy one
worker container, one master service, and one PostgreSQL service, each
of which is linked together and &lt;em&gt;just works™&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Great!
In theory &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#theory-vs-practice&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; we can just translate the options in &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; to K8s options to get a simple cluster up and running.
Which, to clarify, isn&#x27;t an established &lt;strong&gt;thing&lt;&#x2F;strong&gt;, it&#x27;s just a process I&#x27;m guessing should work based on the fact that Docker Compose and K8s are both orchestration tools.
One is &lt;strong&gt;way&lt;&#x2F;strong&gt; more complicated and robust, but At least &lt;strong&gt;some&lt;&#x2F;strong&gt; of their features should over-lap in that Venn diagram.&lt;&#x2F;p&gt;
&lt;p&gt;Once we&#x27;ve got a nieve translated-docker-compose k8s setup running then we can (hopefully) tweak some knobs and get persistent storage and auto-scaling working &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#why&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;throw-some-containers-at-the-wall-and-see-what-sticks&quot;&gt;Throw some containers at the wall and see what sticks&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s start really basic and just try to get something running with &lt;code&gt;kubectl run&lt;&#x2F;code&gt;.
We&#x27;ll use K8s to deploy a Buildbot &lt;code&gt;master&lt;&#x2F;code&gt; container mentioned in that &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; with translated configuration options from that file.
Remember, we&#x27;re just mapping a &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; into a K8s setup to begin.
Nothing fancy, no pre-emptive optimizations, just this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl run master \
&lt;&#x2F;span&gt;&lt;span&gt;    --image=buildbot&#x2F;buildbot-master:master \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_CONFIG_DIR=config&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_CONFIG_URL=https:&#x2F;&#x2F;github.com&#x2F;buildbot&#x2F;buildbot-docker-example-config&#x2F;archive&#x2F;master.tar.gz&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_WORKER_PORT=9989&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_WEB_URL=http:&#x2F;&#x2F;localhost:8080&#x2F;&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_WEB_PORT=8080&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --port=8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some reading later and I can tell you that command started a &lt;em&gt;Deployment&lt;&#x2F;em&gt; of &lt;em&gt;Pods&lt;&#x2F;em&gt;.
To see if it worked, let&#x27;s run &lt;code&gt;kubect get pods&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS             RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-4259088255-afsfk            1&#x2F;1       Running            1          10s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This looks pretty good...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS             RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-4259088255-afsfk            0&#x2F;1       CrashLoopBackOff   2          1m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;... nooo!
The thing was at 1&#x2F;1 and now it&#x27;s at 0&#x2F;1 &lt;strong&gt;and&lt;&#x2F;strong&gt; it says &lt;strong&gt;CrashLoopBackOff&lt;&#x2F;strong&gt;.
Numbers going down when they&#x27;re supposed to stay the same is never a good sign, and crashing is almost never what you want.&lt;&#x2F;p&gt;
&lt;p&gt;If I&#x27;ve learned &lt;em&gt;anything&lt;&#x2F;em&gt; about fixing stuff that&#x27;s broke it&#x27;s &lt;em&gt;always check the logs&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl logs po&#x2F;master-4259088255-afsfk
&lt;&#x2F;span&gt;&lt;span&gt;[...]
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] Setting up database with URL &amp;#39;sqlite:&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] The Buildmaster database needs to be upgraded before this version of
&lt;&#x2F;span&gt;&lt;span&gt;[...]
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] BuildMaster startup failed
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] BuildMaster is stopped
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] Main loop terminated.
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 22:31:42+0000 [-] Server Shut Down.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Gross, but probably useful.
How?
Good question:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I saw the word &lt;code&gt;database&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We &lt;em&gt;didn&#x27;t&lt;&#x2F;em&gt; deploy a database.&lt;&#x2F;li&gt;
&lt;li&gt;QED let&#x27;s do that.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;add-one-cup-of-postgres-to-the-mix&quot;&gt;Add one cup of Postgres to the mix&lt;&#x2F;h3&gt;
&lt;p&gt;Just like with the &lt;code&gt;master&lt;&#x2F;code&gt; container, we&#x27;re just going to use CLI arguments to get a database running.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl run postgres \
&lt;&#x2F;span&gt;&lt;span&gt;    --image=postgres:9.4\
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;POSTGRES_PASSWORD=change_me&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;POSTGRES_USER=buildbot&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;POSTGRES_DB=buildbot&amp;quot; \
&lt;&#x2F;span&gt;&lt;span&gt;    --env=&amp;quot;BUILDBOT_DB_URL=postgresql+psycopg2:&#x2F;&#x2F;{POSTGRES_USER}:{POSTGRES_PASSWORD}@db&#x2F;{POSTGRES_DB}&amp;quot;\
&lt;&#x2F;span&gt;&lt;span&gt;    --port=5432
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cross fingers aaand...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS             RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-4259088255-afsfk            0&#x2F;1       CrashLoopBackOff   6          9m
&lt;&#x2F;span&gt;&lt;span&gt;postgres-2443857112-3ermh          0&#x2F;1       ContainerCreating  0          15s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;&#x2F;me holds breath&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS             RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-4259088255-afsfk            0&#x2F;1       CrashLoopBackOff   6          9m
&lt;&#x2F;span&gt;&lt;span&gt;postgres-2443857112-3ermh          1&#x2F;1       Running            0          54s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yuss! Wait, for real?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl logs postgres-2443857112-3ermh
&lt;&#x2F;span&gt;&lt;span&gt;[... hey look a bunch of useful Postgres garbage ...]
&lt;&#x2F;span&gt;&lt;span&gt;PostgreSQL init process complete; ready for start up.
&lt;&#x2F;span&gt;&lt;span&gt;[... some more useful Postgres garbage ...]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Good &#x27;nuff.
Now how does this database plug into the master container?&lt;&#x2F;p&gt;
&lt;p&gt;Well, in the Docker Compose world, containers talked to one-another on a private network with the &lt;code&gt;link&lt;&#x2F;code&gt; directive.
There&#x27;s probably some way to do we do that with K8s right?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;welcome-yaml-config-files-to-the-class&quot;&gt;Welcome YAML config files to the class&lt;&#x2F;h3&gt;
&lt;p&gt;Running Command-Line Interface (CLI) commands is fun, but the easiest way to get this system running seems to be with configuration files.
I&#x27;m sure I &lt;em&gt;can&lt;&#x2F;em&gt; use CLI commands to orchestrate this entire project, but... honestly all the tutorials talk about how to do things in YAML so we&#x27;re doing it in YAML now.&lt;&#x2F;p&gt;
&lt;p&gt;Some research later it looks like declaring a &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;pods&#x2F;&quot;&gt;Pod&lt;&#x2F;a&gt; is the way to go?
For context, here&#x27;s where I got the idea from the K8s docs:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A pod (as in a pod of whales or pea pod) is a group of one or more containers (such as Docker containers), the shared storage for those containers, and options about how to run the containers.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Well that sounds &lt;em&gt;roughly&lt;&#x2F;em&gt; like what we&#x27;re doing.
I&#x27;ve got some containers, I want them to be able to talk to each other, and they&#x27;re
all logically connected to one another.
Let&#x27;s go down this rabbit hole.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;alice-down.gif&quot; alt=&quot;Alice down the rabbit hole...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here I have Frankensteined this config &lt;code&gt;buildbot.yaml&lt;&#x2F;code&gt; from examples in the configs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&#x2F;buildbot-master:master&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_CONFIG_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_CONFIG_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;buildbot&#x2F;buildbot-docker-example-config&#x2F;archive&#x2F;master.tar.gz&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WORKER_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;9989&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WEB_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;http:&#x2F;&#x2F;localhost:8080&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WEB_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_PASSWORD&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;change_me&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_USER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_DB_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgresql+psycopg2:&#x2F;&#x2F;{POSTGRES_USER}:{POSTGRES_PASSWORD}@db&#x2F;{POSTGRES_DB}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres:9.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;5432
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_PASSWORD&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;change_me&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_USER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_DB_URL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgresql+psycopg2:&#x2F;&#x2F;{POSTGRES_USER}:{POSTGRES_PASSWORD}@db&#x2F;{POSTGRES_DB}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What happens when we run it?&lt;&#x2F;p&gt;
&lt;p&gt;Well first we need to clean up that CLI-created garbage we were doing
earlier.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl delete deployment master postgres
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;master&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;postgres&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then deploy the new pod:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl create -f buildbot.yaml
&lt;&#x2F;span&gt;&lt;span&gt;pod &amp;quot;buildbot&amp;quot; created
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Aaaand:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods
&lt;&#x2F;span&gt;&lt;span&gt;buildbot   2&#x2F;2       Running   0          23s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m suspicious...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl logs po&#x2F;buildbot master
&lt;&#x2F;span&gt;&lt;span&gt;checking basedir
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;python2.7&#x2F;site-packages&#x2F;buildbot&#x2F;config.py:85: ConfigWarning: [0.9.0 and later] `buildbotNetUsageData` is not configured and defaults to basic
&lt;&#x2F;span&gt;&lt;span&gt;[...]
&lt;&#x2F;span&gt;&lt;span&gt;Failure: sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) could not translate host name &amp;quot;db&amp;quot; to address: Try again
&lt;&#x2F;span&gt;&lt;span&gt;[...]
&lt;&#x2F;span&gt;&lt;span&gt;problem while upgrading!:
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;[... python traceback ...]
&lt;&#x2F;span&gt;&lt;span&gt;OperationalError: (psycopg2.OperationalError) could not translate host name &amp;quot;db&amp;quot; to address: Try again
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whelp let&#x27;s play &#x27;Where do I fix &lt;em&gt;that&lt;&#x2F;em&gt;?&#x27;&lt;&#x2F;p&gt;
&lt;p&gt;Is the problem in:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;buildbot-master&lt;&#x2F;code&gt; image&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;postgres&lt;&#x2F;code&gt; image&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;buildbot.yml&lt;&#x2F;code&gt; file&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If you guessed &lt;strong&gt;c&lt;&#x2F;strong&gt; you would be right so let&#x27;s start in
&lt;code&gt;buildbot.yaml&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Based on my experience with databases, specifically the startup time of database containers like Postgres and MariaDB, I&#x27;d &lt;em&gt;guess&lt;&#x2F;em&gt; that the database was taking too long to start.
After some digging around, I found out that Pods were the entirely wrong way to go. Here&#x27;s how that discovery went:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: Does K8s have anything like docker-compose&#x27;s &lt;code&gt;depends_on:&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;: No.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: Okay, so how... actually, is there anything like what I&#x27;m doing already out there?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;: Yes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: ... Where?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;tree&#x2F;master&#x2F;examples&#x2F;mysql-wordpress-pd&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;tree&#x2F;master&#x2F;examples&#x2F;mysql-wordpress-pd&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: Noice. So the &lt;em&gt;Pods&lt;&#x2F;em&gt; thing was the wrong rabbit hole to go down?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;: Right.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: Right like correct or right like...?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;: Stop.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;yay-examples&quot;&gt;Yay examples&lt;&#x2F;h3&gt;
&lt;p&gt;So let&#x27;s run that example to make sure it all works fine.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Clone repo&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;&#x2F;code&gt; to example&lt;&#x2F;li&gt;
&lt;li&gt;Follow README instructions&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl create -f local-volumes.yaml
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolume &amp;quot;local-pv-1&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolume &amp;quot;local-pv-2&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f mysql-deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;wordpress-mysql&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolumeclaim &amp;quot;mysql-pv-claim&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;wordpress-mysql&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f wordpress-deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;wordpress&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolumeclaim &amp;quot;wp-pv-claim&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;wordpress&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl get all
&lt;&#x2F;span&gt;&lt;span&gt;NAME                  CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
&lt;&#x2F;span&gt;&lt;span&gt;svc&#x2F;kubernetes        10.0.0.1     &amp;lt;none&amp;gt;        443&#x2F;TCP    2h
&lt;&#x2F;span&gt;&lt;span&gt;svc&#x2F;wordpress         10.0.0.28    &amp;lt;pending&amp;gt;     80&#x2F;TCP     5s
&lt;&#x2F;span&gt;&lt;span&gt;svc&#x2F;wordpress-mysql   None         &amp;lt;none&amp;gt;        3306&#x2F;TCP   17s
&lt;&#x2F;span&gt;&lt;span&gt;NAME                                  READY     STATUS              RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;po&#x2F;buildbot                           2&#x2F;2       Running             0          8m
&lt;&#x2F;span&gt;&lt;span&gt;po&#x2F;wordpress-1618093523-4if9k         0&#x2F;1       ContainerCreating   0          5s
&lt;&#x2F;span&gt;&lt;span&gt;po&#x2F;wordpress-mysql-2379610080-mqvll   0&#x2F;1       ContainerCreating   0          17s
&lt;&#x2F;span&gt;&lt;span&gt;NAME                 STATUS    VOLUME       CAPACITY   ACCESSMODES   AGE
&lt;&#x2F;span&gt;&lt;span&gt;pvc&#x2F;mysql-pv-claim   Bound     local-pv-1   20Gi       RWO           17s
&lt;&#x2F;span&gt;&lt;span&gt;pvc&#x2F;wp-pv-claim      Bound     local-pv-2   20Gi       RWO           5s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And I can go to the site?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;wordpress-working.png&quot; alt=&quot;Wordpress working correctly&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Great.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;now-use-the-example&quot;&gt;Now Use the example&lt;&#x2F;h3&gt;
&lt;p&gt;Now we need to morph &lt;code&gt;wordpress-deployment.yaml&lt;&#x2F;code&gt; into &lt;code&gt;postgres.yaml&lt;&#x2F;code&gt;, and &lt;code&gt;wordpress-deployment.yaml&lt;&#x2F;code&gt; into &lt;code&gt;master.yaml&lt;&#x2F;code&gt;
Also, let&#x27;s ignore &lt;code&gt;local-volumes.yaml&lt;&#x2F;code&gt; for now, just to be safe.
Don&#x27;t forget: we&#x27;re not doing anything fancy yet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;master.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;frontend
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;NodePort
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Deployment
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recreate
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&#x2F;buildbot-master:master
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_CONFIG_DIR
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;config
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_CONFIG_URL
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;buildbot&#x2F;buildbot-docker-example-config&#x2F;master&#x2F;master.cfg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WORKER_PORT
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;9989&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WEB_URL
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;http:&#x2F;&#x2F;localhost:8080&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_WEB_PORT
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_PASSWORD
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;change_me
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_USER
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB_HOST
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_DB_URL
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgresql+psycopg2:&#x2F;&#x2F;{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_DB_HOST}&#x2F;{POSTGRES_DB}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;frontend
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;postgres.yaml:&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;5432
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;clusterIP&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Deployment
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recreate
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres:9.4
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_PASSWORD
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;change_me
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_USER
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;POSTGRES_DB_HOST
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDBOT_DB_URL
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgresql+psycopg2:&#x2F;&#x2F;{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_DB_HOST}&#x2F;{POSTGRES_DB}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;5432
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;postgres
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with a flick of my wand:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl delete pods,deployment,service --all  # cleanup the old stuff
&lt;&#x2F;span&gt;&lt;span&gt;pod &amp;quot;buildbot&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;pod &amp;quot;wordpress-1618093523-4if9k&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;pod &amp;quot;wordpress-mysql-2379610080-mqvll&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;wordpress&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;wordpress-mysql&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;kubernetes&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;wordpress&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;wordpress-mysql&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f postrges.yml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;postgres&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;postgres&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f master.yml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;master&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;master&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ minikube service master
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Opens up this wonderful site:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;buildbot-working.png&quot; alt=&quot;Buildbot working&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Great, they can talk &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#same-app-note&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hire-a-worker&quot;&gt;Hire a worker&lt;&#x2F;h3&gt;
&lt;p&gt;So we&#x27;ve got a website and a database, but we&#x27;re not actually running any builds yet. Let&#x27;s fix that.&lt;&#x2F;p&gt;
&lt;p&gt;Based on what the &lt;code&gt;docker-compose.yml&lt;&#x2F;code&gt; says we should be able to throw this together and have it work:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;worker.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;9989
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;clusterIP&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Deployment
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;strategy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recreate
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;tier&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;buildbot&#x2F;buildbot-worker:master&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDMASTER
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;master
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;BUILDMASTER_PORT
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;9989&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;WORKERNAME
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;example-worker
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;WORKERPASS
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;pass
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;WORKER_ENVIRONMENT_BLACKLIST
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;DOCKER_BUILDBOT* BUILDBOT_ENV_* BUILDBOT_1* WORKER_ENVIRONMENT_BLACKLIST&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;9989
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;worker
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl create -f worker.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;worker&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;worker&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl get -f worker.yaml
&lt;&#x2F;span&gt;&lt;span&gt;NAME                  CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
&lt;&#x2F;span&gt;&lt;span&gt;svc&#x2F;worker            None         &amp;lt;none&amp;gt;        9989&#x2F;TCP   44s
&lt;&#x2F;span&gt;&lt;span&gt;NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
&lt;&#x2F;span&gt;&lt;span&gt;deploy&#x2F;worker            1         1         1            0           44s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looks promising...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods -l tier=worker
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;worker-3607067131-qdpfd   1&#x2F;1       Running   0          1m
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl logs worker-3607067131-ke4zb -f
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] Loading buildbot.tac...
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] Loaded.
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] twistd 16.5.0 (&#x2F;usr&#x2F;bin&#x2F;python 2.7.12) starting up.
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor.  2016-11-21 19:46:45+0000 [-] Starting Worker -- version: latest
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] recording hostname in twistd.hostname
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] Starting factory &amp;lt;buildbot_worker.pb.BotFactory instance at 0x7fd8c2339cf8&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:45+0000 [-] Connecting to buildbot:9989
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:56+0000 [Uninitialized] Connection to buildbot:9989 failed: Connection Refused
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:56+0000 [Uninitialized] &amp;lt;twisted.internet.tcp.Connector instance at 0x7fd8c233a170&amp;gt; will retry in 2 seconds
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:56+0000 [-] Stopping factory &amp;lt;buildbot_worker.pb.BotFactory instance at 0x7fd8c2339cf8&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:59+0000 [-] Starting factory &amp;lt;buildbot_worker.pb.BotFactory instance at 0x7fd8c2339cf8&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:46:59+0000 [-] Connecting to buildbot:9989
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:47:29+0000 [-] Connection to buildbot:9989 failed: [Failure instance: Traceback (failure with no frames): &amp;lt;class &amp;#39;twisted.internet.error.TimeoutError&amp;#39;&amp;gt;: User timeout caused connection failure.
&lt;&#x2F;span&gt;&lt;span&gt;    ]
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:47:29+0000 [-] &amp;lt;twisted.internet.tcp.Connector instance at 0x7fd8c233a170&amp;gt; will retry in 5 seconds
&lt;&#x2F;span&gt;&lt;span&gt;2016-11-21 19:47:29+0000 [-] Stopping factory &amp;lt;buildbot_worker.pb.BotFactory instance at 0x7fd8c2339cf8&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Khaaaaaan!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;connection-issues&quot;&gt;Connection issues&lt;&#x2F;h3&gt;
&lt;p&gt;Fine, let&#x27;s get to work debugging.
First we&#x27;ll login to the worker pod and try to ping the &lt;code&gt;buildbot&lt;&#x2F;code&gt; pod since the output makes it seem like there was a timeout between the host and the worker.
This usually means they can&#x27;t reach each other.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl exec -it worker-3607067131-qdpfd bash
&lt;&#x2F;span&gt;&lt;span&gt;buildbot@worker-3607067131-qdpfd:&#x2F;buildbot$ ping master
&lt;&#x2F;span&gt;&lt;span&gt;bash: ping: command not found
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uhh...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;buildbot@worker-3607067131-ke4zb:&#x2F;buildbot$ curl http:&#x2F;&#x2F;master:8080
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;!DOCTYPE html&amp;gt;[... definitely actually a webpage ...]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So the worker can reach the master, but can the master reach the worker?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods -l tier=master
&lt;&#x2F;span&gt;&lt;span&gt;NAME                                 READY     STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-2152810066-9ip8b              1&#x2F;1       Running   0          21m
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl exec -it master-2152810066-9ip8b sh
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;var&#x2F;lib&#x2F;buildbot # ping worker
&lt;&#x2F;span&gt;&lt;span&gt;PING worker (172.17.0.6): 56 data bytes
&lt;&#x2F;span&gt;&lt;span&gt;64 bytes from 172.17.0.6: seq=0 ttl=64 time=0.083 ms
&lt;&#x2F;span&gt;&lt;span&gt;64 bytes from 172.17.0.6: seq=1 ttl=64 time=0.101 ms
&lt;&#x2F;span&gt;&lt;span&gt;^C
&lt;&#x2F;span&gt;&lt;span&gt;--- worker ping statistics ---
&lt;&#x2F;span&gt;&lt;span&gt;2 packets transmitted, 2 packets received, 0% packet loss
&lt;&#x2F;span&gt;&lt;span&gt;round-trip min&#x2F;avg&#x2F;max = 0.083&#x2F;0.092&#x2F;0.101 ms
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay, so they can connect to one-another.
What&#x27;s the problem then?
My best guess is that the &lt;code&gt;master&lt;&#x2F;code&gt; pod needs to have it&#x27;s special worker port (&lt;code&gt;9989&lt;&#x2F;code&gt;) exposed.
So let&#x27;s add those lines to &lt;code&gt;master.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;updated-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;updated-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -8,6 +8,8 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;   ports:
&lt;&#x2F;span&gt;&lt;span&gt;     - port: 8080
&lt;&#x2F;span&gt;&lt;span&gt;       name: frontend
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    - port: 9989
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      name: worker
&lt;&#x2F;span&gt;&lt;span&gt;   selector:
&lt;&#x2F;span&gt;&lt;span&gt;     app: buildbot
&lt;&#x2F;span&gt;&lt;span&gt;     tier: master
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -55,3 +57,5 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         ports:
&lt;&#x2F;span&gt;&lt;span&gt;         - containerPort: 8080
&lt;&#x2F;span&gt;&lt;span&gt;           name: frontend
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        - containerPort: 9989
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          name: worker
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And after tearing everything down and bringing it back up:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods -l tier=worker
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;worker-2552724660-l4kmv            1&#x2F;1       Running   0          12s
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl logs worker-2552724660-l4kmv
&lt;&#x2F;span&gt;&lt;span&gt;[... logs logs logs ...]
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 23:30:18+0000 [-] Connecting to master:9989
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 23:30:18+0000 [HangCheckProtocol,client] message from master: attached
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 23:30:18+0000 [HangCheckProtocol,client] message from master: attached
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 23:30:18+0000 [HangCheckProtocol,client] Connected to master:9989; worker is ready
&lt;&#x2F;span&gt;&lt;span&gt;2016-12-09 23:30:18+0000 [HangCheckProtocol,client] sending application-level keepalives every 600 seconds
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hey that looks like success to me!
How does the front-end look?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get pods -l tier=master
&lt;&#x2F;span&gt;&lt;span&gt;NAME                               READY     STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-3038604518-jim6q            1&#x2F;1       Running   0          2m
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl port-forward master-3038604518-jim6q 8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And in a browser:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;build-success.png&quot; alt=&quot;Buildbot still working.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You may now do a happy dance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;happy-dance.gif&quot; alt=&quot;Happy Dance .gif&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;storage&quot;&gt;Storage&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve got the three core moving parts of our system, next on our list is adding some persistent storage.
Thankfully, we can recycle the MySQL+Wordpress example we used before.
Yay examples.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s add the storage bits back in that we ignored before.
This results in configs that look like so (abbreviated for your scrollbar&#x27;s convenience):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;volumes.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;PersistentVolume
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local-pv-1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;1Gi
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;persistentVolumeReclaimPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recycle
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;hostPath&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;data&#x2F;pv-1
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;PersistentVolume
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local-pv-2
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;5Gi
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;persistentVolumeReclaimPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recycle
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;hostPath&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;data&#x2F;pv-2
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;PersistentVolume
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local-pv-3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;local
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;5Gi
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;persistentVolumeReclaimPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Recycle
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;hostPath&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;data&#x2F;pv-3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;master.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;blogpost&#x2F;volumes-master.yaml b&#x2F;blogpost&#x2F;volumes-master.yaml
&lt;&#x2F;span&gt;&lt;span&gt;index 7cbffd7..c7479e3 100644
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;volumes-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;volumes-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -15,6 +15,19 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;     tier: master
&lt;&#x2F;span&gt;&lt;span&gt;   type: NodePort
&lt;&#x2F;span&gt;&lt;span&gt; ---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+apiVersion: v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+kind: PersistentVolumeClaim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  name: master-pv-claim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  labels:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    app: buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+spec:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  accessModes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  resources:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    requests:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      storage: 1Gi
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+---
&lt;&#x2F;span&gt;&lt;span&gt; apiVersion: extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span&gt; kind: Deployment
&lt;&#x2F;span&gt;&lt;span&gt; metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -37,7 +50,7 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_CONFIG_DIR
&lt;&#x2F;span&gt;&lt;span&gt;           value: config
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_CONFIG_URL
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-          value: &amp;#39;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;buildbot&#x2F;buildbot-docker-example-config&#x2F;master&#x2F;master.cfg&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          value: &amp;#39;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&#x2F;master&#x2F;simple&#x2F;master.cfg&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_WORKER_PORT
&lt;&#x2F;span&gt;&lt;span&gt;           value: &amp;#39;9989&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_WEB_URL
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -59,3 +72,10 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;           name: frontend
&lt;&#x2F;span&gt;&lt;span&gt;         - containerPort: 9989
&lt;&#x2F;span&gt;&lt;span&gt;           name: worker
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        volumeMounts:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        - name: master-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          mountPath: &#x2F;var&#x2F;lib&#x2F;buildbot&#x2F;builds
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      volumes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      - name: master-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        persistentVolumeClaim:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          claimName: master-pv-claim
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;postgres.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;volumes-postgres.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;volumes-postgres.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -13,6 +13,19 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;     tier: postgres
&lt;&#x2F;span&gt;&lt;span&gt;   clusterIP: None
&lt;&#x2F;span&gt;&lt;span&gt; ---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+apiVersion: v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+kind: PersistentVolumeClaim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  name: postgres-pv-claim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  labels:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    app: buildbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+spec:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  accessModes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  resources:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    requests:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      storage: 5Gi
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+---
&lt;&#x2F;span&gt;&lt;span&gt; apiVersion: extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span&gt; kind: Deployment
&lt;&#x2F;span&gt;&lt;span&gt; metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -45,3 +58,10 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         ports:
&lt;&#x2F;span&gt;&lt;span&gt;         - containerPort: 5432
&lt;&#x2F;span&gt;&lt;span&gt;           name: postgres
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        volumeMounts:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        - name: postgres-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          mountPath: &#x2F;var&#x2F;lib&#x2F;postgresql
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      volumes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      - name: postgres-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        persistentVolumeClaim:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          claimName: postgres-pv-claim
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;worker.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;volumes-worker.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;volumes-worker.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -13,6 +13,19 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;     tier: worker
&lt;&#x2F;span&gt;&lt;span&gt;   clusterIP: None
&lt;&#x2F;span&gt;&lt;span&gt; ---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+apiVersion: v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+kind: PersistentVolumeClaim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  name: worker-pv-claim
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  labels:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    app: buidlbot
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+spec:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  accessModes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+  resources:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    requests:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      storage: 5Gi
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+---
&lt;&#x2F;span&gt;&lt;span&gt; apiVersion: extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span&gt; kind: Deployment
&lt;&#x2F;span&gt;&lt;span&gt; metadata:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -45,3 +58,10 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         ports:
&lt;&#x2F;span&gt;&lt;span&gt;         - containerPort: 9989
&lt;&#x2F;span&gt;&lt;span&gt;           name: worker
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        volumeMounts:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        - name: worker-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          mountPath: &#x2F;buildbot&#x2F;builds
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      volumes:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      - name: worker-persistent-storage
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        persistentVolumeClaim:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          claimName: worker-pv-claim
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And of lastly we edit the Buildbot &lt;code&gt;master.cfg&lt;&#x2F;code&gt; to use our custom paths
for storing and carrying out builds:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;blogpost&#x2F;volumes-master.cfg b&#x2F;blogpost&#x2F;volumes-master.cfg
&lt;&#x2F;span&gt;&lt;span&gt;index 06ad65b..36212ea 100644
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;volumes-master.cfg
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;volumes-master.cfg
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -78,7 +78,9 @@ c[&amp;#39;builders&amp;#39;] = []
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;builders&amp;#39;].append(
&lt;&#x2F;span&gt;&lt;span&gt;     util.BuilderConfig(name=&amp;quot;runtests&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;       workernames=[&amp;quot;example-worker&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-      factory=factory))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      factory=factory,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      builddir=&amp;#39;builds&amp;#39;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workerbuilddir=&amp;#39;builds&amp;#39;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; ####### STATUS TARGETS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is just an edited version of the original &lt;code&gt;master.cfg&lt;&#x2F;code&gt; you can find
in the original Buildbot docker-compose example repository.&lt;&#x2F;p&gt;
&lt;p&gt;So this &lt;em&gt;should&lt;&#x2F;em&gt; just work, right?
We request a volume of a given size, the volume exists and is the correct size, badda bing badda boom, do the thing like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl delete service,deployment,pods --all
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;master&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;postgres&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;worker&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;kubernetes&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;master&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;postgres&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;worker&amp;quot; deleted
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f volumes.yaml
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolume &amp;quot;local-pv-1&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolume &amp;quot;local-pv-2&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolume &amp;quot;local-pv-3&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f postgres.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;postgres&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolumeclaim &amp;quot;postgres-pv-claim&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;postgres&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f master.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;master&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolumeclaim &amp;quot;master-pv-claim&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;master&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl create -f worker.yaml
&lt;&#x2F;span&gt;&lt;span&gt;service &amp;quot;-worker&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;persistentvolumeclaim &amp;quot;worker-pv-claim&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;worker&amp;quot; created
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl get pods -l tier=master
&lt;&#x2F;span&gt;&lt;span&gt;NAME                        READY     STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;master-3176013930-gvy2i   1&#x2F;1       Running   0          1m
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl port-forward master-3176013930-gvy2i 8080
&lt;&#x2F;span&gt;&lt;span&gt;Forwarding from 127.0.0.1:8080 -&amp;gt; 8080
&lt;&#x2F;span&gt;&lt;span&gt;Forwarding from [::1]:8080 -&amp;gt; 8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That kinda works, but it kept getting weird arbitrary errors which
looked suspicious.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;permissions-build-fail.png&quot;
class=&quot;align-center&quot; style=&quot;width:100.0%&quot;
alt=&quot;Permissions fail in buildbot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since the only thing that had really changed was the volumes I figured I
might as well login to the host and investigate.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ minikube ssh
&lt;&#x2F;span&gt;&lt;span&gt;docker@minikube:~$ ls -alh &#x2F;data&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;total 20
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x    5 root     root        4.0K Dec 11 02:21 .&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x    6 root     root        4.0K Dec 11 01:48 ..&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x    2 root     root        4.0K Dec 11 02:20 pv-1&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x    2 root     root        4.0K Dec 11 02:33 pv-2&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x    3 root     root        4.0K Dec 11 02:33 pv-3&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ahah!
That&#x27;s the problem, root owns everything but the builds are run by the &lt;code&gt;buildbot&lt;&#x2F;code&gt; user (&lt;code&gt;uid: 1000&lt;&#x2F;code&gt;) &lt;em&gt;&#x2F;me shakes fist at permissions errors.&lt;&#x2F;em&gt;
The last first place you think to look.&lt;&#x2F;p&gt;
&lt;p&gt;So is there any way to change the permissions of a volume as you claim it (i.e., in &lt;code&gt;volumes.yaml&lt;&#x2F;code&gt;)?
We can both go through this journey together or I can share with you a quote from my coworker Barak Michener, the BAMF that works on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreos&#x2F;torus&quot;&gt;Torus&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Barak Michener&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;yeah, hostPath is completely hands-off from k8s perspective
so you just chmod the underlying dir
to whatever uid you&#x27;re using inside the pod&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Turns out the problem was with my &lt;code&gt;type&lt;&#x2F;code&gt; of storage in &lt;code&gt;volumes.yaml&lt;&#x2F;code&gt;.
As of yet there is no type-agnostic way to assign permissions for mounted volumes.
Storage, why you gotta be like that?&lt;&#x2F;p&gt;
&lt;p&gt;So after digging around and asking Barak I finally concluded that I had to had to login to my host and set the correct permissions on the directories being reserved.
Here&#x27;s how you do that on Minikube:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ minikube ssh
&lt;&#x2F;span&gt;&lt;span&gt;docker@minikube$ sudo chown -R 1000:1000 &#x2F;data&#x2F;pv*
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case we could just chown the one volume that&#x27;s going to be used by the &lt;code&gt;worker&lt;&#x2F;code&gt; pod, since the other ones run their services as &lt;code&gt;root&lt;&#x2F;code&gt;, but much like Debra from accounting, &lt;code&gt;root&lt;&#x2F;code&gt; doesn&#x27;t give a fuck.
Might as well.&lt;&#x2F;p&gt;
&lt;p&gt;So if we try the build again with the correct permissions, what happens?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;build-success-perms.png&quot; alt=&quot;Buildbot with permissions fixed&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Huzah&lt;&#x2F;p&gt;
&lt;h2 id=&quot;autoscaling&quot;&gt;Autoscaling&lt;&#x2F;h2&gt;
&lt;p&gt;At last we have what I suspect will be the &lt;em&gt;hardest&lt;&#x2F;em&gt; part of the project: autoscaling.
Here&#x27;s what we want in a perfect world:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;When a lot of builds get requested, spin up more &lt;code&gt;worker&lt;&#x2F;code&gt; nodes.&lt;&#x2F;li&gt;
&lt;li&gt;When fewer builds are requested, destroy those extra &lt;code&gt;worker&lt;&#x2F;code&gt; nodes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;asking-the-question&quot;&gt;Asking the question&lt;&#x2F;h3&gt;
&lt;p&gt;This task is actually a pretty tough cookie to crack.
We want enough workers to each deal with 1&#x2F;N requests in a queue of N builds, essentially scaling the building service to deal with usage spikes.
It sounds straight forward enough, but how do we test it?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-a-test-case&quot;&gt;Creating a test-case&lt;&#x2F;h3&gt;
&lt;p&gt;For this we need to add a few projects to our instance of Buildbot, each of which will have a hefty workload.
To do this we need to host a Buildbot &lt;code&gt;master.cfg&lt;&#x2F;code&gt; config file at some public location and refer to this in the &lt;code&gt;master.yaml&lt;&#x2F;code&gt; config file.
I used the GitHub repo that accompanies this blogpost &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#accompanying-repo&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but you could use GitHub Gists or a pastebin; just make sure you&#x27;re referring to the &lt;strong&gt;raw&lt;&#x2F;strong&gt; file or a &lt;code&gt;.tar.gz&lt;&#x2F;code&gt; with the &lt;code&gt;master.cfg&lt;&#x2F;code&gt; file at the base of the tarball.&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s pull a project out of a hat that takes a while to build, how about... &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo&quot;&gt;Cargo&lt;&#x2F;a&gt;.
Any objections?
Great, let&#x27;s roll.&lt;&#x2F;p&gt;
&lt;p&gt;To get started we&#x27;ll need a custom &lt;code&gt;worker&lt;&#x2F;code&gt; container can build Cargo.
A small adventure later and we have this Dockerfile which has all of the dependencies to build what we want:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;FROM buildbot&#x2F;buildbot-worker:master
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN curl https:&#x2F;&#x2F;sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
&lt;&#x2F;span&gt;&lt;span&gt;RUN echo &amp;#39;PATH=$PATH:$HOME&#x2F;.cargo&#x2F;bin&amp;#39; &amp;gt;&amp;gt; $HOME&#x2F;.bashrc
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;USER root
&lt;&#x2F;span&gt;&lt;span&gt;RUN apt update -y
&lt;&#x2F;span&gt;&lt;span&gt;RUN apt install -y cmake pkg-config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;USER buildbot
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I set this to auto-build on &lt;a href=&quot;https:&#x2F;&#x2F;quay.io&#x2F;&quot;&gt;quay.io&lt;&#x2F;a&gt;, hosted at the docker-pull url &lt;code&gt;quay.io&#x2F;elijahcaine&#x2F;buidlbot-rust-worker&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have a capable worker container, we need to create an arbitrary workload.
To do that we&#x27;ll use this Buildbot &lt;code&gt;master.cfg&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;blogpost&#x2F;robust-master.cfg b&#x2F;blogpost&#x2F;robust-master.cfg
&lt;&#x2F;span&gt;&lt;span&gt;index 06ad65b..892188b 100644
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;robust-master.cfg
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;robust-master.cfg
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -18,7 +18,7 @@ c = BuildmasterConfig = {}
&lt;&#x2F;span&gt;&lt;span&gt; # a Worker object, specifying a unique worker name and password.  The same
&lt;&#x2F;span&gt;&lt;span&gt; # worker name and password must be configured on the worker.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-c[&amp;#39;workers&amp;#39;] = [worker.Worker(&amp;quot;example-worker&amp;quot;, &amp;#39;pass&amp;#39;)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+c[&amp;#39;workers&amp;#39;] = [worker.Worker(&amp;quot;rust-worker&amp;quot;, &amp;#39;pass&amp;#39;)]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; if &amp;#39;BUILDBOT_MQ_URL&amp;#39; in os.environ:
&lt;&#x2F;span&gt;&lt;span&gt;     c[&amp;#39;mq&amp;#39;] = {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -43,7 +43,7 @@ c[&amp;#39;protocols&amp;#39;] = {&amp;#39;pb&amp;#39;: {&amp;#39;port&amp;#39;: os.environ.get(&amp;quot;BUILDBOT_WORKER_PORT&amp;quot;, 9989)}}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;change_source&amp;#39;] = []
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;change_source&amp;#39;].append(changes.GitPoller(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-        &amp;#39;git:&#x2F;&#x2F;github.com&#x2F;buildbot&#x2F;pyflakes.git&amp;#39;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        &amp;#39;git:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo.git&amp;#39;,
&lt;&#x2F;span&gt;&lt;span&gt;         workdir=&amp;#39;gitpoller-workdir&amp;#39;, branch=&amp;#39;master&amp;#39;,
&lt;&#x2F;span&gt;&lt;span&gt;         pollinterval=300))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -57,10 +57,10 @@ c[&amp;#39;schedulers&amp;#39;].append(schedulers.SingleBranchScheduler(
&lt;&#x2F;span&gt;&lt;span&gt;                             name=&amp;quot;all&amp;quot;,
&lt;&#x2F;span&gt;&lt;span&gt;                             change_filter=util.ChangeFilter(branch=&amp;#39;master&amp;#39;),
&lt;&#x2F;span&gt;&lt;span&gt;                             treeStableTimer=None,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-                            builderNames=[&amp;quot;runtests&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+                            builderNames=[&amp;quot;cargo1-runtests&amp;quot;, &amp;quot;cargo2-runtests&amp;quot;, &amp;quot;cargo3-runtests&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;schedulers&amp;#39;].append(schedulers.ForceScheduler(
&lt;&#x2F;span&gt;&lt;span&gt;                             name=&amp;quot;force&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-                            builderNames=[&amp;quot;runtests&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+                            builderNames=[&amp;quot;cargo1-runtests&amp;quot;, &amp;quot;cargo2-runtests&amp;quot;, &amp;quot;cargo3-runtests&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; ####### BUILDERS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -68,17 +68,30 @@ c[&amp;#39;schedulers&amp;#39;].append(schedulers.ForceScheduler(
&lt;&#x2F;span&gt;&lt;span&gt; # what steps, and which workers can execute them.  Note that any particular build will
&lt;&#x2F;span&gt;&lt;span&gt; # only take place on one worker.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-factory = util.BuildFactory()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-# check out the source
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-factory.addStep(steps.Git(repourl=&amp;#39;http:&#x2F;&#x2F;github.com&#x2F;buildbot&#x2F;pyflakes.git&amp;#39;, mode=&amp;#39;incremental&amp;#39;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-# run the tests (note that this will require that &amp;#39;trial&amp;#39; is installed)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-factory.addStep(steps.ShellCommand(command=[&amp;quot;trial&amp;quot;, &amp;quot;pyflakes&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+f = {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+f[&amp;#39;cargo&amp;#39;] = util.BuildFactory()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+f[&amp;#39;cargo&amp;#39;].addStep(steps.Git(repourl=&amp;#39;git:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo.git&amp;#39;, mode=&amp;#39;full&amp;#39;, method=&amp;#39;fresh&amp;#39;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+f[&amp;#39;cargo&amp;#39;].addStep(steps.ShellCommand(command=[&amp;quot;&#x2F;home&#x2F;buildbot&#x2F;.cargo&#x2F;bin&#x2F;cargo&amp;quot;, &amp;quot;build&amp;quot;, &amp;quot;--release&amp;quot;]))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;builders&amp;#39;] = []
&lt;&#x2F;span&gt;&lt;span&gt; c[&amp;#39;builders&amp;#39;].append(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-    util.BuilderConfig(name=&amp;quot;runtests&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-      workernames=[&amp;quot;example-worker&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-      factory=factory))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    util.BuilderConfig(name=&amp;quot;cargo1-runtests&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workernames=[&amp;quot;rust-worker&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      factory=f[&amp;#39;cargo&amp;#39;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      builddir=&amp;#39;builds&#x2F;cargo1&amp;#39;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workerbuilddir=&amp;#39;builds&#x2F;cargo1&amp;#39;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+c[&amp;#39;builders&amp;#39;].append(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    util.BuilderConfig(name=&amp;quot;cargo2-runtests&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workernames=[&amp;quot;rust-worker&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      factory=f[&amp;#39;cargo&amp;#39;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      builddir=&amp;#39;builds&#x2F;cargo2&amp;#39;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workerbuilddir=&amp;#39;builds&#x2F;cargo2&amp;#39;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+c[&amp;#39;builders&amp;#39;].append(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+    util.BuilderConfig(name=&amp;quot;cargo3-runtests&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workernames=[&amp;quot;rust-worker&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      factory=f[&amp;#39;cargo&amp;#39;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      builddir=&amp;#39;builds&#x2F;cargo3&amp;#39;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      workerbuilddir=&amp;#39;builds&#x2F;cargo3&amp;#39;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; ####### STATUS TARGETS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -93,8 +106,8 @@ c[&amp;#39;status&amp;#39;] = []
&lt;&#x2F;span&gt;&lt;span&gt; # the &amp;#39;title&amp;#39; string will appear at the top of this buildbot installation&amp;#39;s
&lt;&#x2F;span&gt;&lt;span&gt; # home pages (linked to the &amp;#39;titleURL&amp;#39;).
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-c[&amp;#39;title&amp;#39;] = &amp;quot;Pyflakes&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-c[&amp;#39;titleURL&amp;#39;] = &amp;quot;https:&#x2F;&#x2F;launchpad.net&#x2F;pyflakes&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+c[&amp;#39;title&amp;#39;] = &amp;quot;Rusty Stuffy&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+c[&amp;#39;titleURL&amp;#39;] = &amp;quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;en-US&#x2F;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt; # the &amp;#39;buildbotURL&amp;#39; string should point to the location where the buildbot&amp;#39;s
&lt;&#x2F;span&gt;&lt;span&gt; # internal web server is visible. This typically uses the port number set in
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And deploy it with this &lt;code&gt;master.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;blogpost&#x2F;robust-master.yaml b&#x2F;blogpost&#x2F;robust-master.yaml
&lt;&#x2F;span&gt;&lt;span&gt;index c7479e3..f75b4d6 100644
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;robust-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;robust-master.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -50,7 +50,7 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_CONFIG_DIR
&lt;&#x2F;span&gt;&lt;span&gt;           value: config
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_CONFIG_URL
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-          value: &amp;#39;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&#x2F;master&#x2F;simple&#x2F;master.cfg&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          value: &amp;#39;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&#x2F;master&#x2F;robust&#x2F;master.cfg&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_WORKER_PORT
&lt;&#x2F;span&gt;&lt;span&gt;           value: &amp;#39;9989&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDBOT_WEB_URL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we look at our setup in Buildbot it looks like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;ample-workload.png&quot; alt=&quot;Buildbot wih ample workload&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When each build is run it completely wipes away the old git clone and starts from scratch, which is &lt;em&gt;suuuper&lt;&#x2F;em&gt; wasteful, but exactly what we want here.
The purpose of this test is to create a heavy workload for our nodes to perform, and with this each build will &lt;em&gt;definitely&lt;&#x2F;em&gt; be heavy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kubectl-autoscale&quot;&gt;kubectl autoscale&lt;&#x2F;h3&gt;
&lt;p&gt;Now to start scaling that build.
In a perfect world we&#x27;d get a request, that would start hogging our resources, and K8s would spin up a new worker instance to handle the next build in the queue.
Based on the output of &lt;code&gt;kubectl --help&lt;&#x2F;code&gt; it looks like &lt;code&gt;kubectl autoscale deployment worker&lt;&#x2F;code&gt; is the command we want... so let&#x27;s do that:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl autoscale deployment worker --max=5 --min=1 --cpu-percent=50
&lt;&#x2F;span&gt;&lt;span&gt;deployment &amp;quot;worker&amp;quot; autoscaled
&lt;&#x2F;span&gt;&lt;span&gt;$ kubectl describe hpa
&lt;&#x2F;span&gt;&lt;span&gt;Name:               worker
&lt;&#x2F;span&gt;&lt;span&gt;Namespace:          default
&lt;&#x2F;span&gt;&lt;span&gt;Labels:             &amp;lt;none&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Annotations:            &amp;lt;none&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;CreationTimestamp:      Fri, 09 Dec 2016 11:13:15 -0800
&lt;&#x2F;span&gt;&lt;span&gt;Reference:          Deployment&#x2F;worker
&lt;&#x2F;span&gt;&lt;span&gt;Target CPU utilization:     50%
&lt;&#x2F;span&gt;&lt;span&gt;Current CPU utilization:    &amp;lt;unset&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Min replicas:           1
&lt;&#x2F;span&gt;&lt;span&gt;Max replicas:           5
&lt;&#x2F;span&gt;&lt;span&gt;Events:
&lt;&#x2F;span&gt;&lt;span&gt;  FirstSeen LastSeen    Count   From                SubobjectPath   Type        Reason          Message
&lt;&#x2F;span&gt;&lt;span&gt;  --------- --------    -----   ----                -------------   --------    ------          -------
&lt;&#x2F;span&gt;&lt;span&gt;  37s       11s     6   {horizontal-pod-autoscaler }            Warning     FailedGetMetrics    failed to get CPU consumption and request: failed to get pods metrics: the server could not find the requested resource (get services http:heapster:)
&lt;&#x2F;span&gt;&lt;span&gt;  37s       11s     6   {horizontal-pod-autoscaler }            Warning     FailedComputeReplicas   failed to get CPU utilization: failed to get CPU consumption and request: failed to get pods metrics: the server could not find the requested resource (get services http:heapster:)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hmm... that output looks like things aren&#x27;t working.
Let&#x27;s look around the internet and see if we find anything useful.
I&#x27;ll go East, you go West, and we&#x27;ll meet back here in 20.&lt;&#x2F;p&gt;
&lt;p&gt;Great, what did you find? Me? Oh I found a bunch of Github issues &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hpa-gh&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and Stack Overflow posts &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hpa-so&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;; lot of people mentioned this Heapster thing.
The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;heapster&quot;&gt;Heapster GitHub page&lt;&#x2F;a&gt; says it does &lt;em&gt;Compute Resource Usage Analysis and Monitoring of Container Clusters&lt;&#x2F;em&gt;, which sounds like what we want.
I also found the &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;horizontal-pod-autoscaling&#x2F;&quot;&gt;K8s Autoscaling&lt;&#x2F;a&gt; docs that point to a &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;horizontal-pod-autoscaling&#x2F;&quot;&gt;K8s Autoscaling Tutorial&lt;&#x2F;a&gt;.
That sounds super useful and confirms the suspicion that Heapster is useful.
&lt;strong&gt;TLDR&lt;&#x2F;strong&gt; things are pointing toward setting up Heapster.&lt;&#x2F;p&gt;
&lt;p&gt;As it turns out there is a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;minikube&#x2F;blob&#x2F;master&#x2F;README.md#add-ons&quot;&gt;Heapster addon for Minikube&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#heapster-release&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, so let&#x27;s get that setup.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ minikube addons enable heapster
&lt;&#x2F;span&gt;&lt;span&gt;heapster was successfully enabled
&lt;&#x2F;span&gt;&lt;span&gt;$ minikube addons open heapster
&lt;&#x2F;span&gt;&lt;span&gt;Opening kubernetes service kube-system&#x2F;monitoring-grafana in default browser...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;hello-heapster.png&quot; alt=&quot;Heapster working&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Neato!&lt;&#x2F;p&gt;
&lt;p&gt;So now we&#x27;ve got Heapster running, what&#x27;s next?&lt;&#x2F;p&gt;
&lt;p&gt;Well the tutorial runs this line:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl run php-apache --image=gcr.io&#x2F;google_containers&#x2F;hpa-example --requests=cpu=200m --expose --port=80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which we can appropriate to get some YAML to shove in our &lt;code&gt;worker.yaml&lt;&#x2F;code&gt; to get a good template for our Buildbot worker Deployment.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl run test --image=busybox --requests=cpu=200m -o yaml
&lt;&#x2F;span&gt;&lt;span&gt;apiVersion: extensions&#x2F;v1beta1
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;spec:
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;span&gt;  template:
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;    spec:
&lt;&#x2F;span&gt;&lt;span&gt;      containers:
&lt;&#x2F;span&gt;&lt;span&gt;      - args:
&lt;&#x2F;span&gt;&lt;span&gt;        ...
&lt;&#x2F;span&gt;&lt;span&gt;        resources:
&lt;&#x2F;span&gt;&lt;span&gt;          requests:
&lt;&#x2F;span&gt;&lt;span&gt;            cpu: 200m
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So I added that section to &lt;code&gt;worker.yaml&lt;&#x2F;code&gt;...&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span&gt;diff --git a&#x2F;blogpost&#x2F;robust-worker.yaml b&#x2F;blogpost&#x2F;robust-worker.yaml
&lt;&#x2F;span&gt;&lt;span&gt;index e57db12..de52320 100644
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--- a&#x2F;blogpost&#x2F;robust-worker.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;+++ b&#x2F;blogpost&#x2F;robust-worker.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;@@ -42,15 +42,18 @@ spec:
&lt;&#x2F;span&gt;&lt;span&gt;         tier: worker
&lt;&#x2F;span&gt;&lt;span&gt;     spec:
&lt;&#x2F;span&gt;&lt;span&gt;       containers:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-      - image: &amp;quot;buildbot&#x2F;buildbot-worker:master&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+      - image: &amp;quot;quay.io&#x2F;elijahcaine&#x2F;buildbot-rust-worker:master&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;         name: worker
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+        resources:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          requests:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+            cpu: 200m
&lt;&#x2F;span&gt;&lt;span&gt;         env:
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDMASTER
&lt;&#x2F;span&gt;&lt;span&gt;           value: master
&lt;&#x2F;span&gt;&lt;span&gt;         - name: BUILDMASTER_PORT
&lt;&#x2F;span&gt;&lt;span&gt;           value: &amp;#39;9989&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;         - name: WORKERNAME
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-          value: example-worker
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;+          value: rust-worker
&lt;&#x2F;span&gt;&lt;span&gt;         - name: WORKERPASS
&lt;&#x2F;span&gt;&lt;span&gt;           value: pass
&lt;&#x2F;span&gt;&lt;span&gt;         - name: WORKER_ENVIRONMENT_BLACKLIST
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;... and ran &lt;code&gt;kubectl replace -f worker.yaml&lt;&#x2F;code&gt;, but did it work?
Well, if you&#x27;re impatient like me you&#x27;ll keep refreshing, it won&#x27;t look like it&#x27;s working, and then you&#x27;ll pull your hair out.
If that happens to you, just wait.
Wait like... a minute.
Just get some tea, stare out the window for a second, &lt;em&gt;then&lt;&#x2F;em&gt; see if it worked or not.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;$ kubectl get hpa worker
&lt;&#x2F;span&gt;&lt;span&gt;NAME              REFERENCE                    TARGET    CURRENT   MINPODS   MAXPODS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;worker            Deployment&#x2F;worker            50%       0%        1         5         2m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There.
That looks good.
Let&#x27;s throw some work at it!&lt;&#x2F;p&gt;
&lt;p&gt;A few builds:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;NAME              REFERENCE                    TARGET    CURRENT   MINPODS   MAXPODS   AGE
&lt;&#x2F;span&gt;&lt;span&gt;worker            Deployment&#x2F;worker            50%       536%      1         5         6m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Great!
Let&#x27;s check up on Buildbot:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;replicas-didnt-work.png&quot; alt=&quot;replication failing&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ruh-roh that&#x27;s not good...&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s dig in a bit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;failed-build.png&quot; alt=&quot;replication failing -- zoom, enhance&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s not good...&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[... end of git pull ...]
&lt;&#x2F;span&gt;&lt;span&gt;75  security_updates_as_of=2016-10-07
&lt;&#x2F;span&gt;&lt;span&gt;76  using PTY: False
&lt;&#x2F;span&gt;&lt;span&gt;77  Cloning into &amp;#39;.&amp;#39;...
&lt;&#x2F;span&gt;&lt;span&gt;78
&lt;&#x2F;span&gt;&lt;span&gt;79  command interrupted, attempting to kill
&lt;&#x2F;span&gt;&lt;span&gt;80  process killed by signal 15
&lt;&#x2F;span&gt;&lt;span&gt;81  program finished with exit code -1
&lt;&#x2F;span&gt;&lt;span&gt;82  elapsedTime=2.051445
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;[... entirety of &amp;#39;cancelled&amp;#39; logs ...]
&lt;&#x2F;span&gt;&lt;span&gt;0  no reason
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well, it looks like that plan didn&#x27;t work.&lt;&#x2F;p&gt;
&lt;p&gt;I did a bit more digging and I can say with certainty that the approach I took to scaling the workload did &lt;em&gt;not&lt;&#x2F;em&gt; work.
I can&#x27;t say &lt;em&gt;why&lt;&#x2F;em&gt; for sure, and I definitely can&#x27;t say how to fix it, but honestly... it&#x27;s late.
I&#x27;m tired and right now I&#x27;m okay with throwing in the towel for now.
Maybe we&#x27;ll solve this in a &lt;strong&gt;Part 2&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;debrief&quot;&gt;Debrief&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;First: This blogpost has a repo associated with it: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elijahcaine&#x2F;buildbot-on-kubernetes&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;elijahcaine&#x2F;buildbot-on-kubernetes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Please check that out, see what it has to offer, and make issues&#x2F;pull requests.
Right now it&#x27;s just a copy of the configs used in this project and a little bit of documentation.&lt;&#x2F;p&gt;
&lt;p&gt;Happy hacking!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;m terrible at endings so I&#x27;m just gonna braindump some stuff here and let you, the beautiful and charming reader, find your own closure from all of this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;failure-its-what-s-on-the-menu&quot;&gt;Failure: its what&#x27;s on the menu&lt;&#x2F;h3&gt;
&lt;p&gt;That&#x27;s right, I didn&#x27;t do what I set out to achieve.
Is that a bad thing?
&lt;strong&gt;Of course not!&lt;&#x2F;strong&gt; To quote the great Jake the Dog:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;buildbot-on-k8s&#x2F;sucking-quote.jpg&quot; alt=&quot;Sucking at something is the first step to being kinda good at something&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Sure we didn&#x27;t get the &lt;em&gt;perfect&lt;&#x2F;em&gt; BuildBot+K8s but we learned a ton and got &lt;em&gt;really&lt;&#x2F;em&gt; close!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-stuff-we-learned&quot;&gt;Some stuff we learned&lt;&#x2F;h3&gt;
&lt;p&gt;So what are some things we learned that we should probably write down?
This is a pretty open question and if you followed along you&#x27;ll &lt;em&gt;probably&lt;&#x2F;em&gt; get a drastically different list than I have.
Here&#x27;s the big things I feel like I&#x27;m walking away with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl &amp;lt;command&amp;gt; --dry-run -o yaml&lt;&#x2F;code&gt; is very useful for file-izing your infrastructure.&lt;&#x2F;li&gt;
&lt;li&gt;K8s is very well documented &lt;strong&gt;if&lt;&#x2F;strong&gt; you are a very patient individual.&lt;&#x2F;li&gt;
&lt;li&gt;Storage in K8s is still not a perfectly solved problem [^storage].&lt;&#x2F;li&gt;
&lt;li&gt;K8s applications share private networking.&lt;&#x2F;li&gt;
&lt;li&gt;K8s Pods are really just containers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;m sure there&#x27;s a ton more I&#x27;ve internalized and can&#x27;t recall.
I tried to take thorough notes during this entire experience to capture the failures as well as the successes, which is a harder skill than I expected.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;useful-resources&quot;&gt;Useful resources&lt;&#x2F;h3&gt;
&lt;p&gt;Beyond searching for specific answers these are &lt;em&gt;honestly&lt;&#x2F;em&gt; the websites I kept going back to throughout this project.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;&quot;&gt;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;&lt;&#x2F;a&gt; The main K8s docs.
A bit dense and sparse in key areas, a problem I&#x27;m actively I&#x27;m working on.
Includes API docs and user-guides which are useful for those patient enough to read them.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;k8s.info&#x2F;&quot;&gt;http:&#x2F;&#x2F;k8s.info&#x2F;&lt;&#x2F;a&gt; A community-run resource with some useful links and a &#x27;cheat sheet&#x27;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;community&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;community&lt;&#x2F;a&gt; Includes a bunch of very useful design documentation.
I&#x27;m not usually the kind of person that enjoys reading design docs, but sometimes a feature is too new to have a usable user-guide.
When it&#x27;s the best you&#x27;ve got, take it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As far as Buildbot-specific stuff I honestly just used the &lt;a href=&quot;https:&#x2F;&#x2F;docs.buildbot.net&#x2F;current&#x2F;&quot;&gt;official Buildbot docs&lt;&#x2F;a&gt; which were more than enough.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;whats-next&quot;&gt;Whats next?&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m sure I&#x27;ll be posting more about K8s going forward.
It is a very useful tool because of&#x2F;despite it&#x27;s complexities.
As I use it I&#x27;ll post more about it.&lt;&#x2F;p&gt;
&lt;p&gt;If you have any feedback on this post feel free to get in contact with me &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;pastywhitenoise&quot;&gt;@PastyWhiteNoise&lt;&#x2F;a&gt; on Twitter, &lt;code&gt;pop&lt;&#x2F;code&gt; on &lt;a href=&quot;https:&#x2F;&#x2F;webchat.freenode.net&#x2F;&quot;&gt;irc.freenode.net&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#irc&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, you can make an issue on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;elijahcaine&#x2F;elijahcaine.github.io&quot;&gt;this website&#x27;s Github Repository&lt;&#x2F;a&gt;, and of course I can be reached by Carrier Pigeon..&lt;&#x2F;p&gt;
&lt;h2 id=&quot;errata&quot;&gt;Errata&lt;&#x2F;h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;GIFEE&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Google Infrastructure for Everyone Else&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;accompanying-repo&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ElijahCaine&#x2F;buildbot-on-kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;docs-should&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;My job, at least a big part of it, is writing documentation.
Docs are a notable part of my identify, and I have a belief in the power of good documentation, but at the end of the day they &lt;strong&gt;are&lt;&#x2F;strong&gt; just a means to an end.&lt;&#x2F;p&gt;
&lt;p&gt;In a perfect world docs wouldn&#x27;t &lt;em&gt;need&lt;&#x2F;em&gt; to exist, so all docs should be enough to get whoever&#x27;s readin them to the point where they can do cool shit on their own.
Just like a great cinematographer is so good you don&#x27;t notice the camera in a movie, great docs should be so good you don&#x27;t &lt;strong&gt;notice&lt;&#x2F;strong&gt; how good they are.&lt;&#x2F;p&gt;
&lt;p&gt;So that&#x27;s why I like &lt;strong&gt;doing&lt;&#x2F;strong&gt; cool shit over &lt;strong&gt;reading&lt;&#x2F;strong&gt; about it.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also fun to play with toys! Even if those toys are software.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;heapster-release&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;Authors Note: The heapster addon was added to Minikube &lt;strong&gt;during the writing of this post&lt;&#x2F;strong&gt;. How convenient!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hpa-gh&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openshift&#x2F;origin&#x2F;issues&#x2F;6239&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;openshift&#x2F;origin&#x2F;issues&#x2F;6239&lt;&#x2F;a&gt; - &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;issues&#x2F;18652&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;issues&#x2F;18652&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hpa-so&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;38874145&#x2F;autoscaling-hpa-failed-to-get-cpu-consumption-cannot-unmarshal-object-into-go&quot;&gt;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;38874145&#x2F;autoscaling-hpa-failed-to-get-cpu-consumption-cannot-unmarshal-object-into-go&lt;&#x2F;a&gt; - &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;37631008&#x2F;kubernetes-hpa-cannot-get-cpu-consumption&quot;&gt;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;37631008&#x2F;kubernetes-hpa-cannot-get-cpu-consumption&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;irc&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;I usually hang out in the &lt;code&gt;#osu-lug&lt;&#x2F;code&gt; channel. They&#x27;re cool people, you should hang out with us!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;same-app-note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;It wasn&#x27;t painfully obvious to me so it&#x27;s worth elaborating that for K8s services to communicate with one-another they need to be part of the same &lt;code&gt;app&lt;&#x2F;code&gt;. In the example the &lt;code&gt;postgres&lt;&#x2F;code&gt;, &lt;code&gt;worker&lt;&#x2F;code&gt;, and &lt;code&gt;master&lt;&#x2F;code&gt; containers are all part of the same &lt;code&gt;buildbot&lt;&#x2F;code&gt; app.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a terribly well documented &lt;strong&gt;key&lt;&#x2F;strong&gt; piece of information so it
seemed worth mentioning.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;storge&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;But neither is storage in general so who can blame &#x27;em?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;theory-vs-practice&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;If you read that and thought &quot;You know what they say about theory versus
practice!&quot; then &lt;em&gt;yes&lt;&#x2F;em&gt; -- but you&#x27;re getting ahead of me.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;why&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Might as well clarify &lt;em&gt;why&lt;&#x2F;em&gt; we want persistent storage and auto-scaling
since these are usually desired features in an orchestrator but nobody
explains &lt;em&gt;why&lt;&#x2F;em&gt; they&#x27;re desireable.&lt;&#x2F;p&gt;
&lt;p&gt;Autoscaling:
Autoscaling is important is because we&#x27;ve got a whole data-center (in
theory) and we want to maximize how we use that data-center&#x27;s
computational abilities. In a perfect world we would use exactly as much
of the data-center as is demanded by users, but in practice this is
super hard!&lt;&#x2F;p&gt;
&lt;p&gt;Say your website gets linked on Hacker News, you get tons of requests
pouring in, but your poor little 2004 server falls on it&#x27;s face when you
&lt;em&gt;look&lt;&#x2F;em&gt; at it wrong, and &lt;strong&gt;that&lt;&#x2F;strong&gt; is where the exact page was hosted. If
you don&#x27;t &lt;strong&gt;know&lt;&#x2F;strong&gt; that server fell down you&#x27;ll never fix the problem or
even &lt;strong&gt;know&lt;&#x2F;strong&gt; about the problem.&lt;&#x2F;p&gt;
&lt;p&gt;With an orchestrator we can (in theory) specify how much we want to
utilize a our data-center&#x27;s resources and under what conditions we want
to use more or less resources. If our service is creating a light load,
only have one container up; if it&#x27;s got a metric fuck-ton then spin up
20 containers across our entire cluster. You say what you want and the
load-balancer + scheduler + monitor take care of the rest.&lt;&#x2F;p&gt;
&lt;p&gt;Persistent Storage:
The reason persistent storage is a useful feature is for two reasons&lt;&#x2F;p&gt;
&lt;p&gt;The first is that containers are ephemeral. They can be created,
destroyed, and upgraded &lt;em&gt;all&lt;&#x2F;em&gt; the time, basically making them the polar
opposite of a &#x27;Special Snowflake&#x27; service.&lt;&#x2F;p&gt;
&lt;p&gt;This is nice, but what about state? As nice as it&#x27;d be to make an
entirely stateless data-center, cat pictures and builds aren&#x27;t going to
store themselves!&lt;&#x2F;p&gt;
&lt;p&gt;The solution to this problem is -- well it&#x27;s not solved, but there&#x27;s a
clear direction things are going in. The TLDR is that we create some
block device in the cloud and mount it to each identical container at
the same mount-point, so each container (K8s &#x27;Pod&#x27;) shares some amount
of state. Sorta like... I&#x27;m bad at examples actually. I&#x27;ll think of one
eventually.&lt;&#x2F;p&gt;
&lt;p&gt;Piggy-backing off of this, not only do we preserve state between
container upgrades&#x2F;deletes&#x2F;additions, but we can also share state
between scaled services (i.e., a set of identical containers across a
datacenter). Essentially we can have one worker pod carry out a build
and another pod perform some action on that build (uploading it, verify
it, archive it, etc). When the first worker pod gets deleted the build
lives on in the shared state.&lt;&#x2F;p&gt;
&lt;p&gt;This allows us to treat our state the same way we treat computing
resources in the world of GIFFEE&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;GIFEE&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Create some block device for the service, mount it to this point, and let your orchestrator take care of the rest.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Lady Wangle</title>
        <published>2016-09-14T00:00:00+00:00</published>
        <updated>2016-09-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/lady-wangle/"/>
        <id>https://elijah.run/fiction/lady-wangle/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/lady-wangle/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A baroness looks at the Mona Lisa and sees her newborn baby in the background.
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;768207599468634113&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Lady Wangle (of the prestigious Canadian Royalty) flew to the Louvre for her 27th birthday.
In past visits she had always marveled at the beautiful marble statutes, historic illustrations, and the grandiose building itself.
She always loved the glass pyramid, even if she didn&#x27;t really see how it fit with the rest of the architecture.
The Louvre was a special place in her heart.&lt;&#x2F;p&gt;
&lt;p&gt;She wanted to bring her newborn daughter &lt;em&gt;Anna&lt;&#x2F;em&gt; with but her husband &lt;em&gt;Harold&lt;&#x2F;em&gt; was concerned about the baby flying only two months after being born.
L.W. offered to cancel the trip but he insisted that she go saying &lt;em&gt;&quot;Sweetie, you&#x27;ve been taking care of this baby for nine months. You can take a week off.
You deserve it.&quot;&lt;&#x2F;em&gt; L.W. wasn&#x27;t one to fight over things like this so she packed for a three-day trip and went off to Paris.&lt;&#x2F;p&gt;
&lt;p&gt;As an early riser, or perhaps just a jet-lagged riser -- she always wanted to be an early riser but it wasn&#x27;t in her genes.
Regardless, she was up early.
She didn&#x27;t like the dark of mid January mornings, but that animosity was more or less evened out by her love of being alone in the quiet frigid winter air.
She saw that the museum wouldn&#x27;t open for another two hours and so she adventured toward the big Ferris Wheel East of the museum.
She ultimately intended to walk by the riverfront but settled for seeing some sights first. She hadn&#x27;t been to Paris in many years and was curious to see how it had changed.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;To her disappointment nothing had really changed in Paris.
She supposed that was part of the charm; it was tastefully timeless.
One could come back year after year and get the same Paris they&#x27;d gotten before.
Friends could visit separately and talk about some hole-in-the-wall cafe they&#x27;d found independent of one-another.
Any city built on a certain level of tourism &lt;strong&gt;had&lt;&#x2F;strong&gt; to keep the high-lights stable.&lt;&#x2F;p&gt;
&lt;p&gt;The museum opened and a small line had started to form.
She got in line and held idle chit-chat with a couple from Dallas, Texas.
Their names were Jeffery and Matilda Almond.
They were eager to share that this was their way of celebrating their 30th Anniversary with &lt;em&gt;&#x27;the honeymoon they never had&#x27;&lt;&#x2F;em&gt;.
L.W. asked who was partial to seeing the Louvre to which Jeff proudly exclaimed &lt;em&gt;&quot;It was all Matilda.
She got a degree in ART ya&#x27; know -- she&#x27;s real smart.
Most of this stuff goes way over my head but she&#x27;s there to explain it to me.&quot;&lt;&#x2F;em&gt; Matilda blushed, she was the quiet one and Jeff was the loud one of the pair, but she could tell they got along anyway.
L.W. smiled at this and with that the conversation awkwardly petered out.&lt;&#x2F;p&gt;
&lt;p&gt;L.W. always made a bee-line for the Mona Lisa when she went to the Louvre.
She made the mistake of meandering there on one of her trips but by the time she got to it it was too crowded (&lt;em&gt;only two hours after opening!&lt;&#x2F;em&gt;) to see it. She raced all of the Asian tourist families with their massive &lt;em&gt;Canon DSLR&lt;&#x2F;em&gt; cameras and was one of the first pairs of eyes to see it that day. She took it all in, noting yet again how much smaller it looks in real-life.&lt;&#x2F;p&gt;
&lt;p&gt;Wave after wave she took the piece in.
She knew there were better paintings in the Louvre but something resonated with her about the &lt;em&gt;Mona Lisa&lt;&#x2F;em&gt;.
Something was special, some connection... was that... was that Anna in the background?
L.W. peered at the piece and realized that an exact replication of her daughter --&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I&#x27;m sorry reader.
I can&#x27;t do it.
I built this up too much and now... now the ... I&#x27;m not even sure what to call it.
The punchline?
It doesn&#x27;t make any sense.
I know the point of the MagicRealismBot stories isn&#x27;t to make something that &lt;em&gt;makes sense&lt;&#x2F;em&gt; in a logical sense, but like... it should at least be &lt;em&gt;consistent&lt;&#x2F;em&gt; and actions should be justified.
I&#x27;m not trying to write an &lt;strong&gt;&#x27;and then&#x27;&lt;&#x2F;strong&gt; story I&#x27;m trying to write a &lt;strong&gt;&#x27;therefore, and so&#x27;&lt;&#x2F;strong&gt; story.&lt;&#x2F;p&gt;
&lt;p&gt;I apologize.
This was just a bad story to begin with.
I avoided the prompt for the majority of it anyway.
I even ignored that I had started this for almost three weeks, hoping I&#x27;d come back and the story would magically &lt;em&gt;become better&lt;&#x2F;em&gt;.
I know that&#x27;s not &lt;em&gt;necessarily&lt;&#x2F;em&gt; a bad thing, but in this case it wasn&#x27;t a good sign -- delaying the inevitable usually means one is dread it.
That is kind of a necessity with these, take what you like from a prompt and push the rest to the side, barely quantifying the thing as &#x27;written from the prompt&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I&#x27;m rambling now.
Thank you for reading, it means a lot.
I&#x27;ll try to do something more -- I don&#x27;t know -- &lt;strong&gt;more better&lt;&#x2F;strong&gt; in the future.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Conceptual hurdles in programming</title>
        <published>2016-08-21T00:00:00+00:00</published>
        <updated>2016-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/programming-hurdles/"/>
        <id>https://elijah.run/blog/programming-hurdles/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/programming-hurdles/">&lt;p&gt;I&#x27;ve been actively learning programming for almost five years now.
I started by taking a C++ class at Portland Community College.
That class was the best thing to happen to my engineering career because it taught me that &lt;em&gt;programming is very hard, and I am not naturally good at it&lt;&#x2F;em&gt;, but it was also very rewarding so I stuck with it.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not special either, most of us aren&#x27;t very good at programming because it&#x27;s so abstract and hard to grasp, like Math and Infinite Jest.
There are of course the people that seem like &lt;em&gt;programming gods&lt;&#x2F;em&gt;, but nine times out of ten those people have been programming since they were eight and it&#x27;s really not fair to compare yourself to them.
That&#x27;s like comparing your sporting abilities to &lt;em&gt;any olympic athlete&lt;&#x2F;em&gt;.
Don&#x27;t be so hard on yourself.&lt;&#x2F;p&gt;
&lt;p&gt;In learning to program, and now teaching others how to program, I&#x27;ve identified a few &lt;strong&gt;hurdles&lt;&#x2F;strong&gt; (mountains, cliffs, obstacles, w&#x2F;e) that folks tend to hit and have trouble crossing.
They always get past these hurdles eventually (or they quit CS ☹), but not without a bit of unnecessary struggle.
Struggling builds character, and I don&#x27;t want to cheat anybody out of that, but I do want to help those that want it.&lt;&#x2F;p&gt;
&lt;p&gt;This post will in no way guarantee your success in overcoming these obstacles but it should at least give you a head start to help you understand what you&#x27;re learning and point you in the right direction when you want to ask a question.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-structures&quot;&gt;Data Structures&lt;&#x2F;h2&gt;
&lt;p&gt;Understanding that &lt;strong&gt;a lot of programming is basically manipulating data to fit a need&lt;&#x2F;strong&gt; is pretty important.
A social network can be thought of as a bunch of people&#x27;s personal information plugged into a bunch of algorithms to make connecting easier.
A word processor is really just a front-end for some &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Microsoft_Office_XML_formats&quot;&gt;XML under the hood&lt;&#x2F;a&gt;, which is itself &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;XML&quot;&gt;just a way to represent structured data&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When handling data try to keep in mind what you are trying to accomplish and the best way to structure the data in the pursuit of that goal.&lt;&#x2F;p&gt;
&lt;span class=&quot;define&quot;&gt;
    &lt;span class=&quot;define-word&quot;&gt;
        &amp;lt;a href=&amp;quot;https:&amp;#x2F;&amp;#x2F;en.wikipedia.org&amp;#x2F;wiki&amp;#x2F;Array_data_structure&amp;quot;&amp;gt;Arrays&amp;#x2F;Lists&amp;#x2F;Vectors&amp;lt;&amp;#x2F;a&amp;gt;
    &lt;&#x2F;p&gt;

    &lt;span class=&quot;define-body&quot;&gt;
        &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Arrays and Lists are an ordered data type&amp;lt;&amp;#x2F;strong&amp;gt;. Use them when you need to
keep track of the order things happened in, like queuing an event.
Try to keep them &amp;lt;em&amp;gt;relatively small&amp;lt;&amp;#x2F;em&amp;gt; since they are fast for retrieval but not inherently space efficient.&amp;lt;&amp;#x2F;p&amp;gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;{% define(word=&quot;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hash_table&quot;&gt;Hash-table&#x2F;Key-Value&#x2F;Dictionary&lt;&#x2F;a&gt;&quot; %}
&lt;strong&gt;Hashes are useful for storing unordered data&lt;&#x2F;strong&gt; with keys, like an address book or a small database.
We use them to access data quickly and easily since data is retrieved using a key and always takes approximately the same amount of time.
When you get data out of a dictionary you provide a key and get back the associated data, just like (you guessed it) &lt;em&gt;a real dictionary&lt;&#x2F;em&gt; where provided the word you get back a definition.&lt;&#x2F;p&gt;
&lt;p&gt;Hash-tables are useful tools but should only be used for &lt;em&gt;relatively small&lt;&#x2F;em&gt; amounts of data.
There is a bit of overhead in creating the table for storing your data so if your data-set gets too big you&#x27;ll run out of memory.
{% end %}&lt;&#x2F;p&gt;
&lt;span class=&quot;define&quot;&gt;
    &lt;span class=&quot;define-word&quot;&gt;
        &amp;lt;a href=&amp;quot;https:&amp;#x2F;&amp;#x2F;en.wikipedia.org&amp;#x2F;wiki&amp;#x2F;Linked_list&amp;quot;&amp;gt;Linked Lists&amp;#x2F;Sorted Trees&amp;lt;&amp;#x2F;a&amp;gt;
    &lt;&#x2F;p&gt;

    &lt;span class=&quot;define-body&quot;&gt;
        &amp;lt;p&amp;gt;Linked Lists and Sorted Trees aren&amp;#x27;t exactly the same thing but I&amp;#x27;m lumping them together because they both deal with a lot of the same concepts and can be implemented in similar ways.
In learning about LL&amp;#x2F;ST you&amp;#x27;ll probably deal with Structs, Nodes, Pointers, and dynamic memory allocation, which if you&amp;#x27;re like me will totally break your brain and then become second-nature.&amp;lt;&amp;#x2F;p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;One advantage to these structures is that they can be implemented to take up only the space they require&amp;lt;&amp;#x2F;strong&amp;gt;.
Where Hash-maps and lists are hard to make the &amp;lt;em&amp;gt;right size&amp;lt;&amp;#x2F;em&amp;gt;, LL&amp;#x2F;ST can only take up exactly as much room as they need.
The trade-off (a word you hear a lot when dealing choosing data structures) is that they&amp;#x27;re not always the &amp;lt;em&amp;gt;fastest&amp;lt;&amp;#x2F;em&amp;gt; way to store&amp;#x2F;retrieve data.
Just consider your use-case and think about what you need for the task at hand.&amp;lt;&amp;#x2F;p&amp;gt;
&amp;lt;p&amp;gt;If you&amp;#x27;re interested in learning Rust though there&amp;#x27;s a great guide on &amp;lt;a href=&amp;quot;http:&amp;#x2F;&amp;#x2F;cglab.ca&amp;#x2F;~abeinges&amp;#x2F;blah&amp;#x2F;too-many-lists&amp;#x2F;book&amp;#x2F;README.html&amp;quot;&amp;gt;Learning Rust With Entirely Too Many Linked Lists&amp;lt;&amp;#x2F;a&amp;gt;.
I do suggest it.&amp;lt;&amp;#x2F;p&amp;gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;&lt;strong&gt;These are all just the structures you&#x27;re giving your data&lt;&#x2F;strong&gt; (a series of ones and zeros on disk and in memory).
Anybody that&#x27;s done work with a sufficiently complicated project (e.g., the Linux Kernel) can tell you that one glob of data can be treated as a Linked List, Array, Hash -- or all three at the same time!
The structure you give your data is just so &lt;em&gt;you&lt;&#x2F;em&gt; can work with it, the computer doesn&#x27;t really care one way or another, so choose what makes the most sense.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Speaking of data structures...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;objects-classes&quot;&gt;Objects&#x2F;Classes&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Objects are logical groupings of data (variables) and functions that act on that data&lt;&#x2F;strong&gt;.
They differ from structs in that they are (usually) private by default, meaning that variables declared in an object are not accessible from the &lt;em&gt;outside&lt;&#x2F;em&gt; unless you explicitly say so.
Variables are usually manipulated via a method called a &lt;em&gt;getter&lt;&#x2F;em&gt; and &lt;em&gt;setter&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Well... what I&#x27;ve actually described so far is creating a &lt;strong&gt;class: aka a blueprint for an object&lt;&#x2F;strong&gt;.
This python is a pretty succinct way to describe classes and objects:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;objects_example.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;Declare a class named BazClass.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;text-decoration:underline;color:#8cdaff;&quot;&gt;BazClass&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;text-decoration:underline;font-style:italic;color:#8cdaff;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;__init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;        The __init__ function sets class variables and sets up the object.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.var1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;x
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.var2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;6
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;        a() acts on the object variables (accessed via `self`).
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Variable you set &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.var1))
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Variable set by class definition &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.var2))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;Creating an instance of the class and call the `a()` function.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;foo_object &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;BazClass&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;foo_object.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Objects are something that will &lt;em&gt;click&lt;&#x2F;em&gt; after you use the for a while.
There&#x27;s some nuances and implementation quirks depending on the language you&#x27;re using, but in the end they&#x27;re just logical collections of private data and functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;functional-programming&quot;&gt;Functional Programming&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Functional_programming&quot;&gt;Functional Programming&lt;&#x2F;a&gt; (FP) was my first big paradigm shift in CS since functions. FP includes concepts of variable immutability (once it&#x27;s set it&#x27;s set), callbacks (functions calling functions and propagating results up), program state -- the list goes on. Here&#x27;s an example to get us started.&lt;&#x2F;p&gt;
&lt;p&gt;Non-functional paradigm:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;average_evens&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;avg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.length; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;avg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;avg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;avg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.length;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;avg&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Functional Paradigm:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;average_evens&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;reduce&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.length;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the non-functional example one would create a variable, iterate with a for-loop, and return a variable at the end.
In the functional example you call functions which return data that you handle (callback) and that result is added to or replaces the original data. I&#x27;m honestly not doing this topic justice but it&#x27;s one of those things you either learn first or you learn the hard way.&lt;&#x2F;p&gt;
&lt;p&gt;This is just the tip of the ice-berg; many people prefer functional programming.
If you are even remotely interested you should find one of those people and let them talk your ear off.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re learning functional programming I suggest either &lt;a href=&quot;http:&#x2F;&#x2F;learnyouahaskell.com&#x2F;chapters&quot;&gt;Learn You a Haskell for Great Good&lt;&#x2F;a&gt; if you&#x27;re interested in learning Haskell (which is interesting an interesting language if nothing else) or &lt;a href=&quot;http:&#x2F;&#x2F;www.oreilly.com&#x2F;programming&#x2F;free&#x2F;functional-programming-python.csp&quot;&gt;Functional Programming in Python&lt;&#x2F;a&gt; for &lt;em&gt;pythonistas&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;frameworks&quot;&gt;Frameworks&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Frameworks are a collection of libraries, methods, and tools to accomplish a specific type of task&lt;&#x2F;strong&gt;.
If you want to get something &lt;em&gt;complicated&lt;&#x2F;em&gt; done &lt;em&gt;fast&lt;&#x2F;em&gt;, you&#x27;ll use a framework.
Take for instance a web-app like Facebook or Twitter: it needs to be able to &lt;em&gt;send&#x2F;receive HTTP requests&lt;&#x2F;em&gt;, &lt;em&gt;interface with a database&lt;&#x2F;em&gt; &#x2F; &lt;em&gt;craft database queries&lt;&#x2F;em&gt;, &lt;em&gt;render web-pages&lt;&#x2F;em&gt;, &lt;em&gt;and&lt;&#x2F;em&gt; whatever the actual website is supposed to do.&lt;&#x2F;p&gt;
&lt;p&gt;Frameworks can be very small or very large but they are always a big hurdle for those of us that have never worked with one before.
A good starter framework I suggest is &lt;a href=&quot;http:&#x2F;&#x2F;flask.pocoo.org&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt; for Python-based web-apps.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Testing is writing a program to test your program&lt;&#x2F;strong&gt;.
There are many different &lt;em&gt;kinds&lt;&#x2F;em&gt; of tests from &lt;em&gt;unit tests&lt;&#x2F;em&gt; (checking single functions), to &lt;em&gt;integration tests&lt;&#x2F;em&gt; (checking that your functions work &lt;em&gt;together&lt;&#x2F;em&gt;), to &lt;em&gt;random tests&lt;&#x2F;em&gt; (trying to break your program by telling a computer to break your functions by using they in weird ways).&lt;&#x2F;p&gt;
&lt;p&gt;Remember that first program you wrote for class?
You wrote one that prompted the user for data and then manipulated that input in some way?
Remember how you tested that?
Probably in the most tedious way imaginable: &lt;strong&gt;by hand&lt;&#x2F;strong&gt;.
Tests are much easier to write than your actual code and while they&#x27;re a tedious investment up-front it&#x27;s a small commitment relative to the &lt;em&gt;hours&lt;&#x2F;em&gt; you&#x27;d spend checking your program every time you made a change.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;&#x2F;h2&gt;
&lt;p&gt;The last thing isn&#x27;t really about programming but about &lt;em&gt;fixing&lt;&#x2F;em&gt; your programming.
When you&#x27;re learning a new paradigm, language, or framework you&#x27;re going to spend a lot of time &lt;em&gt;fixing&lt;&#x2F;em&gt; what doesn&#x27;t currently work much more than you&#x27;re going to actually be producing working code.
This skill can also be summed up as &#x27;How to Read Error Messages and Google well&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;My troubleshooting advice is to &lt;em&gt;read&lt;&#x2F;em&gt; the error message, don&#x27;t give up, and search for anything that looks meaningful.
Once you find an answer try to &lt;em&gt;grok&lt;&#x2F;em&gt; what the answer means so you can learn &lt;em&gt;why&lt;&#x2F;em&gt; that worked instead of knowing &lt;em&gt;if I type this in a certain way it will not fall down&lt;&#x2F;em&gt;.
Future you will appreciate the investment you put into &lt;em&gt;understanding&lt;&#x2F;em&gt; the problem and it&#x27;s solution.&lt;&#x2F;p&gt;
&lt;p&gt;Also don&#x27;t be afraid to experiment. Make a copy of your program (or use &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;git&lt;&#x2F;a&gt;) and see if some crazy idea is exactly what you need.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;This list is far from complete but it still felt worth sharing.
If you think I missed something, &lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;about&#x2F;#contact&quot;&gt;contact me&lt;&#x2F;a&gt; and I might do a follow-up post.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The MoonStone discovery</title>
        <published>2016-08-19T00:00:00+00:00</published>
        <updated>2016-08-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/moonstone-discovery/"/>
        <id>https://elijah.run/fiction/moonstone-discovery/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/moonstone-discovery/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;By looking at a fireplace, a medieval sorcerer can turn stone into
moonstones.
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;766606956295356420&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Ellyn scrambled to take notes as fast as she could.
She had finally found a way to produce &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; and it would change &lt;em&gt;everything&lt;&#x2F;em&gt;!
With &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; one could turn sand into gold, the living into the dead, and countless other &lt;em&gt;theoretical&lt;&#x2F;em&gt; properties she had read of.
Now that she was able to produce that which had alluded sorcerers since the dawn of knowledge the sky was the limit.&lt;&#x2F;p&gt;
&lt;p&gt;She took her quill and parchment and wrote furiously.
She described in great detail the position of the Sun in the Sky, the time of year, where she stood in the room and where the room stood on Earth.
She knew every detail wouldn&#x27;t be important but every detail &lt;em&gt;could&lt;&#x2F;em&gt; be so they all must be recorded.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;Standing my robes, staring intently at 12 BoilingRocks in the fireplace, facing head-first at the display.&lt;&#x2F;li&gt;
&lt;li&gt;The sun stands high in a Summer&#x27;s fore-noon, just glancing through the window unto the fireplace.&lt;&#x2F;li&gt;
&lt;li&gt;After the duration of approximately three Hail Mary&#x27;s the stones turned white and fragile.&lt;&#x2F;li&gt;
&lt;li&gt;The rocks no-doubt turned into &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt; as was theorized.
Their shape and texture proves it so.
&lt;ul&gt;
&lt;li&gt;The MoonStones glow faint white, matte and with hints of spiritual aura.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt; weigh substantially less than the BoilingRocks did, perhaps losing mass in the process of transformation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As she finished writing her findings she grabbed her wax and seal and marked it to be delivered to her mentor Rowan.
He had spent the better part of his long life (&lt;em&gt;76 years young!&lt;&#x2F;em&gt;) attempting to find the secret to producing &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; from earthly materials but had come up empty-handed.
Ellyn felt proud of her findings and was glad to be able to share it with Rowan.&lt;&#x2F;p&gt;
&lt;p&gt;Moments later Ellyn sent off her findings with a sample of the &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; via the local carrier.
She told him to &lt;em&gt;take it with haste to Rowan&lt;&#x2F;em&gt; and gave the carrier an extra copper piece in hopes that he would.
The carrier ran off down the road, the journey was almost a quarter day&#x27;s travel so Ellyn returned to her study.&lt;&#x2F;p&gt;
&lt;p&gt;As she sat in wait studying the &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt;, she grew weary of her findings.
Just a moment ago she was so sure of her discovery, but now that she had sent off the finding she became... hesitant.
Was this &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; or perhaps the similar &lt;em&gt;SilverStone&lt;&#x2F;em&gt;.
&lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; was only theoretical, studied in the mind and never before in the hand; it had never been proven to exist so what made her so sure that &lt;em&gt;this rock&lt;&#x2F;em&gt; was what they had been searching for.
She was, after all, just an apprentice sorcerer; what did she know?
If Rowan determined her findings untrue what would stop him from revoking his mentor ship?
Her years of study would be for naut.&lt;&#x2F;p&gt;
&lt;p&gt;Ellyn had always been prone to worry.
She took a deep breath and with nothing else to do, she sat in wait.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The MoonStone discovery</title>
        <published>2016-08-19T00:00:00+00:00</published>
        <updated>2016-08-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/the-moonstone-discovery/"/>
        <id>https://elijah.run/fiction/the-moonstone-discovery/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/the-moonstone-discovery/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;By looking at a fireplace, a medieval sorcerer can turn stone into
moonstones.
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;766606956295356420&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Ellyn scrambled to take notes as fast as she could.
She had finally found a way to produce &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; and it would change &lt;em&gt;everything&lt;&#x2F;em&gt;!
With &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; one could turn sand into gold, the living into the dead, and countless other &lt;em&gt;theoretical&lt;&#x2F;em&gt; properties she had read of.
Now that she was able to produce that which had alluded sorcerers since the dawn of knowledge the sky was the limit.&lt;&#x2F;p&gt;
&lt;p&gt;She took her quill and parchment and wrote furiously.
She described in great detail the position of the Sun in the Sky, the time of year, where she stood in the room and where the room stood on Earth.
She knew every detail wouldn&#x27;t be important but every detail &lt;em&gt;could&lt;&#x2F;em&gt; be so they all must be recorded.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;Standing my robes, staring intently at 12 BoilingRocks in the fireplace, facing head-first at the display.&lt;&#x2F;li&gt;
&lt;li&gt;The sun stands high in a Summer&#x27;s fore-noon, just glancing through the window unto the fireplace.&lt;&#x2F;li&gt;
&lt;li&gt;After the duration of approximately three Hail Mary&#x27;s the stones turned white and fragile.&lt;&#x2F;li&gt;
&lt;li&gt;The rocks no-doubt turned into &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt; as was theorized.
Their shape and texture proves it so.
&lt;ul&gt;
&lt;li&gt;The MoonStones glow faint white, matte and with hints of spiritual aura.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt; weigh substantially less than the BoilingRocks did, perhaps losing mass in the process of transformation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As she finished writing her findings she grabbed her wax and seal and marked it to be delivered to her mentor Rowan.
He had spent the better part of his long life (&lt;em&gt;76 years young!&lt;&#x2F;em&gt;) attempting to find the secret to producing &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; from earthly materials but had come up empty-handed.
Ellyn felt proud of her findings and was glad to be able to share it with Rowan.&lt;&#x2F;p&gt;
&lt;p&gt;Moments later Ellyn sent off her findings with a sample of the &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; via the local carrier.
She told him to &lt;em&gt;take it with haste to Rowan&lt;&#x2F;em&gt; and gave the carrier an extra copper piece in hopes that he would.
The carrier ran off down the road, the journey was almost a quarter day&#x27;s travel so Ellyn returned to her study.&lt;&#x2F;p&gt;
&lt;p&gt;As she sat in wait studying the &lt;strong&gt;MoonStones&lt;&#x2F;strong&gt;, she grew weary of her findings.
Just a moment ago she was so sure of her discovery, but now that she had sent off the finding she became... hesitant.
Was this &lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; or perhaps the similar &lt;em&gt;SilverStone&lt;&#x2F;em&gt;.
&lt;strong&gt;MoonStone&lt;&#x2F;strong&gt; was only theoretical, studied in the mind and never before in the hand; it had never been proven to exist so what made her so sure that &lt;em&gt;this rock&lt;&#x2F;em&gt; was what they had been searching for.
She was, after all, just an apprentice sorcerer; what did she know?
If Rowan determined her findings untrue what would stop him from revoking his mentor ship?
Her years of study would be for naut.&lt;&#x2F;p&gt;
&lt;p&gt;Ellyn had always been prone to worry.
She took a deep breath and with nothing else to do, she sat in wait.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Git Does a Lot of Things</title>
        <published>2016-07-27T00:00:00+00:00</published>
        <updated>2016-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/git-does-a-lot-of-things/"/>
        <id>https://elijah.run/blog/git-does-a-lot-of-things/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/git-does-a-lot-of-things/">&lt;p&gt;I should make a tool that extends &lt;code&gt;git&lt;&#x2F;code&gt; to delete all of the files matched by the &lt;code&gt;.gitginore&lt;&#x2F;code&gt;.
I spend way too much time crafting &lt;code&gt;find &amp;lt;...&amp;gt; | xargs rm&lt;&#x2F;code&gt; commands. I know, I&#x27;ll call it &lt;code&gt;git clean&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Well... before I get too far I&#x27;ll just make sure it doesn&#x27;t already exist.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ man git clean
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;GIT-CLEAN(1)                  Git Manual                       GIT-CLEAN(1)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;NAME
&lt;&#x2F;span&gt;&lt;span&gt;       git-clean - Remove untracked files from the working tree
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SYNOPSIS
&lt;&#x2F;span&gt;&lt;span&gt;    git clean [-d] [-f] [-i] [-n] [-q] [-e &amp;lt;pattern&amp;gt;] [-x | -X] [--]
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;path&amp;gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DESCRIPTION
&lt;&#x2F;span&gt;&lt;span&gt;    Cleans the working tree by recursively removing files that are not
&lt;&#x2F;span&gt;&lt;span&gt;    under version control, starting from the current directory.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Huh... well I... that&#x27;s pretty much exactly how I would have done it...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git&lt;&#x2F;code&gt; &lt;em&gt;tab tab&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;add                  filter-branch        relink
&lt;&#x2F;span&gt;&lt;span&gt;am                   format-patch         remote
&lt;&#x2F;span&gt;&lt;span&gt;annotate             fsck                 repack
&lt;&#x2F;span&gt;&lt;span&gt;apply                gc                   replace
&lt;&#x2F;span&gt;&lt;span&gt;archive              get-tar-commit-id    request-pull
&lt;&#x2F;span&gt;&lt;span&gt;bisect               grep                 reset
&lt;&#x2F;span&gt;&lt;span&gt;blame                help                 revert
&lt;&#x2F;span&gt;&lt;span&gt;branch               imap-send            review
&lt;&#x2F;span&gt;&lt;span&gt;bundle               init                 rm
&lt;&#x2F;span&gt;&lt;span&gt;checkout             instaweb             send-email
&lt;&#x2F;span&gt;&lt;span&gt;cherry               interpret-trailers   shortlog
&lt;&#x2F;span&gt;&lt;span&gt;cherry-pick          log                  show
&lt;&#x2F;span&gt;&lt;span&gt;clean                merge                show-branch
&lt;&#x2F;span&gt;&lt;span&gt;clone                mergetool            stage
&lt;&#x2F;span&gt;&lt;span&gt;column               mv                   stash
&lt;&#x2F;span&gt;&lt;span&gt;commit               name-rev             status
&lt;&#x2F;span&gt;&lt;span&gt;config               notes                submodule
&lt;&#x2F;span&gt;&lt;span&gt;credential           p4                   svn
&lt;&#x2F;span&gt;&lt;span&gt;describe             pull                 tag
&lt;&#x2F;span&gt;&lt;span&gt;diff                 push                 verify-commit
&lt;&#x2F;span&gt;&lt;span&gt;difftool             rebase               whatchanged
&lt;&#x2F;span&gt;&lt;span&gt;fetch                reflog               worktree
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ah, okay.
I get it now.
Git &lt;em&gt;does&lt;&#x2F;em&gt; do a lot of things.&lt;&#x2F;p&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;The above output is from &lt;code&gt;git 2.8.2&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Induction</title>
        <published>2016-07-27T00:00:00+00:00</published>
        <updated>2016-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/induction/"/>
        <id>https://elijah.run/blog/induction/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/induction/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;comics&#x2F;induction.png&quot; alt=&quot;Classic mathematics memes&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debra the ghoul</title>
        <published>2016-07-02T00:00:00+00:00</published>
        <updated>2016-07-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/debra-the-ghoul/"/>
        <id>https://elijah.run/fiction/debra-the-ghoul/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/debra-the-ghoul/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A ghoul and an archbishop are fighting over custody of their children.
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;749301833881915392&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Just like every Friday night, Debra picked up her two daughters from her ex-wife&#x27;s house in Evanston and drove them downtown for the weekend.
As she drove away in her red 2008 Corolla with them she got a text message from her ex.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;From: Gwendolyn&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Debra,&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Please bring Lilyan and Odell back by 9pm on Sunday.&lt;&#x2F;em&gt;
&lt;em&gt;They have school Monday morning.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Debra became immediately filled with rage.
&lt;em&gt;&#x27;Of course they both have school Monday morning!
I&#x27;m not stupid!
I&#x27;ve been doing this for four and a half years goddammit.
How stupid does she think I am?
Christ she can be such a --&#x27;&lt;&#x2F;em&gt;
and before she went down that rabbit hole she remembered what her therapist said.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Just breath. Everything is going to be okay.
This is just temporary.
Her bitchy behavior only affects you if you let it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Debra drove a few more miles, her daughters in the back staying cautiously silent.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually Lilyan spoke up.
&quot;Debora, why does mommy so mean to you?&quot; deliberately calling Debra (or &lt;strong&gt;Debora&lt;&#x2F;strong&gt; in Lilyan&#x27;s case) by her name and Gwen by &lt;em&gt;&#x27;mommy&#x27;&lt;&#x2F;em&gt;.
This used to bug Debra but she eventually became apathetic toward the situation.
Gwendolyn had brainwashed the kids; she was honestly just glad she was able to fight and keep her daughters on the weekends.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Why &lt;em&gt;is&lt;&#x2F;em&gt; mommy so mean to me. And sweety, I&#x27;m a ghoul and that means that &lt;em&gt;most&lt;&#x2F;em&gt; people don&#x27;t really like me.&quot; Debra said matter-of-factly.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Like racism?&quot; Lilyan asked.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Exactly like racism Lily.And your mother is a Christian official called an &#x27;Archbishop&#x27;.
For some reason, probably some squabble hundreds of years ago [or maybe they&#x27;ve just always been biggots] none of your mother&#x27;s bosses liked that she was in a relationship me so she had to give it up.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;There was a momentary pause as the girls thought this over.
Lilyan was six and Odell was eight, neither of which were really prepared to fully process what she was saying, but she wanted them to feel respected and independent so she participated in their questions.
They were both technically Gwendolyn&#x27;s daughters with a donor, Debra would have had child if she was able to but ghouls had a notorously difficult time doing anything related to &lt;em&gt;living&lt;&#x2F;em&gt;, creating life included.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;But why does she not like you?&quot; Lilyan finally asked.&lt;&#x2F;p&gt;
&lt;p&gt;Debra sighed.
&quot;Well, I think she doesn&#x27;t like me because she wishes we could still be together.
We had a very romantic fling in the beginning and we really thought we could stay together but... well it wasn&#x27;t meant to last.
She just thinks that this is the best way to deal with the situation.
Some people would rather feel angry than sad.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Lilyan quickly followed up with the obvious &quot;Do you feel sad Debora?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Debra thought for a moment.
Lilyan asked again &quot;Do you feel sad Debora?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Sometimes sweetie.
Sometimes I feel very sad and it makes it very hard to do things like go to work and eat food.
Most of the time that happens I remind myself how lucky I am to have you two to look forward to.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Lilyan didn&#x27;t know what else to ask and so the three sat in silence as they drove down Lake-Shore Drive.
The lamp posts cast yellow-tinged shadows on their faces as they each looked out the windows.&lt;&#x2F;p&gt;
&lt;p&gt;Odell finally spoke up, &quot;What are we going to do this weekend?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Good question.
What do you guys want to do? I was thinking we could go mini-golfing once you get your homework done.
How does that sound?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;They both groaned.
Debra smiled &quot;Well I guess it&#x27;s settled. Mini putt-putt tomorrow afternoon.&quot;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Emperor Stan of Stantinople</title>
        <published>2016-07-01T00:00:00+00:00</published>
        <updated>2016-07-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/emperor-stan-of-stantinople/"/>
        <id>https://elijah.run/fiction/emperor-stan-of-stantinople/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/emperor-stan-of-stantinople/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;An emperor owns a steam-powered device which allows him to destroy the
past.
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;749120629308203009&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Emperor Stan of Stantinople, the most prosperous 1500 square feet in all of &lt;strong&gt;Oak Burch Sunrise Shire&lt;&#x2F;strong&gt; &lt;em&gt;Suburban [Gated] Community&lt;&#x2F;em&gt;, ruled with an &lt;em&gt;iron fist&lt;&#x2F;em&gt; and an endless stream of &lt;em&gt;Puns&lt;&#x2F;em&gt;.
His wife and three daughters obeyed his every whim, when it fit their schedules... and if they were in a good mood... and they wanted to.
Stan was content with his life as an emperor and ruler of his domain, no matter how far and wide that domain spanned.&lt;&#x2F;p&gt;
&lt;p&gt;One Tuesday afternoon, as he stood at the edge of the sidewalk squinting toward his back yard and telling himself that &lt;em&gt;&#x27;Stantinople stretches as far as the eye can see&#x27;&lt;&#x2F;em&gt;, his mind drifted to the life he could have had.
He thought about all of the mistakes he had made like when he tried stand-up and totally bombed, when he got into massive debt from college and dropped out, and when he bought a house in the suburbs -- the mistakes!&lt;&#x2F;p&gt;
&lt;p&gt;Seemingly out of nowhere he was tapped on the nose by a delivery woman.
She told him to sign her PDA and before he could process what was happening she dropped a thick wooden, about the size of a bedside table, at his doorstep.
He turned around and the woman sped away in an un-marked FedEx van; it didn&#x27;t say FedEx, because it was unmarked, but the color and shape was right so Stan figured it probably was FedEx.&lt;&#x2F;p&gt;
&lt;p&gt;He lugged the box into the house and down to the finished basement he (and a poster in the stairwell leading down to the basement) called the &lt;strong&gt;&#x27;Stantinople Man Cave&#x27;&lt;&#x2F;strong&gt;, despite it not having many &lt;em&gt;Man Cave&lt;&#x2F;em&gt; amenities nor being an actual cave for which one might find men.
The entirety of the basement consisted of three dark brown leather couches lined up in an &#x27;L&#x27; formation in the corner and a small, almost child-sized foosball table on the opposite end of the room.
He didn&#x27;t even invest in a wide-screen TV and a few Lay-Z boy chairs with built-in mini-fridges! Stan really had no concept of what a &lt;em&gt;Man Cave&lt;&#x2F;em&gt; ought to have but nobody really called him on it since he was obviously trying his sad 43 year-old best.&lt;&#x2F;p&gt;
&lt;p&gt;He fumbled the box with a &lt;em&gt;WHOOMP&lt;&#x2F;em&gt; onto the carpet and painlessly opened it with its &lt;em&gt;No Hassle™ packaging&lt;&#x2F;em&gt;, an innovation he did not realized had made its way to wooden packaging.
Removing the item Stan thought this new device was a sewing machine and he got excited, but upon closer inspection he realised it was not a sewing machine.
The device was a rectangular cube with rounded edges and was hollow in the middle except for what looked like some pistons; the device was matt black and had four rubber feet on the bottom and was branded &lt;em&gt;&#x27;Past Scrubber&#x27;&lt;&#x2F;em&gt;.
He lifted the device out of the box and flipped &#x27;on&#x27; the devices only switch; it began to &lt;em&gt;whurrrrrr&lt;&#x2F;em&gt; like a small engine.&lt;&#x2F;p&gt;
&lt;p&gt;Stan rummaged through the box and found a piece of paper which read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;May this device only be used by the mightiest and wisest emperors.
With its mechanical power it may erase both mistakes and triumphs of
the past. It does not discriminate, this is the job of its master.
You are its master.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&quot;Sweet! This thing looks cool.&quot; Stan said oblivious to the ominous tone of this note.
&quot;Let&#x27;s see... it can change the past.
I wonder what I should change...&quot; he said foolishly not taking this very serious device seriously.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Well first I&#x27;d wish I&#x27;d never moved out to the suburbs.
That was a huge mistake.&quot;
The machine&#x27;s &lt;em&gt;whurrr&lt;&#x2F;em&gt;&#x27;ing intensified and an instant later he found himself living in a nice apartment near down-town.
Since time had been altered, and in this universe you don&#x27;t remember old timeliness if you change the past (deal with it), Stan had no idea that anything had changed and had yet to make his first decision.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Well first I&#x27;d wish I never went to college, that was a huge waste of time just to drop out.&quot; and again (for you, not for him) the machine &lt;em&gt;whurrr&lt;&#x2F;em&gt;&#x27;d louder and an instant later Stan found himself in a much shittier apartment, further from downtown.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Well first I&#x27;d wish I went to college, I really could have done something with my life.&quot; and the machine didn&#x27;t respond because, despite it&#x27;s visual similarities to a sewing machine, the device only knew how to destroy time and not how to create it.
He would have known this if he read the freaking manual.&lt;&#x2F;p&gt;
&lt;p&gt;Stan quickly grew bored with the device after naming off a few things he &lt;em&gt;wished&lt;&#x2F;em&gt; he had done and it just &lt;em&gt;whurr&lt;&#x2F;em&gt;&#x27;ing on.
He switched the machine &lt;em&gt;off&lt;&#x2F;em&gt; and put it in the corner and muttered to himself &quot;Maybe I can get something for it on ebay.&quot;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;After a furious bidding war between two hobbyist mechanics Stan got
$153 for it.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Not bad.&quot; he said when the bidding ended. &quot;Not bad indeed.&quot; and smiled.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Character Study: The &#x27;try new things&#x27; couple</title>
        <published>2016-06-17T00:00:00+00:00</published>
        <updated>2016-06-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/the-try-new-things-couple/"/>
        <id>https://elijah.run/fiction/the-try-new-things-couple/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/the-try-new-things-couple/">&lt;p&gt;Gwendolyn and Stefan love to try new things.
Not like... &lt;em&gt;sex things&lt;&#x2F;em&gt;, but like &lt;em&gt;lifestyle things&lt;&#x2F;em&gt;.
Take, for example, Gwendolyn decided last week that she would love to see what life was like if she and Stefan only shared &lt;strong&gt;one&lt;&#x2F;strong&gt; bowl, plate, cup, fork, knife, spoon, and pan for a month.
She didn&#x27;t really have a good reason for &lt;em&gt;why&lt;&#x2F;em&gt; at the time, it&#x27;s not like she read it in a magazine or anything, but they&#x27;re young and into wacky stuff like that.
Stefan always participates in these and likes talking about their &lt;em&gt;adventures&lt;&#x2F;em&gt; as they&#x27;re happening, but never proposes ideas of his own.&lt;&#x2F;p&gt;
&lt;p&gt;Gwendolyn requires that people use the full &lt;em&gt;Gwendolyn&lt;&#x2F;em&gt; and not &lt;em&gt;Gwen&lt;&#x2F;em&gt; and has been known to &lt;strong&gt;halt&lt;&#x2F;strong&gt; conversations if people don&#x27;t.
She feels was confident that she loves Stefan three times more than he loves her.
She wasn&#x27;t sure why she felt that way, or where three times came from, but it had always been her hunch.
Since she&#x27;s never been able to confirm or deny it, she has kept on believing it; this puts her in an artificially smug mood whenever she sacrifices something for Stefan, like the 5% markup on the organic foods because he prefers them.&lt;&#x2F;p&gt;
&lt;p&gt;Stefan previously refereed to her as &lt;em&gt;Gwen&lt;&#x2F;em&gt; internally but forced himself to adapt after a few preventable meltdowns.
He hasn&#x27;t ever really considered how much he loves Gwendolyn, but he regularly thinks about the house they&#x27;ll buy together in a few years.
There isn&#x27;t actually a specific house they&#x27;re thinking about, but he still enjoys the fantasy; some women dream of their wedding day and Stefan dreams of his move-in day.
Year after year they&#x27;ve stayed in the same mid-town loft and will never did move into that house.&lt;&#x2F;p&gt;
&lt;p&gt;They both definitely &lt;strong&gt;love&lt;&#x2F;strong&gt; each other to the extent that any twenty-somethings can love one another while still collectively managing to avoid the question of marriage.
They will eventually break-up, not because of any one event or central cause, but because people grow up and grow apart.
It&#x27;s never anybody&#x27;s fault, it&#x27;s just how the wind blows.
Some people&#x27;s connections are able to persevere that inevitable break, but this connection will not.
Gwendolyn knows this and in the back of her head is already thinking about why a breakup would be best for them.
Stefan has thought about it once or twice but doesn&#x27;t really want things to change.
He likes spending his life with Gwendolyn and feels like they do share a really close bond, even if that bond is largely based on things like sharing one bowl, plate, cup, fork, knife, spoon, and pan for a month.&lt;&#x2F;p&gt;
&lt;p&gt;That said, the &lt;em&gt;sharing-one-of-everything&lt;&#x2F;em&gt; thing is working out pretty well.
Gwendolyn hasn&#x27;t gotten any of their friends to try it but she really feels like she&#x27;s looking at food and meals in a whole new light.
Stefan thinks it&#x27;s a neat idea, but is looking forward to the end of this month.
He would never tell her that though.
He loves her too much.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How to Get the Most out of Your Python Exceptions</title>
        <published>2016-04-03T00:00:00+00:00</published>
        <updated>2016-04-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/python-exceptions/"/>
        <id>https://elijah.run/blog/python-exceptions/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/python-exceptions/">&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Please enter a number not equal to 0: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt;(var)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;ZeroDivisionError &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;e:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Error: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;(e))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;You had one job!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;warning&quot;&gt;
    &lt;span class=&quot;warning-title&quot;&gt;
        Warning
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;warning-body&quot;&gt;
        &lt;p&gt;This post does not cover &lt;em&gt;what&lt;&#x2F;em&gt; python exceptions are. If the above code
doesn&#x27;t make sense you should check out this &lt;a href=&quot;https:&#x2F;&#x2F;wiki.python.org&#x2F;moin&#x2F;HandlingExceptions&quot;&gt;Introduction to Python
Exceptions&lt;&#x2F;a&gt; from
wiki.python.org before reading this post.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If you&#x27;ve fallen in love with Python you&#x27;ve no doubt discovered exceptions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# do a thing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# thing did not work,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# do something else
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They are endlessly useful and help one to avoid writing checks upon checks upon checks before getting to the meat of your project.
Just try a thing, catch the error, keep on rolling (or fail gracefully).&lt;&#x2F;p&gt;
&lt;p&gt;As powerful as they can be, I have found a lot of folks (past me included) who don&#x27;t know how to find python exceptions and don&#x27;t know how to write their own exceptions! So let&#x27;s do that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-exceptions&quot;&gt;Finding Exceptions&lt;&#x2F;h2&gt;
&lt;p&gt;When writing exception handling code it&#x27;s kosher to explicitly state &lt;em&gt;which&lt;&#x2F;em&gt; error you expect.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Bad:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# A thing that might not work
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Something else
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Good:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# A thing that might not work
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except &lt;&#x2F;span&gt;&lt;span&gt;SpecificError &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;err:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Maybe print(err)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Something else
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When I first found this out I thought &lt;em&gt;Golly that does sound useful; I always try to be explicit in my error handling -- but how??&lt;&#x2F;em&gt;
Thankfully future me is here to answer questions like this.&lt;&#x2F;p&gt;
&lt;p&gt;The exception you are looking for (for instance, &lt;code&gt;SpecificError&lt;&#x2F;code&gt; in the above pseudo-code) can be found in the python traceback:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ echo &amp;quot;open(&amp;#39;myfakefile.txt&amp;#39;, &amp;#39;r&amp;#39;).close()&amp;quot; &amp;gt; my-unhandled-script.py
&lt;&#x2F;span&gt;&lt;span&gt;$ python my-unhandled-script.py
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;tmp&#x2F;test.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    open(&amp;#39;myfakefile.txt&amp;#39;, &amp;#39;r&amp;#39;).close()
&lt;&#x2F;span&gt;&lt;span&gt;IOError: [Errno 2] No such file or directory: &amp;#39;myfakefile.txt&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That bit on the last line &lt;code&gt;IOError&lt;&#x2F;code&gt; is the exception you&#x27;re looking for.
So when you write your code you&#x27;ll say something like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;myfakefile.txt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;IOError &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;e:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(e)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;File `myfakefile.txt` does not exist&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To recap, here is one way (and my preferred method for) &#x27;doing&#x27; python exception handling:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Write breakable code.&lt;&#x2F;li&gt;
&lt;li&gt;Run breakable code, see what exceptions python spits out.&lt;&#x2F;li&gt;
&lt;li&gt;Wrap breakable code in explicit &lt;code&gt;try&#x2F;except&lt;&#x2F;code&gt; blocks.&lt;&#x2F;li&gt;
&lt;li&gt;???&lt;&#x2F;li&gt;
&lt;li&gt;Profit.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;writing-your-own-exceptions&quot;&gt;Writing Your Own Exceptions&lt;&#x2F;h2&gt;
&lt;p&gt;You (who me?), yes &lt;em&gt;you&lt;&#x2F;em&gt; can write custom python exceptions.
It&#x27;s dead easy too.&lt;&#x2F;p&gt;
&lt;p&gt;The long and short of it is you define an exception class which either inherits from the &lt;code&gt;Exception&lt;&#x2F;code&gt; class or another pre-existing exception.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;text-decoration:underline;color:#8cdaff;&quot;&gt;CusssstomError&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;text-decoration:underline;font-style:italic;color:#8cdaff;&quot;&gt;Exception&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;#39;&amp;#39;&amp;#39;Raise when snakes&amp;#39;&amp;#39;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;__init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.message &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;message
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#ff5e5e;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;check_for_snakes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;snake&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;foo.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;lower&lt;&#x2F;span&gt;&lt;span&gt;():
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;CusssstomError&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Snakes! I hate snakes!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    foo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Just don&amp;#39;t mention snakes: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;check_for_snakes&lt;&#x2F;span&gt;&lt;span&gt;(foo)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;except &lt;&#x2F;span&gt;&lt;span&gt;CusssstomError &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;e:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(e.message)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Thanks. I appreciate it.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above code defines the &lt;code&gt;CusssstomError&lt;&#x2F;code&gt; exception class which you can &lt;code&gt;raise&lt;&#x2F;code&gt;.
Very neat and &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;2&#x2F;glossary.html#term-pythonic&quot;&gt;pythonic&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;&#x2F;h2&gt;
&lt;p&gt;Here are a few references I suggest you check out to get an even better grasp on exception handling and custom exceptions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;This Stack Overflow post: &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1319615&#x2F;proper-way-to-declare-custom-exceptions-in-modern-python&quot;&gt;Proper way to declare custom exceptions in modern Python?&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;This Python doc: &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;2&#x2F;library&#x2F;exceptions.html&quot;&gt;Built-in Exceptions&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And as always, search engines are your friends.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How to develop a site for the web</title>
        <published>2016-03-25T00:00:00+00:00</published>
        <updated>2016-03-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/how-to-develop-a-site-for-the-web/"/>
        <id>https://elijah.run/blog/how-to-develop-a-site-for-the-web/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/how-to-develop-a-site-for-the-web/">&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;This post does not deal with the basics of HTML, CSS, or Javascript, but
rather a simple and often overlooked part of the web-dev toolchain.&lt;&#x2F;p&gt;
&lt;p&gt;If you would like help with the basics of HTML, CSS, and Javascript I
suggest &lt;a href=&quot;https:&#x2F;&#x2F;codecademy.com&#x2F;learn&#x2F;make-a-website&quot;&gt;Codecademy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Web Development, especially the front-endy stuff, is a great way to
understand how computers &lt;em&gt;think&lt;&#x2F;em&gt; and can be a wonderful foray into
computer programming. Anybody that&#x27;s made a website probably remembers
their first time:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open up a text editor.&lt;&#x2F;li&gt;
&lt;li&gt;Type something like the following in:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;Hello world!&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;This is so cool!&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;code&gt;Save As index.html&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Right click and open the file in your browser.&lt;&#x2F;li&gt;
&lt;li&gt;Marvel at what you&#x27;ve created and hack away at it all night long.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;And there you go! You&#x27;ve got a website made and ready to roll. It&#x27;s not
on a server, and you can&#x27;t tell your friends to go to it from &lt;em&gt;their&lt;&#x2F;em&gt;
computer --but those are just technicalities. You can still celebrate
doing a thing &lt;em&gt;like a boss&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, when you test your website by viewing local files you&#x27;re
missing out on a lot of advantages and quirks that you get when you host
a website on a &lt;em&gt;real server&lt;&#x2F;em&gt; using something like &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Web_server&quot;&gt;Apache or
Nginx&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, when you run check your website by clicking through
&lt;code&gt;file&#x2F;&#x2F;&#x2F;home&#x2F;username&#x2F;project&#x2F;files.html&lt;&#x2F;code&gt; all of your hyperlinks that
should point to &lt;code&gt;http:&#x2F;&#x2F;mywebsite.ext&#x2F;somepage&#x2F;&lt;&#x2F;code&gt; will take you to
&lt;code&gt;file:&#x2F;&#x2F;&#x2F;&#x2F;somepage&lt;&#x2F;code&gt; when they should take you to
&lt;code&gt;file:&#x2F;&#x2F;&#x2F;home&#x2F;username&#x2F;projects&#x2F;myawesomesite&#x2F;somepage&#x2F;index.html&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;run-a-development-server-it-s-easy&quot;&gt;Run A Development Server (it&#x27;s easy!)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;the-short-answer&quot;&gt;The Short Answer&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Use Python!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ python2 -m SimpleHTTPServer
&lt;&#x2F;span&gt;&lt;span&gt;Serving HTTP on 0.0.0.0 port 8000 ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-longer-answer&quot;&gt;The Longer Answer&lt;&#x2F;h3&gt;
&lt;p&gt;You can run your own local webserver to serve files &lt;em&gt;locally&lt;&#x2F;em&gt;.
This gets you all of the developmental advantages of running a webserver without having to rent or run a server in the cloud.
The best part is that it&#x27;s very easy to run a development web server.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;python.org&#x2F;downloads&#x2F;&quot;&gt;Install Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Navigate to &lt;code&gt;your-awesome-website&lt;&#x2F;code&gt; directory&#x2F;folder.&lt;&#x2F;li&gt;
&lt;li&gt;Run &lt;code&gt;python -m SimpleHTTPServer&lt;&#x2F;code&gt; if you installed &lt;code&gt;python2&lt;&#x2F;code&gt; or run &lt;code&gt;python -m http.server&lt;&#x2F;code&gt; if you installed &lt;code&gt;python3&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;note&quot;&gt;
    &lt;span class=&quot;note-title&quot;&gt;
        Note
    &lt;&#x2F;span&gt;

    &lt;span class=&quot;note-body&quot;&gt;
        &lt;p&gt;These instructions assume you are doing things in a Unix environment (OSX or Linux) thought the commandline.
If you are using Windows you should check out this &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;17351016&#x2F;set-up-python-simplehttpserver-on-windows&quot;&gt;stack overflow post&lt;&#x2F;a&gt; for Windows-specific help.&lt;&#x2F;p&gt;

    &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;
&lt;p&gt;Then in your web browser go to the address &lt;code&gt;http:&#x2F;&#x2F;localhost:8000&lt;&#x2F;code&gt; and
bam! &lt;strong&gt;Your&lt;&#x2F;strong&gt; Website.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;gifs&#x2F;high-five.gif&quot; alt=&quot;High Five.gif&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Running Firefox in Docker</title>
        <published>2016-03-05T00:00:00+00:00</published>
        <updated>2016-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/running-firefox-in-docker/"/>
        <id>https://elijah.run/blog/running-firefox-in-docker/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/running-firefox-in-docker/">&lt;p&gt;Turns out you can run Firefox in Docker.
It&#x27;s actually pretty easy:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;From&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;ElijahCaine&#x2F;29e7e829341d58abe370&quot;&gt;my github
gist&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;script src=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;ElijahCaine&#x2F;29e7e829341d58abe370.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;p&gt;Installation instructions (on Linux):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;# install docker and start the docker daemon
&lt;&#x2F;span&gt;&lt;span&gt;$ git clone https:&#x2F;&#x2F;gist.github.com&#x2F;29e7e829341d58abe370.git docker-firefox
&lt;&#x2F;span&gt;&lt;span&gt;$ ln docker-firefox&#x2F;ff-docker &#x2F;some&#x2F;path&#x2F;for&#x2F;binaries
&lt;&#x2F;span&gt;&lt;span&gt;$ ff-docker -b  # -b pulls &amp;amp; builds container, etc used for first time startup.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h2&gt;
&lt;p&gt;I attempted to use &lt;a href=&quot;http:&#x2F;&#x2F;alpinelinux.org&#x2F;&quot;&gt;Alpine Linux&lt;&#x2F;a&gt; as a
proof-of-usability, since it&#x27;s the hip new kid on the containerization
block&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but as it turns out Alpine&#x27;s Firefox package is pretty
fucked&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Dmenu&quot;&gt;dmenu&lt;&#x2F;a&gt;, this means I
can run &lt;code&gt;ff-docker&lt;&#x2F;code&gt; from my desktop without opening a terminal,
effectively making it a super-private-yet-convenient drop-in for
Firefox. Pretty neat right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This was pretty simple but effective in terms of giving me the option to
have more privacy. I can see it being extended to add even more
security; e.g., routing all of the traffic in the container through a
VPN would be easy enough. Food for thought [citation needed].&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;5mb containers sounds pretty nice to me.
&lt;a href=&quot;http:&#x2F;&#x2F;gliderlabs.viewdocs.io&#x2F;docker-alpine&#x2F;&quot;&gt;http:&#x2F;&#x2F;gliderlabs.viewdocs.io&#x2F;docker-alpine&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I get a segfault every time I try to start Firefox. More info
here: &lt;a href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=724227#c11&quot;&gt;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=724227#c11&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>CatBarcamp 2015</title>
        <published>2015-10-12T00:00:00+00:00</published>
        <updated>2015-10-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/cat-barcamp-2015/"/>
        <id>https://elijah.run/blog/cat-barcamp-2015/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/cat-barcamp-2015/">&lt;p&gt;This weekend I went to &lt;a href=&quot;http:&#x2F;&#x2F;catbarcamp.org&#x2F;&quot;&gt;Cat Barcamp 2015&lt;&#x2F;a&gt;, an unconference run by the PSU &lt;a href=&quot;http:&#x2F;&#x2F;cat.pdx.edu&#x2F;&quot;&gt;Computer Action Team&lt;&#x2F;a&gt;.
I went to some awesome talks (and gave one myself).&lt;&#x2F;p&gt;
&lt;p&gt;I enjoyed every talk I went to. Here they are in order:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;History of Cryptography.&lt;&#x2F;strong&gt;
This was given by one of my OSL co-workers.
It didn&#x27;t contain a ton of new information for me, but was delivered very well and focused on different types of cryptography and the context in which each one was developed.
I enjoyed it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Haskell on Steroids.&lt;&#x2F;strong&gt;
I kinda checked out during this talk because I wanted to write my slides... Wooops.
It looked very interesting and mathey though...&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Introduction to Test Driven Development in Power Shell.&lt;&#x2F;strong&gt;
Whoa Windows
(actually though, I learned more about Power Shell than I ever expected to know).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MY TALK.&lt;&#x2F;strong&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;cat-barcamp-2015&#x2F;#my-talk&quot;&gt;(see below)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A Whirlwind Tour of Lojban.&lt;&#x2F;strong&gt;
Lojban seems like a cool language. Corbin (previous LUG president) gave this talk, he&#x27;s a cool guy... you might even say he&#x27;s TheMostAwesomeDude.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Adventures in IT Security: Then and now.&lt;&#x2F;strong&gt;
I like history.
I also like computers.
This was a good talk.
I am biased.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Talking to people! (or, How I learned to stop worrying and love the user.)&lt;&#x2F;strong&gt;
Spoiler: The secret is understanding social cues.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;my-talk&quot;&gt;My Talk&lt;&#x2F;h2&gt;
&lt;p&gt;I decided on the spur of the moment to give a talk &#x27;How to Write a (very mediocre) Static Site Generator&#x27; and with only 40 minutes of prep work I was able to fill an hour pretty well.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some links from that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;ElijahCaine&#x2F;0ee1ef21692f3cbb6934&quot;&gt;demo code&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;elijahcaine.me&#x2F;catbarcamp2015-demo&#x2F;&quot;&gt;abomination of a website&lt;&#x2F;a&gt; we built between the demo and the end of the session (epilepsy warning... no seriously).&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;a href=&quot;http:&#x2F;&#x2F;slides.elijahcaine.me&#x2F;cat-barcamp-2015_how-to-an-ssg&#x2F;&quot;&gt;very sparse slides&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TLDR&lt;&#x2F;h2&gt;
&lt;p&gt;The CAT is an awesome group of people.
I&#x27;m glad I was able to get a few LUG members to come to the event.
If I went to PSU I would be honored to work with the CAT.
They throw a hellofan event.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Covertly Installing Packages with Docker</title>
        <published>2015-10-07T00:00:00+00:00</published>
        <updated>2015-10-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/covertly-install-packages-with-docker/"/>
        <id>https://elijah.run/blog/covertly-install-packages-with-docker/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/covertly-install-packages-with-docker/">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;elijah.run&#x2F;blog&#x2F;covertly-install-packages-with-docker&#x2F;#the-deets-dockerfile-and-commands&quot;&gt;Jump to the codey bits&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-workstations&quot;&gt;The Problem: Workstations&lt;&#x2F;h2&gt;
&lt;p&gt;At the OSL I use workstations which are provisioned by
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Chef_%28software%29&quot;&gt;Chef&lt;&#x2F;a&gt; to look more
or less identical (packages are the same and global config files are
consistent from machine to machine). This is nice because it allows
everybody at the lab to jump from workstation to workstation without
dreading the inevitable setup that usually comes with going to a new
computer.&lt;&#x2F;p&gt;
&lt;p&gt;The only downside here is that to install a package you have to make a
pull request to a GitHub Repository in which you modify a JSON file.
This is almost always for my own good, but as a dev I am prone to
avoiding things that the admins say are good for me (like broccoli,
milk, and consistent workstation environments).&lt;&#x2F;p&gt;
&lt;p&gt;For instance, yesterday I wanted to use
&lt;a href=&quot;http:&#x2F;&#x2F;rg3.github.io&#x2F;youtube-dl&#x2F;&quot;&gt;youtube-dl&lt;&#x2F;a&gt; to grab a video I was
watching on repeat*. I could have made a pull request to add the
package, waited until 30 after for the workstations to refresh, used the
package, and went about my day. This would have been the correct and
bureaucratic way to do things.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;em&gt;could&lt;&#x2F;em&gt; have, and probably &lt;em&gt;should&lt;&#x2F;em&gt; have, done that... but I didn&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;* firefox kept crashing, I wasn&#x27;t just stealing music for the sake of
it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enter-docker&quot;&gt;Enter: Docker&lt;&#x2F;h2&gt;
&lt;p&gt;In this case the solution to the &#x27;problem&#x27; was
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Docker_%28software%29&quot;&gt;Docker&lt;&#x2F;a&gt;. I wrote a
Dockerfile which provisioned a container to have &lt;code&gt;youtube-dl&lt;&#x2F;code&gt; installed,
spun up the container with a shared directory (&lt;code&gt;$PWD:&#x2F;home&#x2F;&lt;&#x2F;code&gt;), and
executed the youtube-dl command. The .mp4 video was downloaded to my
current working directory and I was able to play it with my media player
of choice, all without installing &lt;code&gt;youtube-dl&lt;&#x2F;code&gt; locally.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-deets-dockerfile-and-commands&quot;&gt;The Deets: Dockerfile and Commands&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;FROM ubuntu:latest
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN apt-get -y update
&lt;&#x2F;span&gt;&lt;span&gt;RUN apt-get -y upgrade
&lt;&#x2F;span&gt;&lt;span&gt;RUN apt-get -y install python-pip
&lt;&#x2F;span&gt;&lt;span&gt;RUN pip install youtube-dl
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;WORKDIR &#x2F;home
&lt;&#x2F;span&gt;&lt;span&gt;RUN alias youtube-dl=&amp;#39;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;youtube-dl&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you are in the directory containing the above Dockerfile, build the
container with:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ docker build -t yt-dl .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and run it with:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ docker run -v $PWD:&#x2F;home&#x2F; yt-dl youtube-dl &amp;lt;YOUTUBE-VID-URL&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will download any url&#x27;s video into the current working directory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pro-tip-add-an-alias&quot;&gt;Pro-Tip: Add an &lt;code&gt;Alias&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Add the following content to your &lt;code&gt;~&#x2F;.bashrc&lt;&#x2F;code&gt; file and then run
&lt;code&gt;source ~&#x2F;.bashrc&lt;&#x2F;code&gt; to get rid the of long Docker bits of the above
command.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$VID_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&#x2F;path&#x2F;to&#x2F;downloaded&#x2F;videos&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;yt-dl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;docker run -v $VID_DIR:&#x2F;home&#x2F; yt-dl youtube-dl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;wait-this-is-overly-complicated&quot;&gt;Wait This is Overly Complicated&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;re probably thinking: &quot;Hey, couldn&#x27;t you have just run
&lt;code&gt;pip install --user youtube-dl&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;Yes. I could have. But that wouldn&#x27;t be fun and wouldn&#x27;t have given me
an excuse to write a blog, post now would it Ms. Smarty Pantz.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;drink the coolaid. come to the docker side.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Travel travel travel...</title>
        <published>2015-09-03T00:00:00+00:00</published>
        <updated>2015-09-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-09-03/"/>
        <id>https://elijah.run/blog/2015-09-03/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-09-03/">&lt;h2 id=&quot;travel-travel-travel&quot;&gt;Travel Travel Travel&lt;&#x2F;h2&gt;
&lt;p&gt;Travel travel travel travel travel travel travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel. travel. Travel travel travel travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel travel travel.&lt;&#x2F;p&gt;
&lt;p&gt;Travel travel travel travel travel travel travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel. travel. Travel travel travel travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel travel travel travel. travel. Travel travel travel travel
travel travel travel travel travel travel travel travel travel travel
travel travel travel travel travel travel travel. travel travel travel
travel travel travel travel travel travel travel travel.&lt;&#x2F;p&gt;
&lt;p&gt;Travel travel travel travel travel travel. Travel travel travel travel
travel travel travel. Travel travel travel travel travel travel travel
travel travel.&lt;&#x2F;p&gt;
&lt;p&gt;Sleep.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Personal Day in Prague: (Almost) Just Pictures</title>
        <published>2015-09-02T00:00:00+00:00</published>
        <updated>2015-09-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-09-02/"/>
        <id>https://elijah.run/blog/2015-09-02/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-09-02/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-charles-bridge.jpg&quot; alt=&quot;Charles Bridge.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-pilot-statute.jpg&quot; alt=&quot;Pilot Statue&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-view.jpg&quot; alt=&quot;View of Prague with some trees in the way.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I went on a hike, found a great view at the top of a hill.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-oldtown.jpg&quot; alt=&quot;Oldtown Prague&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-panorama-with-bridge.jpg&quot; alt=&quot;Panorama with bridge&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-creative-spelling.jpg&quot; alt=&quot;Starbucks Coffee&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&#x27;Eli&#x27;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-stunning-sunset.jpg&quot; alt=&quot;Stunning sunset&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I swear it&#x27;s not because I&#x27;m lazy and don&#x27;t want to write.
The pictures just capture it better.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Write the Docs Day 2</title>
        <published>2015-09-01T00:00:00+00:00</published>
        <updated>2015-09-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-09-01/"/>
        <id>https://elijah.run/blog/2015-09-01/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-09-01/">&lt;p&gt;Just like yesterday, I spent most of today enjoying some wonderful talks as well as stressing out -- I mean totally not stressing out -- about my own talk.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;wtd-day-2.jpg&quot; alt=&quot;write the Docs Staff Picture&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Write the Docs Staff saying thanks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The first talk of the day was titled &quot;Judas Priest Ate My Scrum Master&quot;, which has almost nothing to do with Judas Priest or eating or scrum masters; instead it talked about things that are well known issues and a lot of laws (&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Brooks%E2%80%99_law&quot;&gt;Brooks&#x27; Law&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lehman&amp;#x27;s_laws_of_software_evolution&quot;&gt;Lehmann&#x27;s Laws&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pareto_principle&quot;&gt;Pareto Principle&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conway&amp;#x27;s_law&quot;&gt;Conway&#x27;s Law&lt;&#x2F;a&gt;, etc) that nobody talks about that much but can be super helpful to consider when working in an industry.&lt;&#x2F;li&gt;
&lt;li&gt;The second talk covered different types of user interfaces and what to consider when writing error messages, troubleshooting pages, product tours.
It was something I hadn&#x27;t considered having primarily written command line tools with pretty limited and well established interface
guidelines.&lt;&#x2F;li&gt;
&lt;li&gt;Then I gave a talk.
It was a talk. I&#x27;ll post a video of it once those get put up online and you can decide if it was good or bad.&lt;&#x2F;li&gt;
&lt;li&gt;The talk after mine was a nice history lesson and wanted the audience to reflect on what documentations can learn from documentation practices of the past.
The TLDR on that one is that it used to suck to write technical docs even more than it sucks now.&lt;&#x2F;li&gt;
&lt;li&gt;Then there were a bunch of lightning talks.
One talk from a twitter employee (there&#x27;s a fun name for them I&#x27;m sure) mentioned that gathering metrics are is important because without metrics everything you do is just guess and check.&lt;&#x2F;li&gt;
&lt;li&gt;The next talk &quot;MacGyvering your docs&quot; brought up the fact that the best documentation toolchain will (should?) only help existing developers.
A better toolchain won&#x27;t attract new devs.
That was something I think a lot of projects can lose sight of.&lt;&#x2F;li&gt;
&lt;li&gt;The talk after that covered a team of scientists studying clouds (water clouds not internet clouds) using computer simulations.
They wrote and documented a piece of software and they ended up publishing their program&#x27;s documentation in a scientific journal.
It&#x27;s already been sited and everything.
I hadn&#x27;t even considered that as a possibility (publishing docs as a scientific paper).&lt;&#x2F;li&gt;
&lt;li&gt;The next two talks were pretty short (15 minute) talks about putting the data where the users need it and an introduction to screen-casting.
The first was good for documenting things like an API and the second was good if I ever need to make a screen-cast.
I doubt that will happen, but you never know!&lt;&#x2F;li&gt;
&lt;li&gt;The last talk &quot;All roads might not lead to docs&quot; held too main takeaways for me: The quote &lt;em&gt;The Purpose of this document is ________&lt;&#x2F;em&gt; and the &lt;a href=&quot;http:&#x2F;&#x2F;voiceandtone.com&#x2F;&quot;&gt;mailchimp voice &amp;amp; tone guide&lt;&#x2F;a&gt;, which is a very good document I suggest you read it (the title is pretty self explanatory I think).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a full list of talks given at the conference, check out the &lt;a href=&quot;http:&#x2F;&#x2F;www.writethedocs.org&#x2F;conf&#x2F;eu&#x2F;2015&#x2F;schedule&#x2F;&quot;&gt;event&#x27;s schedule&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The after party ended up happening at two venues since we got pre-maturely kicked out of the first one; we made the best of it and I got to talk to Anna Jaruga (the cloud research scientist) as well as a &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;&quot;&gt;Mozilla Development Network&lt;&#x2F;a&gt; writer, both very interesting people.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Write the Docs Day 1</title>
        <published>2015-08-31T00:00:00+00:00</published>
        <updated>2015-08-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-31/"/>
        <id>https://elijah.run/blog/2015-08-31/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-31/">&lt;p&gt;I spent most of today enjoying the Write the Docs talks and (air
conditioned) venue. I took some notes.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The keynote about the imposter syndrome was very relatable.
The coping mechanism of framing goals in &quot;I want to do...&quot; instead of &quot;I want to be...&quot; seems like it could be effective.
I liked the quote &quot;Make better mistakes tomorrow&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;The second talk about naming things was very good and got me to think about the structure of documentation metadata (using labels vs taxonomy vs thesaurus, etc).
This will be useful someday I&#x27;m sure.&lt;&#x2F;li&gt;
&lt;li&gt;The third talk about [emojii] and the use of emoji was [emojii].
I never considered using them before, but I will going forward.&lt;&#x2F;li&gt;
&lt;li&gt;The fourth talk mentioned using &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Selenium_%28software%29?wprov=sfia1&quot;&gt;Selenium&lt;&#x2F;a&gt; to test docs, that just makes sense.
It&#x27;s so obvious I wish it was easier.&lt;&#x2F;li&gt;
&lt;li&gt;The API Docs talk mentioned that you should give your user the data they will be working with as a top level priority instead of an after
thought.
This will definitely be a priority for me.
I already try to give plenty of examples (since I speak example natively), but I&#x27;ll be more Conscience of it.&lt;&#x2F;li&gt;
&lt;li&gt;The Design Docs with Disability in Mind was interesting.
The big takeaway for me was keeping the elderly in mind.&lt;&#x2F;li&gt;
&lt;li&gt;The meta talk about crafting a presentation was delivered very well and mentioned adding contrast slide decks... I should have listened to
this advice...&lt;&#x2F;li&gt;
&lt;li&gt;The second to the last talk of the day covered the plethora of rules we place on documentation.
Having just recently helped established some style guides for the OSL docs I think we did a good job of giving some leeway to the writers.
The extreme example of &#x27;Limited rules docs&#x27; (e.g., the Python Documentation) does not really work well for the reader in my experience.&lt;&#x2F;li&gt;
&lt;li&gt;The final talk by some &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;&quot;&gt;MDN&lt;&#x2F;a&gt; writers equated docs to a garden. The metaphor worked surprisingly well.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a full list of the talks and their descriptions, visit the &lt;a href=&quot;http:&#x2F;&#x2F;www.writethedocs.org&#x2F;conf&#x2F;eu&#x2F;2015&#x2F;schedule&#x2F;&quot;&gt;event&#x27;s schedule&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Day 1 was pretty emojii. We ended the night with emojii at a venue called The Pub.
Many conversations and laughs were had.
I like this crowd.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Prague Day 1</title>
        <published>2015-08-30T00:00:00+00:00</published>
        <updated>2015-08-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-30/"/>
        <id>https://elijah.run/blog/2015-08-30/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-30/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-city-center.jpg&quot; alt=&quot;Prague city center&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I went on a wonderful &lt;a href=&quot;http:&#x2F;&#x2F;www.writethedocs.org&#x2F;conf&#x2F;eu&#x2F;2015&#x2F;#events&quot;&gt;city tour&lt;&#x2F;a&gt; of Prague provided by Write The Docs.
We crossed some bridges, saw some castles, and experienced many wonderful parts of the city.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-gelato.jpg&quot; alt=&quot;My dumb face and a delicious gelato.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Here&#x27;s me in front of a church eating some gelato.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After the tour I was very hungry and tagged along with some folks from my tour group on a journey to get food.
We went to a restaurant that brought us beer on a model train.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-beer-train.jpg&quot; alt=&quot;Choo choo. Here comes the beer train.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;This is the train that brought us beer.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here are some picture I took of the buildings in the city.
I like the architecture a lot.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-city-center.jpg&quot; alt=&quot;Classic architecture in the Prague city center.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-street.jpg&quot; alt=&quot;Even the small regular old streets in Prague are breathtaking.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;They are so cool.&lt;&#x2F;em&gt;
&lt;em&gt;I haven&#x27;t found the words to describe why, but the asthetics please me.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After the tour and food there was a &lt;em&gt;Write the Docs Conference Reception&lt;&#x2F;em&gt; (aka meet &amp;amp; greet) where I got to hang out with many of the attendees of the conference.
There was food and fabulous people.&lt;&#x2F;p&gt;
&lt;p&gt;I did not have a hard time falling asleep that night.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Paperweight on my Shoulders</title>
        <published>2015-08-30T00:00:00+00:00</published>
        <updated>2015-08-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/fiction/paperweight-on-my-shoulders/"/>
        <id>https://elijah.run/fiction/paperweight-on-my-shoulders/</id>
        
        <content type="html" xml:base="https://elijah.run/fiction/paperweight-on-my-shoulders/">&lt;h2 id=&quot;prompt&quot;&gt;Prompt&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A paperweight whispers to a mathematician: &quot;I feel so depressed.&quot;
-&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;MagicRealismBot&#x2F;status&#x2F;770382059319595008&quot;&gt;MagicRealismBot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Fredrick Gustav was working well into the night as he was known to do in the weeks preceding a publication of his work.
When he worked deep into the night he took a drug called Caffeine in various forms from liquid to pill form to stay awake.&lt;&#x2F;p&gt;
&lt;p&gt;On the long nights he was also known to converse with furniture and inanimate objects around the room which were up for a quick chat as he needed to rest.
If his &#x27;people skills&#x27; were more astute (and there were people around to see him) Fredrick might be embarrassed by his own behavior but the pros really did outweigh the cons this late at night.
His bookshelf had many interesting things to say but could sometimes overwhelm him.
His chair was also good to talk with, but didn&#x27;t get out much.&lt;&#x2F;p&gt;
&lt;p&gt;Tonight Fredrick&#x27;s paperweight decided to speak up.
It was a small manatee Beanie Baby and it started the conversation similar to how his bottom drawer tended to:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;I feel so depressed.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Fredrick was shocked by the plush manatee.
It had never spoken up before and quite frankly he wasn&#x27;t sure it was able to until just now.
After the shock subsided he responded.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Well you&#x27;re a new voice.
What might your name be there beanie baby manatee?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;BBM sighed and reflected on the question but was unable to answer.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Do you have a name?
You&#x27;ve been around this office for almost a year now, it seems about time I learned what to call you.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;BBM responded positively to this idea and so Fredrick began the search for a name.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Well, it seems like &lt;em&gt;Snooty&lt;&#x2F;em&gt; is a pretty famous manatee in Florida.
Mind if I call you that?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;BBM responded shyly &quot;Yeah... that sounds okay...&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Fredrick, not picking up on the hesitation in BBM&#x27;s voice, carried on proud of his naming abilities and ready for the rest of the night.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Wonderful.So my next question is &#x27;Why do you feel depressed Snooty?&#x27;&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Snooty, who had not yet fully accepted the name, felt it was obvious why.
She had been stuck in this office for over a year and why?
She was bought by a mother and daughter and had &lt;em&gt;hoped&lt;&#x2F;em&gt; that she would be adopted by them, but of course she ended up being taken in by an old fart like Fredrick. She couldn&#x27;t tell him that but it was how she felt.
Somehow she wanted to get out of here and into the &lt;em&gt;real world&lt;&#x2F;em&gt;.
She wanted to go to the park with a kid who named her something infinitely more creative than &#x27;Snooty&#x27;.
She wanted to go on adventures and see wonders of the world outside people called &lt;em&gt;Cincinnati&lt;&#x2F;em&gt;.
Despite her fear of his reaction she quickly mustered up the gumption to tell Fredrick.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;I&#x27;m depressed because... because I&#x27;m stuck in this office when I could be on adventures with a kid.
Adventures like... like I&#x27;m supposed to be on.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Fredrick reflected on this for a while.
Glancing between her and the seventh draft of his publication.
He finally spoke up.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;I understand.
If I were you I&#x27;d want to get out of this office too.
Maybe my daughter can find a good home for you, she works with children.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Snooty was very excited at this prospect and if she could physically smile she would have just then.&lt;&#x2F;p&gt;
&lt;p&gt;A few hours later Fredrick called it a night, packed up his things, and went home with Snooty in his briefcase.
He arrive home at almost 2:47am and left Snooty in the keys bowl.
He felt sad sometimes, coming home late to an empty house.
Even his paper weight didn&#x27;t like him, how could expect his wife and children to do the same.
But he got up the next morning and did it all again.
At least he&#x27;d have his office to keep him company.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>To Prague!</title>
        <published>2015-08-29T00:00:00+00:00</published>
        <updated>2015-08-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-29/"/>
        <id>https://elijah.run/blog/2015-08-29/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-29/">&lt;h2 id=&quot;i-strongly-dislike-travel&quot;&gt;I Strongly Dislike Travel&lt;&#x2F;h2&gt;
&lt;p&gt;I would say I hate travel, but that level of hyperbole is literally the worst thing on the planet...&lt;&#x2F;p&gt;
&lt;p&gt;My strong dislike for travel comes mostly from my personal inability to trust the systems that will get me to where I am going.
If I have a flight in one week and I have to take a bus or train to the airport, I will spend the entire week running through my head
&quot;When is my flight?
Umm days, yeesh hours, and ack minutes.
How am I getting there?
The oh God bus leaving at some time, somewhere bound.
Once you get there you will go through security which will take between 5 minutes and 2 hours.
Budget your time appropriately.
Any of these systems can fail and based on experience they have&quot;
over and over and over.
The stress is compounded when people don&#x27;t always speak your language and you forgot to eat a proper meal the morning of.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;That&lt;&#x2F;em&gt; is why I am 3 hours early to my flight from Amsterdam to Prague.
I regret nothing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;currency-is-weird&quot;&gt;Currency is Weird&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-conversion-rate.jpg&quot; alt=&quot;1 USD = 24.17 Czech Republic Koruna&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is going to take me forever to remember &lt;em&gt;25 here monies is about 1 home monies&lt;&#x2F;em&gt;.
Everything is gonna feel really expensive I bet...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-made-it-to-prague&quot;&gt;I Made it to Prague&lt;&#x2F;h2&gt;
&lt;p&gt;I made it to Prague just fine. They have a cool train system.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;prague-mustek-stop.jpg&quot; alt=&quot;The MUSTEK stop in the Prague underground transit system. Very Soviet-era design.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Way cooler than the underground train systems I&#x27;m used to...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A very long bike ride</title>
        <published>2015-08-28T00:00:00+00:00</published>
        <updated>2015-08-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-28/"/>
        <id>https://elijah.run/blog/2015-08-28/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-28/">&lt;h2 id=&quot;my-butt-hurts&quot;&gt;My Butt Hurts...&lt;&#x2F;h2&gt;
&lt;p&gt;Today I went on an awesome bike ride all the way to Haarlem (15km west of Amsterdam).
I didn&#x27;t actually do anything there; I just went, picked up snacks, and headed back.
I&#x27;m 99% sure I missed out on an awesome Haarlem exclusive cultural experience, but if was really more about the journey (I originally set out to bike to the coast and Haarlem was my compromise to that).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-huge-park.jpg&quot; alt=&quot;I don&amp;#39;t recall where this park is exactly. I remember i twas east of the city center, many kilometers&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-huge-park-2.jpg&quot; alt=&quot;Another view of the park, this time with a play structure&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I found a very neat park near the Western edge of Amsterdam; I ended up spending an hour or so there having a picnic.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Dilapidated&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-dilapidated-building.jpg&quot; alt=&quot;An old and dilapiddated building. It&amp;#39;s hard to tell the building original purpose...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;This was a cool abandoned building I found.&lt;&#x2F;em&gt;
&lt;em&gt;I like abandoned buildings.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-travelers-trash-can.jpg&quot; alt=&quot;A large ice-cream cone shaped trashcan at a 45 degree angle for cyclists to dispose of trash into.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I also found this awesome trash can for people riding bikes.&lt;&#x2F;em&gt;
&lt;em&gt;It&#x27;s genius.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-ponies.jpg&quot; alt=&quot;Ponies!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;PONIES&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After the bike ride I was very tired.
I slept a lot.
And yet not enough...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;small-and-large-appreciations&quot;&gt;Small (and Large) Appreciations&lt;&#x2F;h2&gt;
&lt;p&gt;Here is a list of some of the traits of Amsterdam (and what I have experienced of the Netherlands at large) which I appreciate.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;They have signs that tell you you&#x27;re going the wrong direction.&lt;&#x2F;li&gt;
&lt;li&gt;You can bike to another city and be on bike paths the whole time!&lt;&#x2F;li&gt;
&lt;li&gt;Bikes are easy to use and aren&#x27;t shoe-horned in as a second class mode of transportation.&lt;&#x2F;li&gt;
&lt;li&gt;The trains are so quiet. Why can&#x27;t America have quiet trains?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This list will probably grow as I remember things.
All in all I like the city and the country.
You should visit if you haven&#x27;t already.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Van Vough museum</title>
        <published>2015-08-27T00:00:00+00:00</published>
        <updated>2015-08-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-27/"/>
        <id>https://elijah.run/blog/2015-08-27/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-27/">&lt;p&gt;TodayI visited the Van Gough museum.
I tried to get in using my mom&#x27;s Amsterdam Museum Pass, but it didn&#x27;t fly there like it did at the Rijks.&lt;&#x2F;p&gt;
&lt;p&gt;It was pretty fun, but the entire experience felt very artificial and plastic.
The paintings were great to see in person, but everything around the pieces felt a little tacky.
My opinion will likely change about it, but I did not enjoy the Van Gough museum nearly as much as I enjoyed the Rijks Museum, despite my love for Van Gough and his works.&lt;&#x2F;p&gt;
&lt;p&gt;I spent the rest of the day walking around and cashed in early.
Jetlag + lots of walking = ready for bed by 3pm.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Rijks museum and travel tips</title>
        <published>2015-08-26T00:00:00+00:00</published>
        <updated>2015-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-26/"/>
        <id>https://elijah.run/blog/2015-08-26/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-26/">&lt;h2 id=&quot;the-rijks-museum&quot;&gt;The Rijks Museum&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-canal.jpg&quot; alt=&quot;A panorama of an Amsterdam canal&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I&#x27;m not sure which street I took this panorama on, but I think it looks awesome.&lt;&#x2F;em&gt;
&lt;em&gt;It captures the Amsterdam canal street pretty well.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today I went to the Rijks Museum and had a bit of a culture overload.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-milk-maid.jpg&quot; alt=&quot;Chilling with the milk maid.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Everybody got selfies with Van Gough, so I got a selfie The Milkmaid.
I realize in retrospect that it doesn&#x27;t work as well.&lt;&#x2F;p&gt;
&lt;p&gt;In other news, this is my face when I realized the bathroom stalls go from floor to ceiling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-all-the-way.jpg&quot; alt=&quot;Surprise and joy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Yes, this photo was taken in the bathroom stall.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And this is a classy restaurant I found with classy lamps.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-cute-lamp.jpg&quot; alt=&quot;A lamp with a cute switch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;They were closed, otherwise I would have gone in.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-travel-tips&quot;&gt;Some Travel Tips&lt;&#x2F;h2&gt;
&lt;p&gt;Although I have not completed my trip, I have some tips to share with you about travel.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Always bring a &#x27;Go Bag&#x27; when you go out for the day.
Fill it with snacks and necessities and leave plenty of room for memorabilia you get while out and about.&lt;&#x2F;li&gt;
&lt;li&gt;Try something new before defaulting to your comfort zone.
This is true for food as well as experiences.&lt;&#x2F;li&gt;
&lt;li&gt;Always being plenty of snacks and water.
You will regret it if you don&#x27;t.&lt;&#x2F;li&gt;
&lt;li&gt;Be patient.
You invested a lot to get here, make it count.&lt;&#x2F;li&gt;
&lt;li&gt;At a museum, take a picture of the plackard after taking a picture of the piece so you don&#x27;t forget what it&#x27;s called.&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t be afraid to sit in a café and just read for a bit.
Sometimes that&#x27;s as culturally diversifying as a day in a museum or city tour.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>To Amsterdam!</title>
        <published>2015-08-25T00:00:00+00:00</published>
        <updated>2015-08-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-24-2015-08-25/"/>
        <id>https://elijah.run/blog/2015-08-24-2015-08-25/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-24-2015-08-25/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-view.jpg&quot; alt=&quot;A view of amsterdam&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pdx-ams&quot;&gt;PDX -&amp;gt; AMS&lt;&#x2F;h2&gt;
&lt;p&gt;The flight was uneventful.
It was the longest one I&#x27;ve ever been on, which is always a rough milestone to overcome, but actually one of the
better flights I&#x27;ve taken.
TIL Delta&#x27;s service does not suck.&lt;&#x2F;p&gt;
&lt;p&gt;I usually sleep the entire way to &amp;lt;insert location here&amp;gt;, but I managed to stay productive (coding, reading, writing) for the majority of flight.
I must say, it was nice to have my own personal screen to catch up on Last Week Tonight.
I&#x27;ve wanted to watch that show for ages...&lt;&#x2F;p&gt;
&lt;p&gt;[&lt;em&gt;Lazy bliss not pictured&lt;&#x2F;em&gt;]&lt;&#x2F;p&gt;
&lt;p&gt;So good.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-0-part-1&quot;&gt;Day 0: Part 1&lt;&#x2F;h2&gt;
&lt;p&gt;So I wrote down some thoughts about Amsterdam thus far:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;People keep using fake made up words. What&#x27;s up with that?&lt;&#x2F;li&gt;
&lt;li&gt;The roads are tiny but people keep driving on them.
It looks like chaos but I haven&#x27;t seen an accident yet.
I&#x27;m kinda impressed.
People aren&#x27;t even yelling at each other about almost getting hit.&lt;&#x2F;li&gt;
&lt;li&gt;The toilet paper squares are actually rectangles.
It might just be the toilet paper at the place I am staying.
Either way, I can&#x27;t deal with this aspect ratio change. I might not be able to poop in Amsterdam.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;COFFEE COFFEE COFFEE COFFEE COFFEE COFFEE COFFEE COFFEE COFFEE&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The trains are so quiet.
I didn&#x27;t want to get off...&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BIKES BIKES BIKES BIKES BIKES BIKES BIKES BIKES BIKES BIKES&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here&#x27;s some pictures I took:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-view.jpg&quot; alt=&quot;Mostly trees and sky.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The view from the location I am staying at.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-park-panorama.jpg&quot; alt=&quot;Panorama of an amsterdam park&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;A panorama from the park outside of where I am staying.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-goats.jpg&quot; alt=&quot;Goats!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Some goats I found.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Aaaaaaaand naptime.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-0-part-2&quot;&gt;Day 0: Part 2&lt;&#x2F;h2&gt;
&lt;p&gt;I finished today by going to the Red Light District. There were a lot of half naked ladies in windows.
They kept winking at me. I&#x27;m pretty sure they liked me; it&#x27;s not like they &lt;em&gt;definitely&lt;&#x2F;em&gt; have a monetary incentive to get my attention or anything.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up finding a bar and enjoying a Belgian White Beer.
It tasted &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1534&#x2F;&quot;&gt;surprisingly good&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;amsterdam-beer.jpg&quot; alt=&quot;A belgium white beer&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;So this is what it feels like to drink in a bar... neat.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Packed and Ready to Fly</title>
        <published>2015-08-23T00:00:00+00:00</published>
        <updated>2015-08-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-23/"/>
        <id>https://elijah.run/blog/2015-08-23/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-23/">&lt;h2 id=&quot;all-packed&quot;&gt;All Packed&lt;&#x2F;h2&gt;
&lt;p&gt;So I&#x27;m all packed up and ready to go.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;europe-2015&#x2F;packed.jpg&quot; alt=&quot;Three weeks of supplies neatly displayed on a pink bed&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Left:&lt;&#x2F;strong&gt; Chargers, electronics, entertainment, toiletries, water bottle, wallet, etc.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Center:&lt;&#x2F;strong&gt; The bag, the &lt;em&gt;Write the Docs&lt;&#x2F;em&gt; shirt I&#x27;ll be wearing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Right:&lt;&#x2F;strong&gt; Clothing. Gameboy SP at the top.&lt;&#x2F;p&gt;
&lt;p&gt;Not the &lt;em&gt;perfect&lt;&#x2F;em&gt; bag of things to bring to Europe, but certainly solid and most of it practical.
I&#x27;m packing an extra bag for all of the trinkets I&#x27;ll bring back.&lt;&#x2F;p&gt;
&lt;p&gt;Let me know if you want anything (if you know how to contact me we&#x27;re close enough for you to ask.)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dominos are setup</title>
        <published>2015-08-02T00:00:00+00:00</published>
        <updated>2015-08-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-02/"/>
        <id>https://elijah.run/blog/2015-08-02/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-02/">&lt;p&gt;All of my travel is booked, plane tickets are bought, and vacation time gotten.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing left to do now is to write the talk. Easy-peasy.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>About the blog (this is a test)</title>
        <published>2015-08-01T00:00:00+00:00</published>
        <updated>2015-08-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Elijah Voigt
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://elijah.run/blog/2015-08-01/"/>
        <id>https://elijah.run/blog/2015-08-01/</id>
        
        <content type="html" xml:base="https://elijah.run/blog/2015-08-01/">&lt;p&gt;This blog was created in preparation for my trip to Europe in about 3 weeks.
I wanted to see how difficult it would be to make a blog that could be updated on the go, version controlled with git, and would not require me to log into a laptop or server to make changes.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up using PageUp (link in the footer), along with Github Gists (also linked in the footer) to make a mostly useful platform.
New changes are pushed to Github, my personal server pulls those changes every 10 minutes, and this page is rebuilt pretty painlessly.&lt;&#x2F;p&gt;
&lt;p&gt;Best of all: with a git client on my phone I can make updates anywhere that has a signal and I don&#x27;t need to bust my laptop out.
I wrote this post while I was on the toilet!&lt;&#x2F;p&gt;
&lt;p&gt;It wasn&#x27;t as easy as using an established platform like Twitter, but just like with everything I try to make, I put something together I would want to use and interact with.
If a friend started a liveblog for a specific event I would follow it over their Twitter feed any day.
Plus I don&#x27;t have to deal with the character limit of Twitter.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
