Jekyll2017-07-24T11:26:46-06:00https://ryanthaut.com/Ryan Thaut (.com)Interpretations of a Bottom DwellerrthautModern VR: Initial Thoughts2017-07-24T12:20:00-06:002017-07-24T12:20:00-06:00https://ryanthaut.com/blog/2017/07/24/modern-vr-initial-thoughts<p>I, like hundreds (if not thousands) of others, have finally acquired a VR system for personal use, thanks entirely to the <a href="https://www.oculus.com/blog/rift-touch-399-for-a-limited-time-summer-of-rifts-best-deal-yet/">Oculus Rift + Touch going on sale for $399</a>. While I have only used it for a few evenings over the last week or so since it arrived, I can definitely say nearly of my previous concerns with today’s VR were unwarranted.</p>
<h2 id="an-actual-virtual-reality-experience">An Actual Virtual Reality Experience</h2>
<p>Living in Wyoming, there’s a certain lack of… local electronic entertainment presence. So my only previous experience with Virtual Reality was through the <a href="http://www.samsung.com/us/mobile/virtual-reality/gear-vr/gear-vr-sm-r322nzwaxar/">Samsung Gear VR</a>, which was free after submitting an online form when I bought my Galaxy S7. I had tried watching a 3D movie, which wasn’t a <em>bad</em> experience, but I didn’t think it was any better than watching an HD movie on a large HDTV with a good sound system. I also bought one of the “premium” games, but, considering there was no controller for it at the time (there’s a touch pad on the side of the headset), it was a truly dissapointing experience. All that is to say I simply didn’t believe the VR hype, nor did I think it was worth more than maybe $150 USD (like the Rock Band bundles of previous console generations).</p>
<p>After experiencing proper VR with the Touch controllers, I struggle to even justify calling the Gear VR a Virtual Reality experience. The Oculus Rift is <strong>far</strong> more immersive (even just visually), and the content (at least the bundled games) are fantastic. Even the introduction demo for the Touch controllers immediately pulls you in; I had forgotten I was in my computer room with a headset strapped to my face in 5 seconds.</p>
<p>So if you have never experienced VR firsthand via either the Oculus Rift or the HTC Vive, you are doing yourself a tragic disservice if you write it off completely without trying it yourself.</p>
<h2 id="cost-of-entry">Cost of Entry</h2>
<p>Despite my <em>glowing</em> recommendation for VR, particularly with motion tracking controllers, I do think the cost (at least prior to the sale) was still unjustifiable. Considering you will need a moderately powerful PC, which will probably run you $1000, there’s no way I could recommend anyone spend more than $500 on the headset and core peripherals (sensors and motion controllers). On top of the PC, the headset, the sensors, and the controllers, there’s still a few more things you will strongly want (if not need) to buy.</p>
<ol>
<li><strong>The content.</strong> While the Rift + Touch bundles do include a few games, several of which are <a href="https://www.oculus.com/robo-recall/">genuinely amazing</a>, most games cost between $25 and $50. Depending on you determine a game’s value (length, replayability, multiplayer, etc.), that may or may not be a tough pill to swallow. So far, I think the games are reasonably priced, but I usually buy my normal PC/Xbox games right at launch (or shortly thereafter) for full retail price ($60). I know some people religiously wait for games to go on sale for 50%-75% off, which I don’t think will be commonplace for VR games for a few years yet.</li>
<li><strong>Extension cables.</strong> For anything more than seated VR, I have already found the cable on the Oculus Rift headset to be just barely long enough for comfort. My current space is very small, just barely meeting the front-back distance requirements for full-motion controls (NOT room-scale), but even so, the cable could use a couple more feet of slack. Thankfully <a href="https://smile.amazon.com/dp/B00C7SA21U">extension USB</a> and <a href="https://smile.amazon.com/gp/product/B01D5H91KE">HDMI cables</a> are less than $10, even for long ones.</li>
<li><strong>Sensor mounts.</strong> These are probably lower priority than the above items, but to properly place the sensors in a large area, you want them up at eye level or higher (pointed down), so mounting them on the wall or ceiling becomes quite logical. Thankfully, the Oculus Rift sensors use a common 1/4” x 20 thread receiver, which is widely used for CCTV mounts.</li>
<li><strong>Washable covers.</strong> Again, these are not really necessary, but I found myself sweating after VR sessions, especially when playing games that utilize motion controls. However, the “cover” (the part that presses against your face) for the Oculus Rift headset, it not washable (though it is removable, by design). There are several after market versions that replace the original one and are machine washable, so if you plan on letting your friends and family try out VR for themselves, you should probably invest in something like <a href="https://vrcover.com/product/oculus-rift-facial-interface-foam-replacement-basic-set/">VR Cover’s Oculus Rift Facial Interface &amp; Foam Replacement Basic Set</a> or <a href="https://widmovr.com/product/oculus-rift-cover/">WIDMOvr’s Oculus Rift Cover</a>.</li>
</ol>
<h2 id="play-area-requirements">Play Area Requirements</h2>
<p>Much like the Xbox Kinect, the full VR experience all but requires a large play area. I can count on one finger the number of houses I have been in where the rooms that would be most suitable for an entertainment room (or a computer room) are actually big enough to comfortably use a motion tracking system. I guess the developers of those systems expect people to have massive homes, or maybe average sized homes without any furniture…</p>
<p>Regardless, do not underestimate the amount of space you will want/need, even just for “stand-in-place” VR with motion tracked controllers. For the Oculus Rift with Touch controllers, you are <em>recommended</em> to have <a href="https://support.oculus.com/help/oculus/287240295005475?helpref=hc_fnav">a play area of 7 feet by 5 feet (2 meters by 1.5 meters)</a>. My space is about 3 feet deep (from the PC screen, which is the “front” of the space) by 5 feet wide, which meets the <em>minimum</em> space requirements, but I can assure you that having another 2 feet of front-back space would be immensely useful (not to mention it would greatly reduce my worry of obliterating my PC monitor while swinging my hands around).</p>
<h2 id="recommended-tools">Recommended Tools</h2>
<p>So far the only 3rd party tool I have found to be significantly useful is the <a href="https://www.reddit.com/r/oculus/comments/6iezwq/guardian_boundary_editor_customizestraighten_your/">Guardian Boundary Editor</a>, which lets you easily edit the boundaries you create when first setting up your Touch controllers. I used it to straighten out the edges and add a notch in the front edge so I can quickly reorient myself.</p>
<p>On that note, the <a href="https://www.reddit.com/r/oculus/">Oculus</a> and <a href="https://www.reddit.com/r/Vive/">Vive</a> subreddits seem to be the best places to find VR information (news, tools, tips, etc.).</p>rthautI, like hundreds (if not thousands) of others, have finally acquired a VR system for personal use, thanks entirely to the Oculus Rift + Touch going on sale for $399. While I have only used it for a few evenings over the last week or so since it arrived, I can definitely say nearly of my previous concerns with today’s VR were unwarranted.Migrating to Jekyll2017-07-02T19:00:00-06:002017-07-02T19:00:00-06:00https://ryanthaut.com/blog/2017/07/02/migrating-to-jekyll<p>I’m honestly not entirely sure why. Probably because I wanted to learn something new. It also seems to align with my recent side projects pretty well. Whatever the reason, I am currently in the process of switching my blog from WordPress to <a href="https://jekyllrb.com">Jekyll</a>. This is not a how-to guide, or an article on the benefits of Jekyll over other blogging platforms; rather, this is simply my thoughts so far on the migration process and Jekyll in general.</p>
<h2 id="finding-jekyll">Finding Jekyll</h2>
<p>I know I had heard of Jekyll before, but I don’t remember ever actually looking into it at all. I had no idea how it worked, or what it was even designed to do, really. I happened upon it when looking for a simple CMS for working in Markdown. It wasn’t even the <a href="https://duckduckgo.com/?q=static+blog+using+markdown">first result in my searches</a>.</p>
<p>However, once I did find Jekyll, I made up my mind very quickly to use it. It seemed both simple and powerful, it allowed me to code the site in HTML+CSS+JS while writing content in Markdown, and I could even “host” it on GitHub. That last point was probably the subconscious selling factor for me: I have been pushing myself to use GitHub as much as possible for my side projects, even the ones that really don’t need to be open source, so this is just another thing to help me make that happen.</p>
<h2 id="getting-started">Getting Started</h2>
<p>Despite how simple it seemed to get going with Jekyll, there was some significant setup time. First, I knew I was going to “host” it on GitHub, which meant using <a href="https://help.github.com/articles/using-jekyll-as-a-static-site-generator-with-github-pages/">GitHub Pages</a>. That was actually quite simple to configure, but the downside was I would need to run it locally during initial development. I still use Windows as my primary OS. (Yes, I am very comfortable using Linux, but Adobe products do not work in Linux – at least not well, and most of the PC games I play do not yet support <a href="https://en.wikipedia.org/wiki/Vulkan_(API)">Vulkan</a>.) Since Jekyll is built on Ruby, that meant <a href="https://rubyinstaller.org/">a few extra steps</a> were needed before I could even start installing and configuring Jekyll itself.</p>
<h2 id="customizing">Customizing</h2>
<p>These days I don’t really spend any time at all <em>designing</em> websites. My professional career is almost exclusively enterprise cloud integrations development &amp; consulting, so most of what I do is server-side. I occasionally get to do front-end development work, but that is almost always just building out a client’s designs inside (or on top) of a cloud system. That said, I definitely still enjoy design work, so there was absolutely no way I was going to use one of the “standard” Jekyll themes (not that there’s anything wrong with them).</p>
<p>I’m starting with basically just porting the WordPress theme I had created for my blog a few years ago, but rebuilding all of the HTML and CSS from scratch. Once I have that figured out, I may work on a proper redesign, but there are a few hurdles to get through first.</p>
<h3 id="limitations-of-github-pages">Limitations of GitHub Pages</h3>
<p>One of the fantastic features of using GitHub is that the Jekyll site is automatically regenerated whenever changes are pushed to the remote repository. Unfortunately, it seems GitHub has configured Jekyll to run in Safe Mode, which disables plugins. Additionally, you can use a package manager like <a href="https://www.npmjs.com/">NPM</a> or <a href="https://bower.io/">Bower</a> to maintain dependencies (like <a href="https://v4-alpha.getbootstrap.com/">Bootstrap</a>, <a href="http://primercss.io/">Primer CSS</a>, etc.), but you would have to upload the files your project is using to GitHub for them to be available in the Jekyll build process, which basically defeats the purpose of using a package manager.</p>
<p>I’m still working through exactly how I want to handle this. For now, I am including Bootstrap’s CSS and JS files from their CDN, then my SASS file generates CSS rules for overriding Bootstrap. This is very much not ideal, but I also don’t necessarily want to upload all of the Bootstrap SASS files (plus my modifications in <code class="highlighter-rouge">_custom.scss</code> and whatnot) to the repository.</p>
<p>Another possible solution to this conundrum is to run Jekyll locally to build the site, then upload the generated files to GitHub, rather than letting GitHub do that for you. That approach bothers me probably more than it should, so that will likely be my last-ditch option.</p>
<h3 id="reinventing-the-wheel">Reinventing the Wheel</h3>
<p>I suspect the process of switching to Jekyll could have taken me weeks (working here on there on evenings/weekends) had I tried to build and theme my site solely using the Jekyll documentation. The documentation itself isn’t necessarily bad, but it is short on full examples of starting a new theme from scratch.</p>
<p>Thankfully, GitHub has a list of <a href="https://github.com/showcases/github-pages-examples">projects using GitHub Pages</a>, and many of them use Jekyll. That list provided a vast amount of examples and inspiration, which I found to be incredibly useful.</p>rthautI’m honestly not entirely sure why. Probably because I wanted to learn something new. It also seems to align with my recent side projects pretty well. Whatever the reason, I am currently in the process of switching my blog from WordPress to Jekyll. This is not a how-to guide, or an article on the benefits of Jekyll over other blogging platforms; rather, this is simply my thoughts so far on the migration process and Jekyll in general.FreeNAS 9.10+ Setup Notes2017-05-19T00:27:45-06:002017-05-19T00:27:45-06:00https://ryanthaut.com/blog/2017/05/18/freenas-9-10-setup-notes<p>This is a collection of notes I took while setting up a new NAS running FreeNAS 9.10. The issues I ran into initially were around enabling SSH and correctly configuring SMB/CIFS Shares for Windows. Maybe I just missed something obvious, or maybe these are actual issues that have plagued others before, but I plan on updating this as needed.</p>
<h2 id="switching-from-synology-diskstation-to-freenas">Switching from Synology DiskStation to FreeNAS</h2>
<p>A few weeks ago I noticed that my Synology NAS (the DS716+ II unit) was running low on available space. As this device only has 2 bays, both of which are occupied with 3TB HDDs (using Synology’s Hybrid RAID), I figured it would be wiser to acquire new enclosure with more bays, rather than to swap in larger HDDs and have to mount the current drives somewhere else to facilitate the data transfer.</p>
<p>However, I couldn’t bring myself to spend hundreds of dollars on a pre-made device with such under-powered hardware, and I definitely couldn’t justify spending $1000.00 (or more) on the few devices that better aligned with my hardware requirements.</p>
<p>So I spent many nights researching both hardware and software for a DIY NAS. I may post my actual NAS build at some point, but this post is specifically for documenting some of the nuances I encountered with FreeNAS (which is what I have currently elected to use on my DIY NAS).</p>
<h2 id="enabling-ssh-and-mounting-the-freenas-filesystem">Enabling SSH (and Mounting the FreeNAS Filesystem)</h2>
<p>I sincerely hope this is just a bug with FreeNAS 9.10, but for me, simply enabling the SSH service didn’t actually allow me to connect via SSH to the box. Using the shell tool built into the FreeNAS Web GUI, I found that sshd wasn’t running (<code class="highlighter-rouge">service sshd status</code>).</p>
<p>So I had to manually enable sshd by adding <code class="highlighter-rouge">sshd_enable="YES"</code> to the <code class="highlighter-rouge">/etc/rc.conf</code> file. After that I could SSH into my NAS and everything seemed fine. Upon rebooting the machine, though, SSH was once again disabled, and the <code class="highlighter-rouge">/etc/rc.conf</code> file no longer had my addition to enable sshd. What gives?!</p>
<p>It turns out you have to mount the FreeNAS filesystem root in write mode before making changes to the system files. So here’s what I had to do:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>mount -uw /
nano /etc/rc.conf # or whatever your editor of choice is, as long as it isn't vim...
</code></pre>
</div>
<p><strong>Bottom line</strong>: if you are going to modify any files from the FreeNAS filesystem, make sure you mount it first. Even though you can see and modify the files, they are reset when the system reboots.</p>
<h2 id="user-storage-and-dynamic-windows-shares-via-smb">User Storage and “Dynamic” Windows Shares (via SMB)</h2>
<p>This caused me tremendous headache, and, to be honest, my solution may not be complete (or secure).</p>
<p>What I wanted to do was share each user’s home directory to Windows, but do so with a “dynamic” mount point. Synology DiskStation exposes this functionality very simply, and I have found it to be tremendously useful for a network with a handful of users.</p>
<h3 id="what-i-wanted">What I wanted:</h3>
<p>Any user on the network could mount <strong>\ [SERVER_NAME] \ Home</strong> (spaces added for legibility) as a network drive in Windows, and have that automatically point to their own home directory on the NAS with write permissions.</p>
<p>After searching the Internet, I realized that most guides and forum posts where for FreeNAS 9.3 or earlier, which utilized CIFS for the Windows shares. Unfortunately, FreeNAS 9.10 uses Samba instead, and the configuration is notably different.</p>
<p>So here’s a step-by-step of what I have done. Some of these steps may be unnecessary, but none of them are counter-productive (as best I can tell).</p>
<ol>
<li>Create a dataset for the home(s) root directory
<ul>
<li>Example path: <strong>/ mnt / [POOL_NAME] / [DATASET_NAME] / homes</strong> (spaces added for legibility)</li>
<li>I used a Unix share type, as at least my own user would be using the same directory in Linux and Windows</li>
</ul>
</li>
<li>Create a dataset for each user under the home(s) dataset
<ul>
<li>The dataset name should match the user’s Windows username</li>
<li>Example path: <strong>/ mnt / [POOL_NAME] / [ROOT_DATASET_NAME] / homes / [USERNAME]</strong> (spaces added for legibility)</li>
<li>I again used a Unix share type for these directories</li>
</ul>
</li>
<li>Create a “users” group</li>
<li>Create a user for each person who will be accessing the NAS
<ul>
<li>I left the primary group as their username (typical for Linux), and added them to the “users” group as an auxiliary</li>
<li>The username <strong>must</strong> match their username from Windows, unless you want to create more headache down the road…</li>
<li>Point their home directory to the directory you created in step 2</li>
</ul>
</li>
<li>Back under the storage section, ensure the home(s) dataset has the following <strong>permission</strong> settings:
<ul>
<li><strong>Apply Owner</strong>: checked</li>
<li><strong>Owner (user)</strong>: root</li>
<li><strong>Apply Group</strong>: checked</li>
<li><strong>Owner (group)</strong>: users</li>
<li><strong>Apply Mode</strong>: checked</li>
<li><strong>Mode</strong> (check the following):
<ul>
<li><strong>Read</strong>: Owner, Group, Other</li>
<li><strong>Write</strong>: Owner, Group</li>
<li><strong>Execute</strong>: Owner, Group, Other</li>
</ul>
</li>
<li><strong>Permission Type</strong>: Unix</li>
</ul>
</li>
<li>Now ensure each of the datasets for your users have the following <strong>permission</strong> settings:
<ul>
<li><strong>Apply Owner</strong>: checked</li>
<li><strong>Owner (user)</strong>: [username]</li>
<li><strong>Apply Group</strong>: checked</li>
<li><strong>Owner (group)</strong>: [username]</li>
<li><strong>Apply Mode</strong>: checked</li>
<li><strong>Mode</strong> (check the following):
<ul>
<li><strong>Read</strong>: Owner, Group, Other</li>
<li><strong>Write</strong>: Owner, Group</li>
<li><strong>Execute</strong>: Owner, Group, Other</li>
</ul>
</li>
<li><strong>Permission Type</strong>: Unix</li>
</ul>
</li>
<li>Create a new Windows (SMB) Share as follows
<ul>
<li><strong>Path</strong>: select the home(s) folder from step 2
<ul>
<li>Example path: <strong>/ mnt / [POOL_NAME] / [DATASET_NAME] / homes</strong> (spaces added for legibility)</li>
</ul>
</li>
<li><strong>Use as home share</strong>: UNCHECKED
<ul>
<li>This is what threw me for a long time, as normally you would want to check this box, but doing so has several caveats</li>
</ul>
</li>
<li><strong>Name</strong>: Home
<ul>
<li>Whatever value you use here will be the “folder” of the network path used in Windows</li>
<li>Do NOT use “homes” as that is a special value in Samba that will have some unwanted results</li>
</ul>
</li>
<li><strong>Apply Default Permissions</strong>: checked</li>
<li><strong>Browsable to Network Clients</strong>: checked</li>
<li><strong>Allow Guest Access</strong>: UNCHECKED
<ul>
<li>You don’t want someone to be able to access a different user’s stuff, do you?</li>
</ul>
</li>
<li><strong>Auxiliary Parameters</strong>:
<div class="highlighter-rouge"><pre class="highlight"><code>valid users = %U
path = %H
</code></pre>
</div>
</li>
</ul>
</li>
<li>Wait for the Samba service to restart (or manually restart it using <code class="highlighter-rouge">service samba_server restart</code> via shell/SSH)</li>
<li>On a Windows machine, access <strong>\ [SERVER_NAME] \ Home</strong> (removing the spaces I added for legibility)
<ul>
<li>Assuming your Windows username matches one of the users you setup in FreeNAS, you should be taken to “your” home directory, and you should be able to create, update, and delete files and folders</li>
</ul>
</li>
</ol>
<h3 id="the-resulting-samba-configuration">The Resulting Samba Configuration</h3>
<p>Your <code class="highlighter-rouge">/etc/local/smb4.conf</code> file should end up with an entry like this (note the 2 bottom lines):</p>
<div class="highlighter-rouge"><pre class="highlight"><code>[Home]
path = /mnt/my-pool/data/homes
comment = Home Directories
printable = no
veto files = /.snapshot/.windows/.mac/.zfs/
writeable = yes
browseable = yes
shadow:snapdir = .zfs/snapshot
shadow:sort = desc
shadow:localtime = yes
shadow:format = auto-%Y%m%d.%H%M-1m
shadow:snapdirseverywhere = yes
vfs objects = shadow_copy2 zfs_space zfsacl streams_xattr aio_pthread
hide dot files = yes
guest ok = no
nfs4:mode = special
nfs4:acedup = merge
nfs4:chown = true
zfsacl:acesort = dontcare
valid users = %U #important
path = %H #important
</code></pre>
</div>
<h3 id="the-important-pieces">The Important Pieces</h3>
<ul>
<li>Don’t use the “Use as home share” option for your Windows (SMB) Share of the home(s) directory, as that exposes folders for each user to the network (as well as an extra “homes” folder), and doesn’t seem to correctly set access permissions.</li>
<li>Use the Auxiliary Parameters I provided above for the Windows (SMB) Share of the home(s) directory.
<ul>
<li>These values remap the path to the connecting user’s home directory (instead of exposing the parent home(s) directory to everyone) and ensures that user is given access.</li>
</ul>
</li>
<li>Don’t just manually add an entry to the <code class="highlighter-rouge">/etc/local/smb4.conf</code> file, as the FreeNAS Web GUI doesn’t seem to pick those up (which means you can end up with duplicate entries). Always create a new share via the FreeNAS Web GUI and just add your auxiliary Samba configs there.</li>
</ul>rthautThis is a collection of notes I took while setting up a new NAS running FreeNAS 9.10. The issues I ran into initially were around enabling SSH and correctly configuring SMB/CIFS Shares for Windows. Maybe I just missed something obvious, or maybe these are actual issues that have plagued others before, but I plan on updating this as needed.PHP: Implode a Multidimensional Array2013-09-12T17:47:58-06:002013-09-12T17:47:58-06:00https://ryanthaut.com/blog/2013/09/12/implode-a-multidimensional-array<p>I can’t image this is a common problem, but I recently needed to implode a multidimensional array into all possible combinations for a <a href="https://www.managerisms.com">side project</a>. Since I may need to use this again (or maybe someone else needs something similar), I thought I would post my solution here and attempt to explain it. I also put together a <a href="http://sandbox.ryanthaut.com/md_implode.php">live demo</a>; you might want to check it out before reading the rest of this post.</p>
<h2 id="final-result">Final Result</h2>
<p>Here is the final result for anyone just looking for the code:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">function</span> <span class="nf">multidimensional_implode</span><span class="p">(</span><span class="nv">$glue</span><span class="p">,</span> <span class="nv">$pieces</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$total</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$piece</span><span class="p">)</span>
<span class="nv">$total</span> <span class="o">*=</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">);</span>
<span class="nv">$variations</span> <span class="o">=</span> <span class="nb">array_fill</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$total</span><span class="p">,</span> <span class="nb">array_fill</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$pieces</span><span class="p">),</span> <span class="kc">null</span><span class="p">));</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$j</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$step</span> <span class="o">=</span> <span class="nb">ceil</span><span class="p">((</span><span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">)</span> <span class="o">/</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">),</span> <span class="nv">$j</span><span class="p">)));</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">);</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$k</span> <span class="o">=</span> <span class="p">(</span><span class="nb">floor</span><span class="p">(</span><span class="nv">$i</span> <span class="o">/</span> <span class="nv">$step</span><span class="p">)</span> <span class="o">%</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">));</span>
<span class="nv">$variations</span><span class="p">[</span><span class="nv">$i</span><span class="p">][</span><span class="nv">$j</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$pieces</span><span class="p">[</span><span class="nv">$j</span><span class="p">][</span><span class="nv">$k</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$variations</span> <span class="k">as</span> <span class="nv">$i</span> <span class="o">=&gt;</span> <span class="nv">$variation</span><span class="p">)</span>
<span class="nv">$variations</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">implode</span><span class="p">(</span><span class="nv">$glue</span><span class="p">,</span> <span class="nv">$variation</span><span class="p">);</span>
<span class="k">return</span> <span class="nv">$variations</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>Now that the copy-pasters have their code, the rest of us can dive in.</p>
<!--more-->
<h2 id="example-scenario">Example Scenario</h2>
<p>Imagine, if you will, that you had a sentence of three words, but each word had multiple options, like this:</p>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Position 1</th>
<th>Position 2</th>
<th>Position 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>man<br />woman</td>
<td>likes</td>
<td>red<br />green<br />blue</td>
</tr>
</tbody>
</table>
<p>Now imagine that your goal was to convert that into all possible 3 word sentence permutations like this:</p>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Position 1</th>
<th>Position 2</th>
<th>Position 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>man</td>
<td>likes</td>
<td>red</td>
</tr>
<tr>
<td>man</td>
<td>likes</td>
<td>green</td>
</tr>
<tr>
<td>man</td>
<td>likes</td>
<td>blue</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>red</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>green</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>blue</td>
</tr>
</tbody>
</table>
<p>I realize that is a bit crazy, but hopefully it illustrates the point. It would obviously be easy to explode() the original string on the pipes to get array of length 3, and then you could explode() each of those 3 elements again (this time on the commas) to get a multidimensional array. However, it is much more complicated to take that multidimensional array and turn it into all possible combinations. Obviously we aren’t looking for a solution specific to this example, but something that would work for any reasonable situation.</p>
<p><strong>Note:</strong> assume from this point on that we are working with a multidimensional array that needs to be imploded()’d into all possible combinations.</p>
<h2 id="getting-started">Getting Started</h2>
<p>The first bit of useful information needed for a solution is: <strong>how many possible variations are there?</strong> Calculating that is trivial, similar to calculating how many unique license plate combinations a state can have. Simply multiply the number of options available for each position. So for the above example, we get: 2x1x3=6.</p>
<p>To do that with an array, we simply loop through the first dimension and multiply the number of elements in each position:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="nv">$total</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$piece</span><span class="p">)</span>
<span class="nv">$total</span> <span class="o">*=</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>I then built out an empty array to iterate over, as it will simplify counting/looping later, but it is not necessary:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="nv">$variations</span> <span class="o">=</span> <span class="nb">array_fill</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$total</span><span class="p">,</span> <span class="nb">array_fill</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$pieces</span><span class="p">),</span> <span class="kc">null</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>Now that we know how many variations there will be, we simply need to spread out the options into each position. <strong>Except it is not simple at all.</strong></p>
<h2 id="building-each-variation">Building Each Variation</h2>
<p>Obviously we need to loop through each position of the first dimension of the array, so we have this as our base loop:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$position</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// code for each position
</span><span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<h3 id="the-step-amount">The Step Amount</h3>
<p>If we go back to the original example or work through it logically, it is clear that of the 6 combinations, 3 will have “man” for the first word and the other 3 will all start with “woman.” Additionally, it is clear that since there are 3 possibilities for the 3<sup>rd</sup> word, each of the 3 words will be in 2 sentences (one “man” and one “woman” for each word). From this we can deduce that <strong>the number of variations built with each option for each position is directly related to the number of options for that position</strong>. We calculate this by simply dividing the total number of variations by the number of options for that position. I call this the “step amount” because it says we will build this many variations using the first option before “stepping up” to the next option.</p>
<p>Using this information, we end up with the following basic division for the step amount:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$position</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$step</span> <span class="o">=</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">)</span> <span class="o">/</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">));</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>Unfortunately, the “step amount” cannot be the same for all of the positions because <strong>that would lead to duplicates</strong>. Using our example, you would end up with this:</p>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Position 1</th>
<th>Position 2</th>
<th>Position 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>man</td>
<td>likes</td>
<td>red</td>
</tr>
<tr>
<td>man</td>
<td>likes</td>
<td>red</td>
</tr>
<tr>
<td>man</td>
<td>likes</td>
<td>green</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>green</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>blue</td>
</tr>
<tr>
<td>woman</td>
<td>likes</td>
<td>blue</td>
</tr>
</tbody>
</table>
<p>Since you went through the first option in steps of 3, you can’t just go through the last word in steps of 2 (at least not linearly). To solve for this, we have to factor the position into our step amount calculation.</p>
<h3 id="the-scaled-step-amount">The Scaled Step Amount</h3>
<p>To keep things simple, we can step through the first position using the full step amount, since nothing else has been built out yet. However, the remaining words all need incrementally smaller step amounts so that each variation of the first position has all variations of the remaining position(s). Using our example, we can see that the third position actually needs to step by 1 option each time. Additionally, <strong>it needs to reset</strong> once it reaches the first statement built using the second available word. To accomplish this, we must divide the step amount by the number of available pieces, and this division must occur repeatedly for each position.</p>
<p>The best way I found to accomplish this was as follows:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$position</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$step</span> <span class="o">=</span> <span class="nb">ceil</span><span class="p">((</span><span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">)</span> <span class="o">/</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">),</span> <span class="nv">$position</span><span class="p">)));</span>
<span class="c1">// code to assign each possible word into a variation
</span><span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>This essentially takes our original step amount and divides it by a multiple of the amount of pieces available for the current position.</p>
<h3 id="inserting-each-word-into-the-correct-variations">Inserting Each Word into the Correct Variations</h3>
<p>Now we are pretty much ready to start inserting words into the variations. Since we are looping through each position of the original multidimensional array, we now just need to loop through each variation so we can insert the words (i.e. from top to bottom, then left to right):</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$position</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$step</span> <span class="o">=</span> <span class="nb">ceil</span><span class="p">((</span><span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">)</span> <span class="o">/</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">),</span> <span class="nv">$position</span><span class="p">)));</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$variation</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$variation</span> <span class="o">&lt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">);</span> <span class="nv">$variation</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// code to insert word into variation
</span> <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>At this point all that is left is to use the step amount to select the correct option from the original multidimensional array. To calculate that position, we simply divide which variation we are processing by the step amount and take the integer value of that quotient. This means that if our step value is 3 and there are 6 combinations, we will get something like this:</p>
<ul>
<li>0.000… <strong>(integer value: 0)</strong></li>
<li>0.333… <strong>(integer value: 0)</strong></li>
<li>0.666… <strong>(integer value: 0)</strong></li>
<li>1.000… <strong>(integer value: 1)</strong></li>
<li>1.333… <strong>(integer value: 1)</strong></li>
<li>1.666… <strong>(integer value: 1)</strong></li>
</ul>
<p>So you can see that if we use this calculated position as the index, we will take the first option 3 times and then the second option 3 times. As explained earlier, for the smaller step amounts we have to loop back to the beginning, so a simple modulus on the number of options available for the current position will keep us looping without hiccup. So this is how we calculate the position to pull from the original multidimensional array:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="nv">$target</span> <span class="o">=</span> <span class="p">(</span><span class="nb">floor</span><span class="p">(</span><span class="nv">$variation</span> <span class="o">/</span> <span class="nv">$step</span><span class="p">)</span> <span class="o">%</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>
<p>Putting it all together, our final loop is:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$pieces</span> <span class="k">as</span> <span class="nv">$position</span> <span class="o">=&gt;</span> <span class="nv">$piece</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$step</span> <span class="o">=</span> <span class="nb">ceil</span><span class="p">((</span><span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">)</span> <span class="o">/</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">),</span> <span class="nv">$position</span><span class="p">)));</span>
<span class="k">for</span> <span class="p">(</span><span class="nv">$variation</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$variation</span> <span class="o">&lt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$variations</span><span class="p">);</span> <span class="nv">$variation</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$target</span> <span class="o">=</span> <span class="p">(</span><span class="nb">floor</span><span class="p">(</span><span class="nv">$variation</span> <span class="o">/</span> <span class="nv">$step</span><span class="p">)</span> <span class="o">%</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$piece</span><span class="p">));</span>
<span class="nv">$variations</span><span class="p">[</span><span class="nv">$variation</span><span class="p">][</span><span class="nv">$position</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$pieces</span><span class="p">[</span><span class="nv">$position</span><span class="p">][</span><span class="nv">$target</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>
<h2 id="imploding-the-variations">Imploding the Variations</h2>
<p>Now the simple part is to loop through all of our populated variations and implode them:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$variations</span> <span class="k">as</span> <span class="nv">$i</span> <span class="o">=&gt;</span> <span class="nv">$variation</span><span class="p">)</span>
<span class="nv">$variations</span><span class="p">[</span><span class="nv">$i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">implode</span><span class="p">(</span><span class="nv">$glue</span><span class="p">,</span> <span class="nv">$variation</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>
<h2 id="conclusion">Conclusion</h2>
<p>It took me forever to figure out the scaled step amount, which is why I didn’t fully explain the logic behind <strong>why</strong> we must raise the number of options to a power of the position. That alone could (and maybe should) be a separate post, but without the context, I don’t think it could possibly be useful to anyone.</p>
<p>This solution performs reasonably well, but quickly blows up if you have lots of potential combinations. I haven’t properly bench-marked it, but the only other alternative I found that “worked” was exponentially slower; it involved verifying a constructed combination was unique, which equates to programmatic guess-and-check, which is not a solution.</p>rthautI can’t image this is a common problem, but I recently needed to implode a multidimensional array into all possible combinations for a side project. Since I may need to use this again (or maybe someone else needs something similar), I thought I would post my solution here and attempt to explain it. I also put together a live demo; you might want to check it out before reading the rest of this post.Sublime Text 3: Markdown and Live Reload2013-08-17T05:18:32-06:002013-08-17T05:18:32-06:00https://ryanthaut.com/blog/2013/08/17/sublime-text-3-markdown-and-live-reload<p>Recently I have started using the <a href="http://en.wikipedia.org/wiki/Markdown">Markdown syntax</a> for all of my notes, to-do lists, etc. due to the readability it offers (not to mention I have been using a similar syntax of my own for years). Obviously one of the biggest perks to using Markdown is that you can quickly generate an HTML document from it for a more polished presentation.</p>
<p>I have also been using <a href="http://www.sublimetext.com/">Sublime Text</a> for well over a year now, and I absolutely love it. I consider it to be a Vim/Notepad++ hybrid, bringing <em>nearly</em> all of my favorite features (more on that later…) from both together into one editor. Today I wanted to try using Markdown to actually generate an entire webpage, and I quickly realized that I would like to live preview my changes in a browser; enter the <a href="https://github.com/revolunet/sublimetext-markdown-preview">Markdown Preview</a> and <a href="https://github.com/dz0ny/LiveReload-sublimetext2">LiveReload</a> packages.</p>
<p>Setup for this was actually very simple, except for one oversight that took me far too long to resolve…</p>
<h2 id="installation">Installation</h2>
<ol>
<li>The very first thing you should do when getting started with Sublime Text is to install <a href="https://sublime.wbond.net/installation">Package Control</a> and familiarize yourself with it. Hit <kbd>CTRL+SHIFT+P</kbd> and type “Package” to find all of the relevant commands.</li>
<li>Next, use Package Control to install the aforementioned “Markdown Preview” and “LiveReload” packages.</li>
<li>Install the <a href="http://feedback.livereload.com/knowledgebase/articles/67441-how-do-i-start-using-livereload-">LiveReload server application</a> for your OS of choice.</li>
<li>Install the <a href="http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-">LiveReload browser extension</a> for your browser of choice.</li>
<li>Start the LiveReload server and add your project directory to the site folders.
<ul>
<li><strong>Important:</strong> Markdown preview generates the HTML documents in a temporary folder by default (Windows: <code class="highlighter-rouge">C:\Users\&lt;username&gt;\AppData\Local\Temp\</code> by default)</li>
</ul>
</li>
<li>Restart Sublime Text and your browser.</li>
</ol>
<h2 id="usage">Usage</h2>
<ol>
<li>Open up a Markdown file and use the “Markdown Preview: Preview in Browser” option (via <kbd>CTRL+SHIFT+P</kbd>) to generate an HTML document and open it in your default browser.
<ul>
<li>This can be bound to a hotkey, as described in the <a href="https://github.com/revolunet/sublimetext-markdown-preview#usage-">Usage section of the Markdown Preview Github README</a>.</li>
</ul>
</li>
<li>Click the LiveReload button in your browser to enable the LiveReload functionality (the button’s enabled state has a red dot in the middle of the icon).</li>
<li>Make some changes in your Markdown file and hit save; the HTML document in your web browser should automatically update.</li>
</ol>
<h2 id="issues">Issues</h2>
<p>The only issue I had took me long enough to discover that I decided to document it here. Basically, <strong>there are only certain file extensions for which the Markdown Preview package enables the LiveReload functionality by default</strong>. I happen to save all of my Markdown files as “.txt” files, just in case I need to access them on my phone (or anywhere else that the “.md” or “.markdown” extensions could cause issues). Unfortunately, “.txt” is NOT one of the extensions that automatically has this support by default. Fortunately, there is a setting in the Markdown Preview package that controls which extensions should have the LiveReload functionality:</p>
<ol>
<li>Using the menu, navigate as follows: <code class="highlighter-rouge">Preferences &gt; Package Settings &gt; Markdown Preview &gt; Settings - User</code>
<ul>
<li>Insert the following block of text (assuming the file is blank; if the file already has content, just modify the <code class="highlighter-rouge">"markdown_filetypes"</code> line):
<div class="highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nt">"markdown_filetypes"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">".md"</span><span class="p">,</span><span class="w"> </span><span class="s2">".markdown"</span><span class="p">,</span><span class="w"> </span><span class="s2">".mdown"</span><span class="p">,</span><span class="w"> </span><span class="s2">".txt"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
</li>
</ul>
</li>
</ol>
<p>Obviously if your Markdown files use a different extension(s), update the list accordingly. I hope this saves someone else the time and frustration of not having your files auto-update.</p>rthautRecently I have started using the Markdown syntax for all of my notes, to-do lists, etc. due to the readability it offers (not to mention I have been using a similar syntax of my own for years). Obviously one of the biggest perks to using Markdown is that you can quickly generate an HTML document from it for a more polished presentation.The Five Stages of Insomnia2012-03-24T06:28:40-06:002012-03-24T06:28:40-06:00https://ryanthaut.com/blog/2012/03/24/the-five-stages-of-insomnia<p>I actually wrote most of this a few nights ago when I was unable to sleep (shock, I know). The nearly exclusive reason for my occasional insomnia is that my brain is not ready to let me sleep, despite the rest of my body eagerly waiting rest. So there I was, not sleeping, when I realized over the last hour or so I had transitioned through several “phases.” Thinking back on those “phases,” I realized they were noticeably similar to the infamous <a href="http://en.wikipedia.org/wiki/K%C3%BCbler-Ross_model">Five Stages of Grief</a>. Coincidence or not, I had to document my observations.</p>
<h2 id="stage-1-denial">Stage 1: Denial</h2>
<p>The denial stage is not so much about denying you are unable to obtain sleep. Instead, it occurs prior to the lack of obtaining sleep; specifically, when you decide to go to bed for various reasons other than you are literally falling asleep. Perhaps you have to be up earlier than normal the following day, or maybe it is fast approaching 2:15 AM and society tells us that we should be asleep at this time (unless you work a night shift, or you play video games). Regardless of the reason you decide to go to bed, it is not a good enough reason. This is denial, as it relates to insomnia.</p>
<h2 id="stage-2-anger">Stage 2: Anger</h2>
<p>At this point you are lying in your bed (or hanging from the rafters if conventional beds are too cliché for you). You realize you are not sleeping, primarily because <a href="http://starwars.wikia.com/wiki/Sith">Sith apprentice</a>.</p>
<p>“Come on,” you angrily think to yourself. “I need to be up in 4 hours. At this rate I will be lucky if I get a solid 3 hours of sleep.” Your anger has caused you to preclude the possibility of falling asleep this very instant, and instead have made the assumption that your lack of rest will continue for a while longer, but hopefully not more than another 60 minutes.</p>
<p>Eventually the anger passes, but you are still left awake.</p>
<h2 id="stage-3-bargaining">Stage 3: Bargaining</h2>
<p>It’s time to get smart about this. “Being upset about this won’t solve anything; I need to &lt;insert any sports analogy or common “manager” phrase&gt; so I can get to sleep.” So you start bargaining with your brain; after all, even if you have nothing substantial to offer your brain, it may just take pity on you and let you sleep. So you start simple: “If you let me sleep soon, I promise to go to bed at a regular time every night. That way it will become routine for you.” A few minutes pass, and <strike>that asshole</strike> your brain is still thinking.</p>
<p>“Surely I can do better than that,” you think, scrambling for something brains want even more than zombies. “I know! I will read more books, and they won’t all be from the juvenile fiction (a.k.a. young-adults literature) section! I probably don’t utilize you as well or as often as I should, but reading books should change that.” So now you are thinking about what books you could be reading to uphold your end of the ingenious bargain you just struck with your own mind. You even briefly recall some of the good books you have read throughout your life; just when you seem to be drifting off to <a href="http://www.imdb.com/title/tt0104740/">Slumberland</a>, your brain cruelly reminds you that you are still awake.</p>
<p>“I swear to all things holy, if you let me sleep now <strong>I will drown you with all the caffeine I can afford</strong> for the rest of the week! We probably won’t sleep for days, and you will be able to think about EVERYTHING imaginable!” Alas, even promises of gratuitous amounts of chemical energy are not enough for you to achieve sleep.</p>
<h2 id="stage-4-depression">Stage 4: Depression</h2>
<p>At this point, you become overwhelmed with sadness. Even if you manage to fall asleep within the next few minutes, you won’t even get half of your normal night’s rest. You are going to be worthless tomorrow morning, and probably well into the afternoon. You will want to go to bed at 8:00 PM, which ruins your entire evening, and, to top it all off, this same <em>**</em> thing will probably happen the following night due to your early bedtime!</p>
<p>“This is terrible! I just want sleep. It’s free and awesome and healthy and it is even supposed to be effortless.” Thankfully, the depression stage typically passes the quickest, primarily because your brain hates being depressed. It is a total buzz kill, which, as it turns out, is exactly what was needed for your brain to finally submit to sleep.</p>
<h2 id="stage-5-acceptance">Stage 5: Acceptance</h2>
<p>“Finally! We are on the verge sleep!” Indeed you are. Having weathered through 4 unforgiving stages, you are finally ready to accept the fact that you probably aren’t going to get any sleep whatsoever tonight. So you might as well be productive and write a new post for your blog, or check all 18 social networks you are registered on. Maybe you even watch some late night programming and buy some things that look totally awesome at 3:30 in the morning.</p>
<p>“This is nice, actually,” you peacefully say out loud. “I can get so much done now that my day is starting almost 3 hours early.”</p>
<p><em>BEEP BEEP BEEP</em> That’s the alarm, alerting you that the day has begun.</p>rthautI actually wrote most of this a few nights ago when I was unable to sleep (shock, I know). The nearly exclusive reason for my occasional insomnia is that my brain is not ready to let me sleep, despite the rest of my body eagerly waiting rest. So there I was, not sleeping, when I realized over the last hour or so I had transitioned through several “phases.” Thinking back on those “phases,” I realized they were noticeably similar to the infamous Five Stages of Grief. Coincidence or not, I had to document my observations.Pedestrian Roadkill2012-01-29T22:02:48-07:002012-01-29T22:02:48-07:00https://ryanthaut.com/blog/2012/01/29/pedestrian-roadkill<p>Maybe it’s just me, but don’t most pedestrians seem like morons around motor vehicles? Perhaps their self-preservation instincts shut off when they are walking in and around traffic. It seems abundantly obvious that motor vehicles should always have the right of way, given that in the event of a collision, people on foot stand no chance against automobiles. I understand that there are many situations where, by law, car traffic must yield to foot traffic, but I am speaking in regards to the people who will cross a street without even looking to see if the surrounding vehicles are yielding to them.</p>
<p>Where I come from, it doesn’t matter if you, as the pedestrian, have the right of way or not: you <em>always</em> check to make sure you won’t be hit before crossing in front of traffic. And not only do you stop and check, but you wave towards any vehicles that stopped for you, even if traffic laws dictate they stop for pedestrians. Your wave is a simple, polite way of saying, “<strong>Thank you for not running me the **** over.</strong>”</p>
<p>There are only a few cities in the United States that I have spent time in, so maybe where I come from, we do things “wrong.” That’s not too hard to believe, since Wyoming is not known for being politically correct, or following the social standards commonly portrayed in the media. Instead, we often rely on common sense to dictate our standards. In this particular situation, pedestrians yield to anything with wheels, especially if it has wheels and an engine. People on bikes ride on the sidewalks wherever sidewalks are present, and they yield to cars and trucks at all times.</p>
<p>It seems highly illogical that bikes are supposed to ride on the roads with cars and trucks, instead of on sidewalks with skateboarders, dog-walkers, and stroller-pushers. In the even of a collision, which situation is better for all parties involved? A biker hitting/being hit by a car, or a person on foot hitting/being hit by a biker? Additionally, it is far easier for a biker or a pedestrian to dodge each other and avoid the collision entirely, than it is for a driver or a biker to do so.</p>
<p>Apparently that logic is lost on many people, however, as I regularly am forced to yield to the moronic bikers riding in traffic, often when they choose to go around a parked vehicle. I also find myself stopping violently as someone chooses to walk out in front of me with the expectation that I not only saw them, but that I am also willing to stop for them. I might not mind it so much if those people would wave at me when I do stop, but people around here are obviously unfamiliar with the courtesy wave.</p>
<p>I fear the day when I stop caring for those morons, and instead “run them the **** over” without concern or remorse.</p>rthautMaybe it’s just me, but don’t most pedestrians seem like morons around motor vehicles? Perhaps their self-preservation instincts shut off when they are walking in and around traffic. It seems abundantly obvious that motor vehicles should always have the right of way, given that in the event of a collision, people on foot stand no chance against automobiles. I understand that there are many situations where, by law, car traffic must yield to foot traffic, but I am speaking in regards to the people who will cross a street without even looking to see if the surrounding vehicles are yielding to them.Twenty Twelve2012-01-17T06:26:53-07:002012-01-17T06:26:53-07:00https://ryanthaut.com/blog/2012/01/17/twenty-twelve<p>That just rolls off the tongue, doesn’t it? Not like 2011, which often came out as “twen’y ‘leven” if you were unwilling to take the time to say “two thousand eleven.” Say it one more time, now that you are thinking about your enunciation: 2012.</p>
<p>Despite that heart-warming moment we just shared, I am not writing a post solely on how easy it is to say 2012. I actually set out to write my first actual blog post, ever; it just so happens that this is also my first post of the year 2012, hence the title. It feels good to be writing something, but I am already feeling slightly overwhelmed. It’s not so much the act of writing; it’s actually just the idea that I need to organize my thoughts. Typically my thought process is chaotic at best, so I imagine my first few posts will seem at least slightly scatter-brained. I think most people’s thought process is that way, but they either don’t admit it, or they don’t realize it.</p>
<p>I am not here to write about my plans, hopes, dreams, or wishes for the coming year. It’s not that I don’t like thinking about the future; I simply don’t (think about the future). For instance, I despise the common interview question, “Where do you see yourself in 5 years?” Honestly, I would like to see myself successfully employed in an enjoyable career that is both challenging and rewarding. For some reason, though, interviewers don’t like that answer. They want to see if you are gunning for management, or if you intend to move on after a year or two, so that answer does not help them at all.</p>
<p>That seems to be everything I have to say on the subject of 2012, for now. I will leave you with a spoiler, though: I plan to write a post (as well as update my status on various social networks) on December 22, 2012, when we are all… still here.</p>rthautThat just rolls off the tongue, doesn’t it? Not like 2011, which often came out as “twen’y ‘leven” if you were unwilling to take the time to say “two thousand eleven.” Say it one more time, now that you are thinking about your enunciation: 2012.