<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Stuff by Nirav Blog</title>
        <link>https://bynirav.com/blog</link>
        <description>Stuff by Nirav Blog</description>
        <lastBuildDate>Sun, 25 May 2025 07:11:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Making miti.today]]></title>
            <link>https://bynirav.com/blog/miti.today</link>
            <guid>https://bynirav.com/blog/miti.today</guid>
            <pubDate>Sun, 25 May 2025 07:11:02 GMT</pubDate>
            <description><![CDATA[Website]]></description>
            <content:encoded><![CDATA[<div style="text-align:center"><img src="https://bynirav.com/assets/images/icon-26ce1fa612b8a551ce1acb1314e9bc7d.png" alt="miti.today" style="max-width:200px"></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="website">Website<a href="https://bynirav.com/blog/miti.today#website" class="hash-link" aria-label="Direct link to Website" title="Direct link to Website">​</a></h2>
<p>The <a href="https://miti.today/" target="_blank" rel="noopener noreferrer">miti.today</a> website is my attempt at making a minimal calendar that gets me the Nepali date
without any fluff or ambition.</p>
<p>My requirements for the website were simple:</p>
<ol>
<li>build it in a day</li>
<li>hosted for free</li>
<li>Loads fast</li>
</ol>
<p>So I came up with a system where I host a static website on Cloudflare Pages. And every 24 hours at 12AM Nepal time,
a cloudflare worker triggers the deployment again, updating the page.</p>
<!-- -->
<p>An invocation a day is well within the free tier, and something that even if I had to pay for, it would be in cents/day.</p>
<p>I use a table of months in each day to calculate what date today should be:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> daysInYears </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token spread operator" style="color:black">...</span><span class="token plain"> </span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">[</span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">32</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">32</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">29</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">29</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// 2080</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">[</span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">32</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">32</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">29</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">30</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">29</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">31</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// 2081</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token spread operator" style="color:black">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> startingTime </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">Date</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"2018-04-14T00:00:00+05:45"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getTime</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">/</span><span class="token plain"> </span><span class="token number" style="color:red">1000</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> daysSince </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">seconds </span><span class="token operator" style="color:black">-</span><span class="token plain"> startingTimestamp</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">/</span><span class="token plain"> </span><span class="token number" style="color:red">86400</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> year </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">month </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">day </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">firstDayOfMonth </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> _daySum </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> daysInYearsFlat </span><span class="token operator" style="color:black">=</span><span class="token plain"> daysInYears</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">flat</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword control-flow" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> i </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> i </span><span class="token operator" style="color:black">&lt;</span><span class="token plain"> daysInYearsFlat</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> i</span><span class="token operator" style="color:black">++</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    _daySum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> daysInYearsFlat</span><span class="token punctuation" style="color:black">[</span><span class="token plain">i</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">_daySum </span><span class="token operator" style="color:black">&gt;=</span><span class="token plain"> daysSince</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        _daySum </span><span class="token operator" style="color:black">-=</span><span class="token plain"> daysInYearsFlat</span><span class="token punctuation" style="color:black">[</span><span class="token plain">i</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// revert</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        year </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Math</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">floor</span><span class="token punctuation" style="color:black">(</span><span class="token plain">i </span><span class="token operator" style="color:black">/</span><span class="token plain"> </span><span class="token number" style="color:red">12</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token number" style="color:red">2075</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        month </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">i </span><span class="token operator" style="color:black">%</span><span class="token plain"> </span><span class="token number" style="color:red">12</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        day </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Math</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">floor</span><span class="token punctuation" style="color:black">(</span><span class="token plain">daysSince </span><span class="token operator" style="color:black">-</span><span class="token plain"> _daySum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        firstDayOfMonth </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">_daySum </span><span class="token operator" style="color:black">%</span><span class="token plain"> </span><span class="token number" style="color:red">7</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">-</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token keyword control-flow" style="font-style:italic;color:black">break</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The code is crude but works fine.</p>
<p>For a while I considered using the <a href="http://www.cc.kyoto-su.ac.jp/~yanom/pancanga/message314.html" target="_blank" rel="noopener noreferrer">pancanga</a> perl
script by Professors M. YANO and M FUSHIMI (<a href="https://www.cc.kyoto-su.ac.jp/~yanom/pancanga/" target="_blank" rel="noopener noreferrer">demo here</a>).
It is interesting and and something I hope to study in detail in future, but ultimately I felt it was too complex for my current use.</p>
<p>Once I have the date and the calendar, I generate the HTML "by hand".</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"> calendar</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">forEach</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">week</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    week</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">forEach</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">day</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> $day</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">day </span><span class="token operator" style="color:black">===</span><span class="token plain"> </span><span class="token string" style="color:red">"-"</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        $day </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token template-string string" style="color:red">&lt;div class='day'&gt;&lt;/div&gt;</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        $day </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token template-string string" style="color:red">&lt;div class='day</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token template-string interpolation">            dateArray</span><span class="token template-string interpolation punctuation" style="color:black">[</span><span class="token template-string interpolation number" style="color:red">2</span><span class="token template-string interpolation punctuation" style="color:black">]</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:black">===</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation function" style="font-weight:bold;color:black">parseInt</span><span class="token template-string interpolation punctuation" style="color:black">(</span><span class="token template-string interpolation">day</span><span class="token template-string interpolation punctuation" style="color:black">)</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:black">?</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:red">" toDay"</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:black">:</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:red">""</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token template-string interpolation">          </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string string" style="color:red">'&gt;</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation">day</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string string" style="color:red">&lt;/div&gt;</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      $calendar</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">append</span><span class="token punctuation" style="color:black">(</span><span class="token plain">$day</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> html </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">".calendar"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">prop</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"outerHTML"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> monthEnHtml </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token template-string string" style="color:red">&lt;div class="monthEn"&gt;</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token template-string interpolation">    monthsEn</span><span class="token template-string interpolation punctuation" style="color:black">[</span><span class="token template-string interpolation">dateArray</span><span class="token template-string interpolation punctuation" style="color:black">[</span><span class="token template-string interpolation number" style="color:red">1</span><span class="token template-string interpolation punctuation" style="color:black">]</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:black">-</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation number" style="color:red">1</span><span class="token template-string interpolation punctuation" style="color:black">]</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token template-string interpolation">  </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string string" style="color:red">&lt;/div&gt;</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>I'm using Cheerio to work with HTML easier. The generated HTML gets injected into a template using mustache.</p>
<p>It was important to me that the HTML generated be a single page,
with no extra HTTP requests once it reaches the browser. Thus:</p>
<ol>
<li>I embedded the font in the HTML (and makes up for more than 90% of the page weight)</li>
<li>The favicon is a SVG that has today's date in Nepali.</li>
<li>The CSS is inlined.</li>
<li>There is no JS.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="apps">Apps<a href="https://bynirav.com/blog/miti.today#apps" class="hash-link" aria-label="Direct link to Apps" title="Direct link to Apps">​</a></h2>
<p>The <a href="https://miti.today/" target="_blank" rel="noopener noreferrer">miti.today</a> website was useful. It is something I reference everyday.</p>
<p>But over time, I began to wonder if a widget would be more useful. I decided to write a simple widget
for iOS and see if it would be more useful. I used SwiftUI to make it, it was quite pleasant.</p>
<div class="row"><div class="col col--4"><img src="https://bynirav.com/assets/images/ios_app-5aa8c2fd3c23852fd360d90b8f52e3d1.png" alt="miti.today iOS app"></div><div class="col col--4"><img src="https://bynirav.com/assets/images/ios_widget-b64537652c44675853453562bce40135.png" alt="miti.today iOS widget"></div></div>
<p>It turned out to beuseful. Some of my friends asked for an Android version. So I used Compose
with Glance to make it. It wasn't as pleasant.</p>
<div class="row"><div class="col col--4"><img src="https://bynirav.com/assets/images/android_app-08420d149b3f99016fc7eda9171c4533.png" alt="miti.today Android app"></div><div class="col col--4"><img src="https://bynirav.com/assets/images/android_widget-2b63a2ab7c40bef625004444493c0d38.png" alt="miti.today Android widget"></div></div>
<p>The Android app is in internal testing in Play Store, and I'm waiting
for my Apple developer account to be approved. I'll update this page with links
after they are generally available.
The apps will be listed at <a href="https://app.miti.today/" target="_blank" rel="noopener noreferrer">app.miti.today</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Authentication Multiplexing]]></title>
            <link>https://bynirav.com/blog/auth_multiplexing/auth_multiplexing</link>
            <guid>https://bynirav.com/blog/auth_multiplexing/auth_multiplexing</guid>
            <pubDate>Sat, 24 May 2025 05:15:44 GMT</pubDate>
            <description><![CDATA[Haven't we all lived some form of the diagram below:]]></description>
            <content:encoded><![CDATA[<p>Haven't we all lived some form of the diagram below:</p>
<!-- -->
<p>Your real server is behind a reverse proxy. But all ingress traffic
comes through a different gated proxy not in your control that locks
everything behind it with a Basic Auth.</p>
<!-- -->
<p>This is quite a pickle. Because both the basic auth that Nginx is expecting
and the bearer token that our server is expecting uses the same
<code>Authentication</code> HTTP header.</p>
<p>Basic auth is cool because it is a simple way to password protect a system.
The browser itself handles asking the user for password, saving it in memory and
making sure all requests have the basic auth header. The HTML/JS code doesn't
even have to know if it's password protected.</p>
<p>But it's also inflexible and less secure. Just
<a href="https://stackoverflow.com/questions/233507/how-to-log-out-user-from-web-site-using-basic-authentication" target="_blank" rel="noopener noreferrer">logging out is a dance</a>.
Bearer token based authentication is flexible, can be made much more secure,
and allows for a much better user and developer experience.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="eating-the-pickle">Eating the Pickle<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#eating-the-pickle" class="hash-link" aria-label="Direct link to Eating the Pickle" title="Direct link to Eating the Pickle">​</a></h2>
<p>It would make sense that, for certain applications (for example in-house tools),
all incoming traffic is protected by default with a basic auth. But the more complex
application-specific authorization is handled with a proper JWT token.</p>
<p>In such cases,
we can get by with some JavaScript and Caddy gymnastics. And an extra header: <code>X-Custom-Authorization</code> (arbitrarily named).</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="caddy-configuration">Caddy Configuration<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#caddy-configuration" class="hash-link" aria-label="Direct link to Caddy Configuration" title="Direct link to Caddy Configuration">​</a></h2>
<p>Here Caddy is doing the fun things. It sets the value of the Authorization header to whatever is in
the X-Custom-Authorization header <strong>before</strong> any request goes to the upstream server.</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">example.com {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  reverse_proxy localhost:3000{</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    header_up Authorization {http.request.header.X-Custom-Authorization}</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  }</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">}</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-going-on-in-the-client-browser">What's going on in the client browser?<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#whats-going-on-in-the-client-browser" class="hash-link" aria-label="Direct link to What's going on in the client browser?" title="Direct link to What's going on in the client browser?">​</a></h2>
<p>We also need some code on the browser to make sure that:</p>
<ol>
<li>
<p>the <code>Authorization</code> header doesn't exist. If the browser notices
that we have manually set the <code>Authorization</code> header, it won't overwrite
it with the basic auth credentials. Since asking for, saving, and using the
basic auth is handled by the browser, we must allow browser to handle this auth.</p>
</li>
<li>
<p>before any request goes to the browser, it is intercepted and it's outgoing bearer
<code>Authorization</code> header is renamed to <code>X-Custom-Authorization</code>, leaving the <code>Authorization</code>
free for the browser to use.</p>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="axios-interceptor">Axios Interceptor<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#axios-interceptor" class="hash-link" aria-label="Direct link to Axios Interceptor" title="Direct link to Axios Interceptor">​</a></h3>
<p>If we had complete control of the client code, we'd just make sure all our requests went through
a middleware before passing through. For example, as an Axios interceptor:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">axios</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">use</span><span class="token punctuation" style="color:black">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">config</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    config</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"X-Custom-Authorization"</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> config</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"Authorization"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">delete</span><span class="token plain"> config</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"Authorization"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> config</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Promise</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">reject</span><span class="token punctuation" style="color:black">(</span><span class="token plain">error</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="pocketbase">Pocketbase<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#pocketbase" class="hash-link" aria-label="Direct link to Pocketbase" title="Direct link to Pocketbase">​</a></h3>
<p>Or as a PocketBase before send hook:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">pb</span><span class="token punctuation" style="color:black">.</span><span class="token method-variable function-variable method function property-access" style="font-weight:bold;color:black">beforeSend</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">url</span><span class="token parameter punctuation" style="color:black">,</span><span class="token parameter"> options</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">options</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"Authorization"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    options</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Object</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">assign</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">{</span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> options</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token string-property property">"X-Custom-Authorization"</span><span class="token operator" style="color:black">:</span><span class="token plain"> options</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"Authorization"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">delete</span><span class="token plain"> options</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:black">.</span><span class="token property-access maybe-class-name">Authorization</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> url</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> options </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="chrome-extension">Chrome Extension<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#chrome-extension" class="hash-link" aria-label="Direct link to Chrome Extension" title="Direct link to Chrome Extension">​</a></h3>
<p>However, we might not always have access to all parts of the client JS code. If
its for an internal tool, then a simple chrome extension might suffice:</p>
<!-- -->
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">background.js</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">manifest.json</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">chrome</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">webRequest</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">onBeforeSendHeaders</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">addListener</span><span class="token punctuation" style="color:black">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">details</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">details</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">frameType</span><span class="token plain"> </span><span class="token operator" style="color:black">===</span><span class="token plain"> </span><span class="token string" style="color:red">"outermost_frame"</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword control-flow" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">var</span><span class="token plain"> i </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> i </span><span class="token operator" style="color:black">&lt;</span><span class="token plain"> details</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">requestHeaders</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">length</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token operator" style="color:black">++</span><span class="token plain">i</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">details</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">requestHeaders</span><span class="token punctuation" style="color:black">[</span><span class="token plain">i</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:black">===</span><span class="token plain"> </span><span class="token string" style="color:red">"Authorization"</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          details</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">requestHeaders</span><span class="token punctuation" style="color:black">[</span><span class="token plain">i</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"X-Custom-Authorization"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token keyword control-flow" style="font-style:italic;color:black">break</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token literal-property property">requestHeaders</span><span class="token operator" style="color:black">:</span><span class="token plain"> details</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">requestHeaders</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token literal-property property">urls</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"&lt;all_urls&gt;"</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"blocking"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"requestHeaders"</span><span class="token punctuation" style="color:black">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"manifest_version"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"Outbound Header Modifier"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"1.0.0"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"permissions"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"webRequest"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"webRequestBlocking"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"https://example.com/*"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"background"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token property">"scripts"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"background.js"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token property">"persistent"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token boolean" style="color:red">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://bynirav.com/blog/auth_multiplexing/auth_multiplexing#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Whatever the method, what we're doing is making sure that the right layers in the stack see the appropriate information.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nepali Date on the Playdate]]></title>
            <link>https://bynirav.com/blog/nepali-date-on-play-date</link>
            <guid>https://bynirav.com/blog/nepali-date-on-play-date</guid>
            <pubDate>Sat, 24 May 2025 05:15:44 GMT</pubDate>
            <description><![CDATA[<img]]></description>
            <content:encoded><![CDATA[<img class="img-halfwidth" style="float:right;margin-left:10px;max-width:300px" src="https://bynirav.com/assets/images/desk-84d8dc3e7fd71895ea5d476afea51af2.jpg" alt="playdate on a 3d printed stand">
<p>I finally got the <a href="https://play.date/" target="_blank" rel="noopener noreferrer">Playdate</a>.
This little yellow machine is nice to look at and
quite fun to play with, but it doesn't yet have the kind of
games I like to play. No problem, I'm writing them myself.</p>
<p>Meanwhile, I have 3d printed a stand for it, and it sits on my desk
acting as a unique clock.</p>
<p>Now that I have a stand and a really cool memory LCD display which barely
needs power to display static images, I can display anything on it while it
sits on my desk.</p>
<!-- -->
<p>One of my pet peeves has been that computers and mobile phones
display date in AD, but daily life in Nepal needs me to know
the date in BS. And I can't just whip out my phone to check the
Nepali date without resorting to some external app or some ugly widget.
The external app (or website) is almost always riddled with ads, horoscopes,
religious messaging, and news. They load slow and the important information
is is buried in a maze of irrelevant information.</p>
<p>To remedy these minor annoyances, I have done two important things:</p>
<ol>
<li>
<p>I have established a website <a href="https://miti.today/" target="_blank" rel="noopener noreferrer">miti.today</a> for times when
I'm already using a browser and I just need to check the date really fast.
It just displays the Nepali date today in large font in the center of the page,
and barely anything else. I am also working on <a href="https://patro.today/" target="_blank" rel="noopener noreferrer">patro.today</a>
which will be an extremly simple calendar website.</p>
</li>
<li>
<p>I wrote a simple wallpaper utility for the Mac. It edits in the time and Nepali date
information into a selected wallpaper and changes it every minute. The code was a lot more
involved than I expected it to be, but I use it on my monitors has been useful.
<a href="https://github.com/niravcodes/clock_on_wallpaper_mac" target="_blank" rel="noopener noreferrer">niravcodes/clock_on_wallpaper_mac</a></p>
</li>
</ol>
<p>Now that I have the Playdate I'm free to add a third:</p>
<ul>
<li>Write software for the Playdate that takes as little power as possible while it
displays the current time, date, and a wallpaper of my selection.</li>
</ul>
<p>So I went ahead and wrote it.</p>
<img class="img-75" src="https://bynirav.com/assets/images/bg-a451a0c2aebdc3779ec0f129a8c65fec.JPG" alt="playdate on a 3d printed stand">
<p>The really awesome robot wallpaper I'm using is titled
<a href="https://www.artstation.com/artwork/xD4EY1" target="_blank" rel="noopener noreferrer">The Nerd Desk</a> by
<a href="https://www.instagram.com/vaz.cg" target="_blank" rel="noopener noreferrer">Marcelo Vaz</a>.</p>]]></content:encoded>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[Animating seven-segment displays with a web tool]]></title>
            <link>https://bynirav.com/blog/seven-segment-animation</link>
            <guid>https://bynirav.com/blog/seven-segment-animation</guid>
            <pubDate>Sat, 24 May 2025 05:15:44 GMT</pubDate>
            <description><![CDATA[Seven Segment animator]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Seven Segment animator" src="https://bynirav.com/assets/images/sevenseg-028149c52d3b0ab5e3f9f1d195ef8acd.png" width="1460" height="450" class="img_ev3q"></p>
<img class="img-halfwidth" style="float:right;margin-left:10px" src="https://bynirav.com/assets/images/output-36578c3f7dba5b5446f2deb813e0013d.jpg" alt="the real thing">
<p>So a friend was building a device which had an array of 6 seven-segment-displays.
We were thinking about some cool idle and loading animations we might be able to program into it.</p>
<p>I didn't ask for the specifics but it was clear that the display unit had an arrangement
of one shift register (probably a 74HC595) per digit. The 74HC595 is a nice little chip
that can be fed one byte serially, and it outputs that byte in parallel. It also latches onto that
byte for however long we ask it to, and it can be daisy-chained. So it is a cheap way to
drive a huge amount of LED lights with a few micro-controller pins.</p>
<!-- -->
<!-- -->
<p>He was hand-writing the bytes. Each 1 on the byte turns on some LED, and each 0 turns it off
(<code>0b01001111</code> or <code>0x4f</code> to display the digit '3'). I realized I could quickly hack
together some tool to make it easier and more fun to animate.</p>
<p>It took me about an hour to write the tool but I polished it up a little for this article.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="one-seven-segment-display">One Seven Segment display<a href="https://bynirav.com/blog/seven-segment-animation#one-seven-segment-display" class="hash-link" aria-label="Direct link to One Seven Segment display" title="Direct link to One Seven Segment display">​</a></h2>
<p>First I need to display and manipulate a single digit.</p>
<hr>
<!-- -->
<div style="background:#eeeeef;padding:0 0 0 10px"><div>Try clicking on the segments to toggle them.</div><div style="height:210px;background:#eeeeef"><div id="segment-byte-container" style="font-weight:bold;margin-left:36px"></div><div id="segment-container" style="margin-top:5px"></div></div></div>
<script>{const e="red",t="black",s=["h","g","f","e","d","c","b","a"],n={a:1,b:1,c:1,d:0,e:0,f:0,g:0,h:0},o=e=>document.getElementById(e);class r{constructor(e){this.root=o(e),this.model={...n},this.render()}render(){const s=document.createElement("div");s.className="sevenseg",Object.entries(this.model).forEach((([n,o])=>{const r=document.createElement("div");r.style.backgroundColor=o?e:t,r.className="seg seg-"+n,r.onclick=(()=>{this.model[n]=!this.model[n],this.render()}).bind(this),s.appendChild(r)})),this.root.innerHTML="",this.root.appendChild(s),o("segment-byte-container").textContent=this.serialize()}serialize(){let e="";for(const t of s)if(this.model.hasOwnProperty(t)){e+=this.model[t]?"1":"0"}else e+="0";return"0x"+parseInt(e,2).toString(16).padStart(2,"0")}}new r("segment-container")}</script>
<style>.sevenseg { width: 80px; position: relative; transform: skew(-7deg); margin-left: 20px; } .segGroup { width: 120px; height: 190px; } .seg { position: absolute; } .sevenseg > .seg-a { top: 0px; left: 0px; height: 15px; width: 70px; } .sevenseg > .seg-b { top: 0px; right: 0px; height: 70px; width: 15px; } .sevenseg > .seg-c { top: 70px; right: 0px; height: 70px; width: 15px; } .sevenseg > .seg-d { top: 140px; right: 0px; width: 70px; height: 15px; } .sevenseg > .seg-e { top: 70px; left: 0px; height: 70px; width: 15px; } .sevenseg > .seg-f { top: 0px; left: 0px; height: 70px; width: 15px; } .sevenseg > .seg-g { top: 70px; right: 0px; width: 70px; height: 15px; } .sevenseg > .seg-h { top: 140px; left: 90px; height: 15px; width: 15px; }</style>
<hr>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-model">The Model<a href="https://bynirav.com/blog/seven-segment-animation#the-model" class="hash-link" aria-label="Direct link to The Model" title="Direct link to The Model">​</a></h3>
<p>These kinds of systems are best described by some form of
<a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter" target="_blank" rel="noopener noreferrer">Model-View-Presenter</a>
separation.</p>
<p>Which is just a fancy way of saying: keep the representation of the LED matrix separate from
the visualization of it.</p>
<p>If we assume the display to be labelled like below:</p>
<img src="https://bynirav.com/assets/images/sevenlabel-9431af581166a04a6bfdc1a8686a1ce3.png" style="height:200px">
<p>It can be described with a single object:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> model </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token literal-property property">a</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">b</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">c</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">d</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">e</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">f</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">g</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">h</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This model can theoretically represent all the states of the digit display. For example, to display one, this model would be:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token literal-property property">a</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">b</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">c</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">d</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">e</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">f</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">g</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">h</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="rendering">Rendering<a href="https://bynirav.com/blog/seven-segment-animation#rendering" class="hash-link" aria-label="Direct link to Rendering" title="Direct link to Rendering">​</a></h3>
<p>Now we need to find some way to display this model visually. It could have been a picture or a canvas.
For this project, it is a bunch of <code>&lt;div&gt;</code> elements positioned with some CSS:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">model</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> container </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  container</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"sevenseg"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Object</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">entries</span><span class="token punctuation" style="color:black">(</span><span class="token plain">model</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">forEach</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token parameter punctuation" style="color:black">[</span><span class="token parameter">key</span><span class="token parameter punctuation" style="color:black">,</span><span class="token parameter"> value</span><span class="token parameter punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> el </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">style</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">backgroundColor</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> value </span><span class="token operator" style="color:black">?</span><span class="token plain"> </span><span class="token constant">ON_COLOR</span><span class="token plain"> </span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token constant">OFF_COLOR</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"seg seg-"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> key</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    container</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">el</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> container</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>render</code> method simply takes <em>any</em> model object and faithfully generates
a visual representation of it. Notice that it is a pure function. It has no
side effects. It doesn't affect the program in any way other than taking an
model as an input, doing some processing on it, and returning an output.</p>
<p>This separation is an incredible thing. We have cleverly avoided all kinds of complications
by having a pure <code>render</code> function that just renders whatever the system state is describing.</p>
<p>Now, changing the system model is a simple matter of changing the model and calling the <code>render</code> function
again.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">model</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> container </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  container</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"sevenseg"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Object</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">entries</span><span class="token punctuation" style="color:black">(</span><span class="token plain">model</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">forEach</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token parameter punctuation" style="color:black">[</span><span class="token parameter">key</span><span class="token parameter punctuation" style="color:black">,</span><span class="token parameter"> value</span><span class="token parameter punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> el </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">style</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">backgroundColor</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> value </span><span class="token operator" style="color:black">?</span><span class="token plain"> </span><span class="token constant">ON_COLOR</span><span class="token plain"> </span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token constant">OFF_COLOR</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"seg seg-"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> key</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    el</span><span class="token punctuation" style="color:black">.</span><span class="token method-variable function-variable method function property-access" style="font-weight:bold;color:black">onclick</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">present</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token spread operator" style="color:black">...</span><span class="token plain">model</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token operator" style="color:black">!</span><span class="token plain">model</span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    container</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">el</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> container</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">present</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">model</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">innerHTML</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> view </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token plain">model</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">view</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Note that we have added an <code>el.onclick</code> function to each of the segment elements.
Each time a segment is clicked on, it toggles its associated key in the model, and
calls render again (via the <code>present</code> function). The <code>present</code> function
simply makes sure that each rendering overwrites the last one.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="serialization">Serialization<a href="https://bynirav.com/blog/seven-segment-animation#serialization" class="hash-link" aria-label="Direct link to Serialization" title="Direct link to Serialization">​</a></h3>
<p>Serialization here means just converting the digit as it is being viewed into the
final byte representation that will be programmed into the display firmware.</p>
<p>The really cool thing about the Model-View separation is that one model can have
multiple views. Conceptually, a serialized byte representation of the system model
can also be considered a view. So it can be "rendered" as before, but onto a different "medium".</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">KEY_ORDER</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"h"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"g"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"f"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"e"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"d"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"c"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"b"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"a"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">serialize</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">model</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> binaryString </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> key </span><span class="token keyword" style="font-style:italic;color:black">of</span><span class="token plain"> </span><span class="token constant">KEY_ORDER</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">model</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">hasOwnProperty</span><span class="token punctuation" style="color:black">(</span><span class="token plain">key</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> binaryValue </span><span class="token operator" style="color:black">=</span><span class="token plain"> model</span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token operator" style="color:black">?</span><span class="token plain"> </span><span class="token string" style="color:red">"1"</span><span class="token plain"> </span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      binaryString </span><span class="token operator" style="color:black">+=</span><span class="token plain"> binaryValue</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      binaryString </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// Convert binary string to hexadecimal</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> hexString </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">parseInt</span><span class="token punctuation" style="color:black">(</span><span class="token plain">binaryString</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">toString</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">16</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">padStart</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> </span><span class="token string" style="color:red">"0x"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> hexString</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>KEY_ORDER</code> constant is introduced because what binary bits map onto what LEDs is
hardware dependent.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="multiple-displays">Multiple displays<a href="https://bynirav.com/blog/seven-segment-animation#multiple-displays" class="hash-link" aria-label="Direct link to Multiple displays" title="Direct link to Multiple displays">​</a></h2>
<p>An easy way to support multiple displays is to compartmentalize all the data
pertaining to a single display inside a class.</p>
<div class="tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">js</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">css</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">ON_COLOR</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"red"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">OFF_COLOR</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"black"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">KEY_ORDER</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"h"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"g"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"f"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"e"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"d"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"c"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"b"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"a"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">EMPTY</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token literal-property property">a</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">b</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">c</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">d</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">e</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">f</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">g</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token literal-property property">h</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">class</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">SevenSeg</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">constructor</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">root</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">root</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token plain">root</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token spread operator" style="color:black">...</span><span class="token constant">EMPTY</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> container </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    container</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"sevenseg"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token known-class-name class-name" style="font-weight:bold;color:black">Object</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">entries</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">forEach</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token parameter punctuation" style="color:black">[</span><span class="token parameter">key</span><span class="token parameter punctuation" style="color:black">,</span><span class="token parameter"> value</span><span class="token parameter punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> el </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">style</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">backgroundColor</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> value </span><span class="token operator" style="color:black">?</span><span class="token plain"> </span><span class="token constant">ON_COLOR</span><span class="token plain"> </span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token constant">OFF_COLOR</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"seg seg-"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> key</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      el</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">onclick</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token operator" style="color:black">!</span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">render</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">bind</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      container</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">el</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">root</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">innerHTML</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">root</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">container</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">serialize</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> binaryString </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> key </span><span class="token keyword" style="font-style:italic;color:black">of</span><span class="token plain"> </span><span class="token constant">KEY_ORDER</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">hasOwnProperty</span><span class="token punctuation" style="color:black">(</span><span class="token plain">key</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> binaryValue </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">this</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">model</span><span class="token punctuation" style="color:black">[</span><span class="token plain">key</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token operator" style="color:black">?</span><span class="token plain"> </span><span class="token string" style="color:red">"1"</span><span class="token plain"> </span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        binaryString </span><span class="token operator" style="color:black">+=</span><span class="token plain"> binaryValue</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        binaryString </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token comment" style="font-style:italic;color:red">// Convert binary string to hexadecimal</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> hexString </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">parseInt</span><span class="token punctuation" style="color:black">(</span><span class="token plain">binaryString</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">toString</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">16</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">padStart</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token string" style="color:red">"0"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">return</span><span class="token plain"> </span><span class="token string" style="color:red">"0x"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> hexString</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token selector class">.container</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">display</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> flex</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">80</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">position</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> relative</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">transform</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">skew</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">-7</span><span class="token unit">deg</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">margin-left</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">20</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.segGroup</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">120</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">190</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.seg</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">position</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> absolute</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-a</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">left</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-b</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">right</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-c</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">right</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-d</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">140</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">right</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-e</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">left</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-f</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">left</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-g</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">right</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">70</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token selector class">.sevenseg</span><span class="token selector"> </span><span class="token selector combinator">&gt;</span><span class="token selector"> </span><span class="token selector class">.seg-h</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"> </span><span class="token property">top</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">140</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">left</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">90</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">height</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token property">width</span><span class="token punctuation" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">15</span><span class="token unit">px</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></div>
<p>Now we can just create a <code>new SevenSeg()</code> per display.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token constant">NUM_DISPLAYS</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">6</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token function-variable function" style="font-weight:bold;color:black">$</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">x</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getElementById</span><span class="token punctuation" style="color:black">(</span><span class="token plain">x</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> frames </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">createNewSegmentGroup</span><span class="token punctuation" style="color:black">(</span><span class="token parameter">frameIdentifier</span><span class="token parameter punctuation" style="color:black">,</span><span class="token parameter"> frame </span><span class="token parameter operator" style="color:black">=</span><span class="token parameter"> </span><span class="token parameter punctuation" style="color:black">[</span><span class="token parameter punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> div </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  div</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token template-string string" style="color:red">container</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation">frameIdentifier</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  div</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"container"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"container"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">div</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> display </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> j </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> j </span><span class="token operator" style="color:black">&lt;=</span><span class="token plain"> </span><span class="token constant">NUM_DISPLAYS</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> j</span><span class="token operator" style="color:black">++</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> segContainer </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">createElement</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"div"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    segContainer</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token template-string string" style="color:red">c</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation">frameIdentifier</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string string" style="color:red">a</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">${</span><span class="token template-string interpolation">j</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:black">}</span><span class="token template-string template-punctuation string" style="color:red">`</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    segContainer</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">className</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"segGroup"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    div</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">appendChild</span><span class="token punctuation" style="color:black">(</span><span class="token plain">segContainer</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">let</span><span class="token plain"> seg </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">SevenSeg</span><span class="token punctuation" style="color:black">(</span><span class="token plain">segContainer</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:black">[</span><span class="token plain">j </span><span class="token operator" style="color:black">-</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> </span><span class="token operator" style="color:black">!==</span><span class="token plain"> </span><span class="token keyword nil" style="font-style:italic;color:black">undefined</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> seg</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">deserialize</span><span class="token punctuation" style="color:black">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:black">[</span><span class="token plain">j </span><span class="token operator" style="color:black">-</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    display</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">push</span><span class="token punctuation" style="color:black">(</span><span class="token plain">seg</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  frames</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">push</span><span class="token punctuation" style="color:black">(</span><span class="token plain">display</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<div style="padding-top:10px;padding-left:10px;background:#eeeeef"><div id="display-byte-container" style="font-weight:bold;margin-left:10px"></div><br><div id="display-container" style="margin-top:0;transform:scale(0.5);transform-origin:top left;height:390px"></div></div>
<script>{const e="red",t="black",n=["h","g","f","e","d","c","b","a"],o={a:0,b:0,c:0,d:0,e:0,f:0,g:0,h:1},s=e=>document.getElementById(e);class r{constructor(e){this.root=s(e),this.model={...o},this.render()}render(){const n=document.createElement("div");n.className="sevenseg",Object.entries(this.model).forEach((([o,s])=>{const r=document.createElement("div");r.style.backgroundColor=s?e:t,r.className="seg seg-"+o,r.onclick=(()=>{this.model[o]=!this.model[o],this.render(),this.onclick()}).bind(this),n.appendChild(r)})),this.root.innerHTML="",this.root.appendChild(n)}serialize(){let e="";for(const t of n)if(this.model.hasOwnProperty(t)){e+=this.model[t]?"1":"0"}else e+="0";return"0x"+parseInt(e,2).toString(16).padStart(2,"0")}onclick(){}}const i=6;let c=[];function createNewSegmentGroup(e,t=[]){const n=document.createElement("div");n.id="container"+e,n.className="display-container",s("display-container").appendChild(n);let o=[];for(let c=1;c<=i;c++){const i=document.createElement("div");i.id="c"+e+"a"+c,i.className="segGroup",n.appendChild(i);let l=new r(i.id);l.onclick=()=>{const e=a();s("display-byte-container").textContent=e},void 0!==t[c-1]&&l.deserialize(t[c-1]),o.push(l)}c.push(o)}const a=()=>{let e="";return c.forEach((t=>{let n="";t.forEach((e=>{n+=e.serialize()+","})),e+="["+n.substring(0,n.length-1)+"],"})),e="["+e.substring(0,e.length-1)+"]",e};let l=0;function newframe(){createNewSegmentGroup(++l)}newframe(),newframe(),newframe(),newframe();const d=a();s("display-byte-container").textContent=d}</script>
<style>.display-container{display:flex} .sevenseg { width: 80px; position: relative; transform: skew(-7deg); margin-left: 20px; } .segGroup { width: 120px; height: 190px; } .seg { position: absolute; } .sevenseg > .seg-a { top: 0px; left: 0px; height: 15px; width: 70px; } .sevenseg > .seg-b { top: 0px; right: 0px; height: 70px; width: 15px; } .sevenseg > .seg-c { top: 70px; right: 0px; height: 70px; width: 15px; } .sevenseg > .seg-d { top: 140px; right: 0px; width: 70px; height: 15px; } .sevenseg > .seg-e { top: 70px; left: 0px; height: 70px; width: 15px; } .sevenseg > .seg-f { top: 0px; left: 0px; height: 70px; width: 15px; } .sevenseg > .seg-g { top: 70px; right: 0px; width: 70px; height: 15px; } .sevenseg > .seg-h { top: 140px; left: 90px; height: 15px; width: 15px; }</style>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-not-react">Why not React?<a href="https://bynirav.com/blog/seven-segment-animation#why-not-react" class="hash-link" aria-label="Direct link to Why not React?" title="Direct link to Why not React?">​</a></h2>
<p>For simple and quick-use application like this, the abstractions of React feel
clunky and unnecessary. Remember that React came into the scene to make complex web-apps
simpler to manage. It didn't invent interactive web pages. And in any case, without
an intuitive grasp of the system model, React wouldn't have been much help.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[nightless]]></title>
            <link>https://bynirav.com/blog/nightless</link>
            <guid>https://bynirav.com/blog/nightless</guid>
            <pubDate>Thu, 13 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[sleep tight good night is when the world stops and the universe is a box of cyan walls inside which you will find me with fever intense and endless and with my body hollow and transparent and just a little candlelight for heart which is hard to see, actually, for all these incandescent bulbs unnatural and nauseating but necessary, indispensable actually, these lights that burn my soul with their uncaring intensity they bind me they destroy me.]]></description>
            <content:encoded><![CDATA[<p>sleep tight good night is when the world stops and the universe is a box of cyan walls inside which you will find me with fever intense and endless and with my body hollow and transparent and just a little candlelight for heart which is hard to see, actually, for all these incandescent bulbs unnatural and nauseating but necessary, indispensable actually, these lights that burn my soul with their uncaring intensity they bind me they destroy me.</p>
<!-- -->
<p>CLICK and even the cyanbox universe stops and the silence starts; silence of the eyes and the shadows looming and the shadows looming and the shadows moving about in the absolute darkness; these shadows, like rainclouds, like whispered questions, shadows of an old friend; these shadows like a tree in the forest and the forest unwhispering unmoving planted firmly in the ancient and everlasting night.</p>
<p>this ancient night that I have inherited and that I have suffered like a fever all this time, is all I have yet I keep it at bay with the overbright incandescent lights.</p>
<p>can't sleep won't sleep<br>
nirav unsleeping in this non-night</p>
<p>In the dark will it start?<br>
the slow death the red dream<br>
just the soul; nowhere;<br>
content and wandering<br>
in the dark forest of the night<br></p>
<p>or will it start the thoughtengine sputtering and smokevomiting the ugly mechanical and noisy discordant rising from the gutter truly an abomination this thoughtengine; spewing and oozing from rusted pipes leaking and smelly too and it just comes to be in the ancient night the ancestral night,</p>
<p>pristine, with fireflies decorated,<br>
pure, like the sound of a stream,<br>
the silent nightforest where&nbsp;<br>
my soul would be content if not for the<br></p>
<p>unwieldy and ginormous, infested with flies this thoughtengine thoughtmuttering thoughtsputtering thick acidlike illwords strung in illsentences and singing them cacophonic in the language of sorrows and fears; making sin of the sacred; lustful eyes froglegs the thoughtengine looks at my soul and corrupts my being.</p>]]></content:encoded>
            <category>writing</category>
        </item>
        <item>
            <title><![CDATA[The TMS website sucks so I made a captcha autofiller]]></title>
            <link>https://bynirav.com/blog/tms-captcha</link>
            <guid>https://bynirav.com/blog/tms-captcha</guid>
            <pubDate>Sat, 22 May 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[In keeping with the spirit of the times, I've started playing in the Nepali]]></description>
            <content:encoded><![CDATA[<p>In keeping with the spirit of the times, I've started playing in the Nepali
Stock Exchange playground. It is a strange, distorted world for someone like me
who's used to the determinism of the computer realm. And so far, it has just
proved to be a more fashionable way of losing money. But it's addictive!</p>
<p>If you've ever had to use Nepal Stock Exchange's Trade Management System (often
called just TMS), you probably hate it. It is at best an
incompetently made software with many glaring issues, hosted over a woefully
underpowered infrastructure that cannot even handle the most predictable of
traffic spikes. On more than one occasion I've oversold or undersold shares
because it's UI was out of sync with it's database.</p>
<!-- -->
<p>The TMS's login captcha is the epitome of this incompetence and negligence.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/captcha-36bdab8d474fb834047b72937a507b72.png" width="581" height="505" class="img_ev3q"></p>
<p>If you didn't know, a captcha is supposed to be a challenge that only humans can
solve in a reasonable time. A malicious computer program which, if unopposed,
could execute hundreds of thousands of requests every second testing various
username<!-- -->:password<!-- --> combos or security vulnerabilities, or just plain overloading
the system so that it becomes unresponsive to legitimate users, is blocked by
the captcha.</p>
<p>With that definition, however, the TMS's "captcha" actually turns out to be an
<em>anti-captcha</em>, the exact opposite. It appears as a challenge to the user, who
has to manually type it out every time. <strong>But it is completely transparent to
any half-decent computer script</strong>. In fact, when you hit the login button, the
captcha is not even sent to the server. It's a purely cosmetic effect. It's like
a gate that you have to painstakingly unlock every time, but every burglar can
pass through it as if it wasn't even there.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/captchagate-eb5b9fe07ab4c2b0136612c6ebed09d5.png" width="392" height="381" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-tms-captcha-implementation">The TMS captcha implementation<a href="https://bynirav.com/blog/tms-captcha#the-tms-captcha-implementation" class="hash-link" aria-label="Direct link to The TMS captcha implementation" title="Direct link to The TMS captcha implementation">​</a></h2>
<p>Even a cursory inspection will show that the implementation of the TMS captcha
system is not an actual captcha. Any OCR like Google Lens can read it readily,
making it very cheap to overcome.</p>
<p>But you don't have to go that far. The captcha's random text is generated in the
browser by a simple JavaScript code, and it's laid over an static image. The css
<code>user-select</code> property is set to <code>none</code> so you can't just copy the text from
over the image and paste it in the captcha field.</p>
<p>Which means it should be accessible via the DOM:</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/captcha2-1435894b5df1c89ac416f26c2299745a.png" width="629" height="593" class="img_ev3q"></p>
<p>Unsurprisingly, it is.</p>
<p>Now, if you can read the text from the DOM, it's not a big deal to write it back
to DOM:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getElementById</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"captchaEnter"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getElementById</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"randomfield"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This piece of code will autofill the captcha input.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-problem-arises">A problem arises<a href="https://bynirav.com/blog/tms-captcha#a-problem-arises" class="hash-link" aria-label="Direct link to A problem arises" title="Direct link to A problem arises">​</a></h3>
<p>An interesting problem that emerges is that when you autofill the captcha input
via JavaScript then and hit Login, the website still says "Incorrect Captcha"
even when the captcha is actually correct.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/captcha3-bd193918b57a8f13022b64fd2672c933.png" width="629" height="654" class="img_ev3q"></p>
<p>But how could that be? Could the TMS's system be more well thought out than I
expected?</p>
<p>You wish! Turns out, they're using a frontend framework (Angular.js). Angular.js
internally maintains a state, with the values of all inputs. That state gets
altered only when the corresponding input's <code>input</code> event is fired. Otherwise
the value change is not registered. But that's easy to fire. Here:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token function-variable function" style="font-weight:bold;color:black">$</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">_</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getElementById</span><span class="token punctuation" style="color:black">(</span><span class="token plain">_</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"captchaEnter"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"randomfield"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"captchaEnter"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">dispatchEvent</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">Event</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"input"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// Fire the event to trigger angular state change</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And with that, the captcha auto-filler works.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="making-a-chrome-extension">Making a chrome extension<a href="https://bynirav.com/blog/tms-captcha#making-a-chrome-extension" class="hash-link" aria-label="Direct link to Making a chrome extension" title="Direct link to Making a chrome extension">​</a></h3>
<p>Now that I've come this far, I might as well make a chrome extension. so that I
don't have to deal with this again. Chrome extensions are pretty easy to make.
It takes like 10 minutes to make something this simple. Here's the relevant part
of the code:</p>
<ol>
<li>manifest.json</li>
</ol>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"TMS Captcha Autofiller"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"description"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"This extention will autofill TMS captchas. Made by nirav.com.np"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token string" style="color:red">"0.5"</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"manifest_version"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token number" style="color:red">3</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token property">"content_scripts"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token property">"matches"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"https://*.nepsetms.com.np/login"</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token property">"js"</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token punctuation" style="color:black">[</span><span class="token string" style="color:red">"contentScript.js"</span><span class="token punctuation" style="color:black">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ol start="2">
<li>contentScript.js</li>
</ol>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> </span><span class="token function-variable function" style="font-weight:bold;color:black">$</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token parameter">_</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:black">=&gt;</span><span class="token plain"> </span><span class="token dom variable" style="font-weight:bold;color:black">document</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">getElementById</span><span class="token punctuation" style="color:black">(</span><span class="token plain">_</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">//aliasing a long fn call</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">function</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">l</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"captchaEnter"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"randomfield"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">value</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">$</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"captchaEnter"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">.</span><span class="token method function property-access" style="font-weight:bold;color:black">dispatchEvent</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">Event</span><span class="token punctuation" style="color:black">(</span><span class="token string" style="color:red">"input"</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// Fire the event to trigger angular state change</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token dom variable" style="font-weight:bold;color:black">window</span><span class="token punctuation" style="color:black">.</span><span class="token property-access">onload</span><span class="token plain"> </span><span class="token operator" style="color:black">=</span><span class="token plain"> l</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Done. Put these two files in a folder and import it from the chrome extension
page (<code>chrome://extensions</code>).</p>
<p>A slightly more decorated version is published in my Github:
<a href="https://github.com/niravcodes/TMSCaptchaAutoFiller" target="_blank" rel="noopener noreferrer">github.com/niravcodes/TMSCaptchaAutoFiller</a>.</p>
<p>You can go there and install that version instead.</p>
<p><strong>Update:</strong> The extension is now available in
<a href="https://chrome.google.com/webstore/detail/tms-captcha-autofiller/bbnmlbcjjojlcigkphmancneeplopmhg" target="_blank" rel="noopener noreferrer">Google Extension store</a>.
So you can download the app from official Google channel.
<a href="https://chrome.google.com/webstore/detail/tms-captcha-autofiller/bbnmlbcjjojlcigkphmancneeplopmhg" target="_blank" rel="noopener noreferrer">Download Here</a></p>
<p><strong>Request to the TMS devs</strong></p>
<p>Please change the font in the captcha field from sans serif to a serif one if
that's the least you do. Thousands of people needlessly confuse <code>capital i</code> and
<code>small L</code> everyday.</p>
<p><img decoding="async" loading="lazy" src="https://nirav.com.np/assets/img/serifsans.png" alt="" class="img_ev3q"></p>
<h1>Update</h1>
<p>The websites have been fixed and the captcha font has been changed to a legible
one. Thanks devs.</p>]]></content:encoded>
            <category>coding</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[An Octopus and a Game Engine]]></title>
            <link>https://bynirav.com/blog/octopus-game-and-engine</link>
            <guid>https://bynirav.com/blog/octopus-game-and-engine</guid>
            <pubDate>Mon, 14 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[I started making this thing as a one-day experiment: a fun little browser-game I]]></description>
            <content:encoded><![CDATA[<p>I started making this thing as a one-day experiment: a fun little browser-game I
could craft before committing to the everlooming neverending self-judo
one-man-deathwrestle called exams. But it instead ended up spreading out sparse
as intense hour-long coding sessions throughout the Quarantine months.</p>
<!-- -->
<p>This is how it turned out finally:</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/zVu_AQDCDgY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<p>To play this game in your browser,
<a href="https://niravcodes.github.io/Octopus-Game-JS" target="_blank" rel="noopener noreferrer">click here</a>.</p>
<p>Before starting, the question was how I would simulate the motion of an octopus
in the ocean. So I started with a prototype in javascript. After some trial and
error, and some primitive physics, I had the rough behavior of the octopus down.</p>
<p><img decoding="async" loading="lazy" alt="GIF of initial game prototype" src="https://bynirav.com/assets/images/initOctoGif-0dc5e867f6c7c0e36365a1b468160912.gif" width="500" height="500" class="img_ev3q"></p>
<p>It worked as I'd envisioned but looked rather drab. So I found a placeholder
animation on Dribbble by
<a href="https://dribbble.com/shots/3492217-Octopus-gif-animation" target="_blank" rel="noopener noreferrer">Narubalie</a> and put it
in. At this stage I had to write an animation-player for the game, because HTML5
canvas can't directly play a gif.</p>
<video autoplay="" muted="" loop="" class="img-halfwidth"><source src="/assets/medias/octo2-e84e7ca9a11c8f05d46ee44752b0661a.mp4" type="video/mp4"></video>
<p>Next I wrote an AABB collision detection system (meaning non-rotating
rectangular bounding boxes can now detect when they overlap). So now I could
finally make a little island for the octopus to land on.</p>
<video autoplay="" loop="" muted="" class="img-halfwidth"><source src="/assets/medias/octo0-35c6452c800e58c8bc44de5a70d7eaf5.mp4" type="video/mp4"></video>
<p>Next up is obviously an angry enemy angler fish. I found a cool animation on
Tumblr made by <a href="https://blabberf.whalecakes.com/" target="_blank" rel="noopener noreferrer">Blabberf</a>, and coded it's
motion.</p>
<video autoplay="" loop="" muted="" class="img-halfwidth"><source src="/assets/medias/octo3-9913c550be8a2dedf44c113bd0383062.mp4" type="video/mp4"></video>
<p>Now I wanted the octopus to be able to explore the ocean outside of the
rectangular box it's confined in. So I wrote a camera system that will follow
the octopus wherever it goes. I was also experimenting with different speeds at
this time so it might seem jumpy in the video.</p>
<video controls="" muted=""><source src="/assets/medias/octocamera-2916d1677eadc2cef48e91f5fa144eaa.mp4" type="video/mp4"></video>
<p>Then I wrote the level management system and made new components (text, static
image, etc) to build the UI of the game with. I found a nice octopus icon made
by <a href="http://www.freepik.com/" target="_blank" rel="noopener noreferrer">FreePik</a> from
<a href="https://www.flaticon.com/" target="_blank" rel="noopener noreferrer">flaticon.com</a> for the title screen.</p>
<p><img decoding="async" loading="lazy" alt="Picture of Octupus Game UI" src="https://bynirav.com/assets/images/ui-97a4a275ab3cb706d5307ca2f28419a9.jpg" width="1193" height="727" class="img_ev3q"></p>
<p>At some point, I realized that I could decouple the game code from the game
engine code, so I did. Then, just for kicks, I made a
<a href="https://nirav.com.np/2020/06/09/flappy-millennial-an-html5-canvas-game.html" target="_blank" rel="noopener noreferrer">Flappy Bird clone</a>
using only the Engine code, which was rather fun.</p>
<p>Now I wanted to animate my own main character instead of using some random image
on the internet. So I studied a lot of videos on octopus motion, and got to work
on Piskel app, which is a nice browser-based pixel art software. After laboring
over the motion for days, this is what I came up with:</p>
<img src="https://bynirav.com/assets/images/octoAnimOne-a1662cae449e41d0a4056a3b740f2201.gif" alt="octopus swimming" class="img-30p img-spaceTop">
<p>You'll notice that this octopus is far more exaggerated in motion than the
previous one, which is intentional, and I'm rather proud of this.</p>
<p>Next, I made the animation of the octopus crawling on the floor.</p>
<img src="data:image/gif;base64,R0lGODlhyADIAPAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgAAACwAAAAAyADIAAAC/4yPqcvtD6OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5LL5jE6r1+y2+w2Py+f0uv2Oz+v3/L7/DxgoOEhYaHiImKi4yNjo+AgZKTlJWWl5iZmpucnZ6fkJGio6Slpqeoqaqro6A+D6ChsrO0tbG6tpm6u7C4vL+wvcmxlM/OtbjFwLaVxjG8hM4wwI3ao8zWsj/Ucto5136+TtBt4k3kbOZM6GvqS+xq7kXgaPRR9mb4X/pU/F3+UvBeAWgVAI9hN2DyEYg1MYBlS4D6IXh1EoFpT4D+MVi/9ZOBLxuFFjRZFkQAoxWQUlEJUNST5hGfLVQZlxYOKwmdJlEpwzXfUEIIenDqHldBal+c5oOqURkeZjOhHqTqlciN609oLbCas35KHQaoJrNqwuwJYQ24xsC7Mk0EZTy4LtCLdlIXrtwE7uhLvh7MINkRcbB75HfSIgrCHwLrx/HzoNgDiDYl2MaXX0azksZsqDG48ktjXZ472ec4LWLBrohcgvi4VOjYF139NnU6u2ILswsNeiY5e+vBiwbd+jz+hdPRx5cTPHcSd3vnyeYBC2b1ega6T59efbo5d0rdxwBJTVgQcjLh4Cee6mz4e3/mA97HrgoaePT3VBefq0u9//dyBfbz/sNx5TAcIXV35fsQeggQomgB2ED6ImYIHeSXihBBEeNmFt81n4XwMHxrAhiMmQluEBI8KAnXaQ/cZhigbghAyGs6DI2QYuRkYQjfXNCKOK0yU2JH6ZmYgjgp319+KR6hWJXi5J9uigjBTUGOONGkL5Ho9BAmmlj0x6GZx9SpqYG5ghMiDmmvqRtCKSXX6pAJVWJomniB2qeeabd2Yp5Xt5Ulelm00aOuiTfwpZpn991rknpGHCGamdiOrZ6JWFPhplopJeKqeZ3FhUXZqHcrqldwQSOaaCpdJpI6qh+lkhq+4xCiqtr7paKaUf2roboFHumuunsipq6KqShv146rDEdrpksgyyyKuqvtZqrKc/QcvmtSdiWmyJdS3KZ4PW/pptqsXGU62052Ibq7YtkdssuI8qG6+6x17EZBEu/vTvUFxWxay/Aw9U8EcHa4ElEgGzAnHEEk9MccUWX4xxxhpvzHHHHn8Mcsgij0xyySafjHLKKq/McssuvwxzzDLPDEoBACH5BAUKAAAALAUARgC+AF8AgQAAAAAAAP///wAAAAL/hI+py+2PhJy02otzhbz7D4bip5XmSY3qyrZugsby9tb2fc96jPf+39kJS8Ci0aVJBJbMpvMJjUphmaP1CkgipNyul0nFYMdA7eGLToMjVbI71z6r593w5Y1/mQ30ftRukScIUpE2yCe1dyhYiLbIpbiI1/j1mBgnmUfpZRkVmUm2WXcIiQlqJXqqUjqhWpTqGsIqEfsDW+sxK4Dbc8sLofsLN+EkzBFsrOKbzMxIUdwcrfncJG3ttnytXUa9tv1tkw2e20TzLT5+XJ4Cjp7+4GS+7f7eEM9+3r1UD3Lfyg/QhT9aAQt+GLjLoEJg6/4tfLgAIcSJShoSlAaNosYt/9U2egSQ8SPFkCIhkiy5kKS8MSsrekMJr+OBlldoynkJ055MAzaP9AS5MycDlfhCFVVwUqjLfWwcGnWKNKhShESh4hD1MymHlVpjUQ36E4m+AFmlBjna1dVXnGFbYD26NMAIrmZrrWU6E+4wCRJ14vRA9y+uu3KbXvTx1ipHwVvR1vX6WEFbFpMjRgYEMC1mborVMV5QuZlmwwlt6fWMF0JoZqPzdq6xenHqB7GNteZ5GnbumJ8l7x6XtjaiPw3K9t58czbwyMKBEmdgXHlxx8etBf/tF4qD6IUbQ70tmjn2oVOmv3YuHTr19Nuun3fAZftu8IHZa6M/fvgS7s0B9f9Pht97spE1n0WlrfBJPQEextt+BTLxn2t3KLTggQ0SeF5flJmS2WWkkQPhgw4K6N2Eg8R3hYaWhUjiiiMy6IcqKFqhYlQsMgjiixbGeMqMR9QYV3M18giKj0YAOaCQBsZlSI/l0bhkdhji2MGQfXSiY2gI8bfeExHqN6WFGlRFJQtpJOhimFx+d0mLF640Jlj5HYQGmjZmKWKYTEZpJp+4YUCmhQLVyaGUdlrpyZzw+ZlFBoHicGah5N0YiKFdIikLo3GypWiVbfLloYRizklSqYyOQJh8xDyp26qUVogcQziZSumgr4rnqnZ7CZDqWVBpGRStOtqqo3ugPtfqscW7hvong8DOGuypIvSqXq5PXDUWPbE26qaw3YH5JXphGssrq3qMte0kO6RrKZt0YEHuIkKwO+mwAzYJZW/hiqUDvWnWpwa8uJb51Az+3qnnvY6kOLCgb8z7oae1KlwJw9VlOnFyo5To8IbnhbbvG4hy4ivByuwGcqdFMoqvaiq7/PGcIbsx8sYwmzwXyjK/LEnNRqqKswg/pewmL+TOXDAR/BzNs7wodKivpMLwsHTDSLP0dNVRi2EN1YMUAAAh+QQFCgAAACwFAGkAmwA8AIEAAAAAAAD///8AAAAC/4SPqcst/5qctNqLs74w7g+G4vh1Aomm6sp17AvHoynX9o2z5u7m/r/hCYHE4kTIMyqXBuSOCSU6adFgJ4DFJqjSazYg4YbEL9MXjCD7zN9wT6ResbPbN3CuddhBcRUefdB38+cGQSKIQpi2t+ZFp2c4wyiDGFUpCXHWGFm1cAnnmIfzuUTKFwo4ONkJYFqCuunBWscJoxijuXKWy+DES/E7uxBMstsGyUPcoCx8wBxi/NiL9KxQLXy9ES3qSX1ckc0anrGdquD7DZzeXF6YtLxOFuyKKQvTjvwEL920N79qCyAKfNOG7OPWyl88gToYjiDYzSCDf7UAULRng54GiP/nkEi4eAIByFghC2Icl1DISJELK35seXKdu5IZ5MnMd6tfxZXgYNK0eNPkzxY7g0ZM5jMBT3X8UsZsOvNVUag4YS2aitDUUqBUhUp9inBmTqc/t75sarPr0aH5QJplqZarMScf3H5Jm1Xg2L0Cq5Wjq83nGbzmEPHNlPSgOaXbAG8UfFchWr1WA1XWiZFx3L8eA09GnIUwrcxXH9j9TNqZUbm7HJODHFpyXpdwsRB+qzqa6460e6IWMLjv6j+3E09s3Nmr59mmI/c2UI247F2j2eaem3xtXdi2hceVjpV6aevQkUvUvrwwKkTR10/HXV53dt6pmTIH7rw+66i11T+DJ3vWfQH6p99WKFV3AXwAKoYgg+MN2OB1i1mglXHoHfcbhA86aFl4X5FnjYX0gahgiSIeuKFvAuajYYcFiqjZihJ+2Mx4FUYjlkM1ljHfgO2dt+MoPSr24ztB5rCbj8MNeWQMSRK5JJBNWiHllFZSyOSVWgql0ZZNPullmC7qI2YOBQAAIfkEBQoAAAAsBQBGAL4AXwCBAAAAAAAA////AAAAAv+Ej6nL7Y+CnLTai3OFvPsPhuKnleZJjerKtm6CxvL21vZ9z3qM9/7f2QlLwKLRpUkIlsym8wmNSmGZo/UKSCKk3K6XScVgx0Dt4YtOgyNVsjvXPqvn3fDljX+ZDfR+1G6RJwhSkTbIJ7V3KFiItsiluIjX+PWYGCeZR+llGRWZSbZZdwiJCWoleqpSOqFalOoawioR+wNb6zEbgNtzywuh+ws34STMEWys4pvMzEhR3Byt+dwkbe22fK1dRr22/W2TDZ7bRPMtPn5cngKOnv7gZL7t/t4Qz37evVQPct8KDo1fC3+0rAUUuILgLoPVELJQeO2gQxEQGXqbSHHdP4z/HDt6/AgypMiRJEtekWiSI8qUE1eyROjyJb+YMt9JlDcGp5KGLDTQ5HUTXyihCn4GyWC0VtCNQ5kW5bnCJ9RmSwtiI7rzojKkU5lVXXjVadZ9LaRqBapRwtdX+gTo3NK1gVmy0hSu5UYsLdgFSQ3MFRBR711bbd/KOSuXK2JjdqcariHqMYC+WRTTjdZYq2QkhbHCXbzgb2DQCiT7ATSCJk7KaEmjttfntay4B1bTxny7tOfDc2T3y23bdTLKpmOzEdtBNVHWuIjvRkTH9wflTpmDOp2RSQzrkE15NT5bOwruerwPB/9b/AnynMVY7J19yfbcbN3XRT9dr+g3n9xw/xkL2HF3xOfWc7rlJRxvanz3x2eXVWZfevIZCAhl2DE2hYMB1maeOupZBQE9ABpyXoMKArIZbB/u9YCIGpKIoYnQPdgfMHp54KKCMMbylUIpDrIMTn+xR6BEPepH4SFBEjUkfTf8p2GFSCIHypJONZlgDVCeKGAAPiYJZFvSYflgEVvOuKFfnUXoipUgQnjBmUbsCKeXGU7kZiAqlllWW0fKiFCexWVJgp+OGUroNYIaSCQDovwJBUeLUokmDo8eimCkGE36JoCWihnlKTnydWOXdDYqYZpPJXrFqKtOeCWimnJpBU2o9gJqeLC+eSmgt5JD2q/DqOUkAxVxmOkotF4eYWuxTRHLqoJCyvqEpyc5W6dkipD3Y2gGDgFmJjVmuxy20uH4Lbid4jLutuZ2OYK26rLIS7umcBvugesiCy4z9rKJL6UtpquuSu/WdF+0CFN18MIM8unwOMJG3EIBACH5BAUKAAAALA8AZACvADwAgQAAAAAAAP///wAAAAL/hI+pa+HOopy02ouz3uxBDobiSJadZ6bqypJe0MbyTL/0jeecwPO2DgwCez6U8IhsEQW/pPMZWjah1CpFarRqt5Yp8AXOcq1eXfg83pZz53Bau8a1wW+y+Du/12ueZSJu8uIXAbhXIkj0p6eC2CNRaDjSyKP4MDMp8LgYediXiAAp6elIuMkp+jB4ECqCqWl5emmKBxv7xHqDaytb66S7G/MrIwy8QtxyXBz1+aR6xay8TNoMPeEcvVONdC3BjZ3hLRS+MP5dUa6DjqBuzjbbDl/aG08/kVwffY9frL8Pru3PH7uA5gYSxGbwoLKECoH1I7ck4rSGFww+VCAxI8V/lBPtvduQUeJGDBY/aggZcWRFgCfmkUDJkGK5OS+ruVJZ4eaqNjU76sT5ysE1miOGjqIE1GMqmzyLMl3aMamCnwCIijAKFanUlkJZLkiW52imrcFMfg3bNSrZQGanog0Qc22XtpXCxpVLAezbu1KxfpBDd67Lgk//5gqcE3EkvzDcDW6l2BBjM5GDNqY32bHhTo+xFQAAIfkEBQoAAAAsDwCCAKoAHgCBAAAAAAAA////AAAAAv+Ej6nL7SlifChYS7PeSk4OhmLjCduFjWpYru77tBoawDbp3TosZ/QOBPSCRM3w8SvajkphbobalJKMabQpojF3WwaVYr04wiksSPssdhffmKcNeV/NHLSkuVbAcZL9gVxDV4eSx5NG4bcAOCYnJnhCeMhRWDFnsAjlyNJIY1GS12k5qHkpGXeXWVbaJ+qQ6MYaGvBpWik70pZHeZDLGejTauRrR+sq+3smqlvrpewLSTo5HElr0nCMPKrqhFrFzOYcu20cLTV9Uf3RfJsVrr76zh3/irkeatiNSF2sRPx5Oi/Yn2fXjuGLR85Tuib+jhyhR9Bep4PWgKFb2G/fPwS0DwXCE/AKG0VoCqsx1OhQEkRx2RKIfLHLQMNvNmbmQ+JRXkVFKnOau5kwW8dorwCmQ1iwHEeaQ8eJiAmg1802RZceBZrU6UCsWwMq3cQVXLSm2ap2vUqypVWkZ136FBZWj7udUUWZ/Xg0LaO4ZEemEtqT6NuzKa+yFauVZ1wYNg/LZUfH8GJbiTvQZIzyMuWJgiQ7dvtV8ecXjekGvbvEs164o12UTouaYt6/P1uveP03togCACH5BAUKAAAALA8AggBpAB4AgQAAAAAAAP///wAAAAKhhI+py+0uYnwoWEuz3hxKsV1YR5Zm8oGaGJzuq6WhCNc2+s3XzfcA65EAfUTSkJE6FpcUpSJJY0odTpwwOs0mqgjoboXVimXgr3icK4/OWnKGyy66m+E4c65g4a0T+1SfhhTotwQoEdRHWCiy1zWo6GOYuNAISQRn2SOpcoCZebO5VfcZyfjoSQoTWjGaCmp66MpWKdv2WHtGiyulu7uEVwAAIfkEBQoAAAAsBQCCALkAIwCBAAAAAAAA////AAAAAv+Ej6nLHQ+jlE2Ji3OltTPuAWBIlqYzpVOZtcIWneHY0fKNf+r+sC4Gg+RQQpJtiLzxeL7fi9hLJo66ovR6Wu6av2AUK4oZxeCS1rpwXqbktJpqaMHLbsycfv7Wu4i5WuCXcUeHINdGyHZW8ZeoZ/F2mGCIhtgw6VhpkBewqNbIaQlJKSkYmUlqZ1q52en02foTmDp6WlhKK8Nk+wfUd9jyurvmi+txCSpzLDt8oFuVgsr71PyrQewIfI18coyjrBpnTa3itSLMG3yQPY4trgne0X3zXQyw/k4OZa4uzYzf3ovdNnvuwtSDBQgeQmd7pv3bt4AhwX7pwgV8GM2hQUz/JOQluwUt1MWNEElmLCfxpEg+AqUcuxev4CB+IyXC/JTyHEKYM42BDHBzpcaeE/2RpBFUYE6aRjPyVNjxZ9KGFWPW3KJT31KLTc89PRh11oOpj66CZToUK1qUaqkK/crxo1igBRFWtasNJzyyeJXCI6pSIN+wXZ+V1FtvMAO4h/POkxlBsc+RbOttLaqRS9p8hr1BhiDZauGIbRVcDh344RzAWQXXfUxZ69/SqU0wXg118eexr+WONk07Uz+jrMGcHl4reUNGjpUjjssVnfPpwzdDr3Wc4nTn1e86zy5tO3fkzcWDly4e+6bc6ccoan9qPXv4NfLQzyT/7P3KIffjEsk/kH8msCJgGQAGWOAM9rVXAAA7" alt="octopus crawling" class="img-30p">
<p>You might notice that the sprites are lacking colors. That's because I'm not a
good artist, and colors are difficult.</p>
<p>Next I coded a quick background parallax system and a minimal emitter system to
emit bubbles convincingly. This is the end result.</p>
<video controls="" muted=""><source src="/assets/medias/octo5-f869fd347d7d532c65f8bd6e2312e83c.mp4" type="video/mp4"></video>
<p>Then I burned out. And now I can't bring myself to even look at the code. Maybe
you can, though. So check out the
<a href="https://github.com/niravcodes/Octopus-Game-JS" target="_blank" rel="noopener noreferrer">code on GitHub</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://bynirav.com/blog/octopus-game-and-engine#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3>
<p>I worked on this project without much planning, or design. So it was interesting
to see the abstractions almost form themselves, and to see the architecture
emerge spontaneously from beneath the insignificant lines of code as I typed
them.</p>
<p>Right in front of my eyes, the coordinate-based motion wrapped itself in a
physics interface and neatly exposed methods like
<code>applyForce (magnitude, angle)</code>. The <code>Spritesheet</code> animation system amalgamated
with <code>Motion</code> and <code>Collider</code> to from a high level <code>Character</code> object for my
benefit. Components organised themselves into categories like <code>drawable</code>s and
<code>manager</code>s, which allowed for other interesting experiments like
<a href="https://stackoverflow.com/q/62194995/2735127" target="_blank" rel="noopener noreferrer">duck-typing-aided composition</a>.</p>
<p>Not to mean that it is perfection, of course. Far from it. On the engine side,
the API is painful, there's a lot of vestigial code, scenes are not isolated
(and colliders leak through by default), there is no obvious way to handle
instantiation of multiple objects, and there's a lot of cohesion among
components. On the game side, the controls are terrible, the world is
incomplete, and moving around is clumsy at best. The only consolation is that my
next game will be easier to make because of this exercise.</p>]]></content:encoded>
            <category>coding</category>
            <category>game</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[पर्खीर'न्छु]]></title>
            <link>https://bynirav.com/blog/पर्खीर'न्छु</link>
            <guid>https://bynirav.com/blog/पर्खीर'न्छु</guid>
            <pubDate>Sat, 05 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[I keep on waiting]]></description>
            <content:encoded><![CDATA[<p>I keep on waiting<br>
<!-- -->for a relief; she'll come barefoot</p>
<p>Like the wind she'll<br>
<!-- -->blow out the candles I've lit<br>
<!-- -->and like the wind she'll<br>
<!-- -->whisper in my ear</p>
<p>I'm waiting for that<br>
<!-- -->whisper in my ear ...</p>
<!-- -->
<p>Because I've picked up this strange habit of forgetting to exist at times. True,
I wake up in flesh and blood, and I walk through the air as it parts for me. Yet
between my step out of one room and into the other, I find myself dissolving
into thin air: much like a whisper that never finds its ear.</p>
<p>I keep on waiting<br>
<!-- -->for a quick kiss;<br>
<!-- -->a peck on the cheek will do.<br>
<!-- -->or a red slap<br>
<!-- -->right on that same cheek.</p>
<p>Because I've picked up this strange habit of wallowing in ennui; of basking in
the dull glow of the half moon and SCREAMING as a phantasm that never existed
yet I'm right here and phantasmal and SCREAMING</p>
<p>I keep on waiting<br>
<!-- -->on the terrace and barefoot</p>
<p>I keep on waiting<br>
<!-- -->on the terrace at 11 pm</p>
<p>I keep on waiting<br>
<!-- -->on the terrace with the power out</p>
<p>I keep on waiting<br>
<!-- -->on the terrace where I'm the only man in the universe</p>
<p>It's 11 pm, served with a light drizzle and a garnish of absolute darkness here
on this terrace where I stand so lonely I don't exist at all</p>
<p>And here the stars have descended into the gourds amongst whom I stand<br>
<!-- -->And here they'll wander down to the kitchen garden twinkling as ever<br>
<!-- -->And here they'll land upon the bushes: a constellation of berries<br>
<!-- -->And here they'll ripen into Fireflies,<br>
<!-- -->one presumes,<br>
<!-- -->to flicker for a little while just<br>
<!-- -->to go out like a candle</p>
<p><img decoding="async" loading="lazy" alt="image of fireflies" src="https://bynirav.com/assets/images/fireflies-2fb7b7056f9d41a41453b7dd3f4627e9.jpg" width="1920" height="1276" class="img_ev3q"></p>
<p>And among these Fireflies, I wait.<br>
<!-- -->I wait for that barefoot wind and her subdued whisper<br>
<!-- -->to put me out for a little while<br>
<!-- -->so I can wake up in flesh and blood<br>
<!-- -->and remain in flesh and blood for the rest of the day</p>
<p>Because I've picked up this strange habit of being everywhen:<br>
<!-- -->in the vast array of nameless days,<br>
<!-- -->in the spectrum between the Full Moon and the Crescent,<br>
<!-- -->during the afternoons and the evenings,<br>
<!-- -->and all moments in between.</p>
<p>And so my abode is smeared across days of the week and stretched across the
months<br>
<!-- -->And it might eventually settle itself across the years and decades<br>
<!-- -->like a dead cat curled up but rotten.</p>
<p>In my abode the time-stream flows like endless words, relentless words,<br>
<!-- -->words that never stop and words that never stay</p>
<p>So I wait,<br>
<!-- -->for that flowery giggle<br>
<!-- -->which will punctuate these words<br>
<!-- -->into sentences that I can live<br>
<!-- -->one at a time</p>
<p>So I wait<br>
<!-- -->for the kisses<br>
<!-- -->which will punctuate these<br>
<!-- -->Sundays and Wednesdays,<br>
<!-- -->and the untold number of Fridays,<br>
<!-- -->into hours that I can live<br>
<!-- -->one at a time</p>
<p><em>Featured photo by</em>
<a href="https://unsplash.com/@ikewinski?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer"><em>Mike Lewinski</em></a>
<em>on</em>
<a href="https://unsplash.com/" target="_blank" rel="noopener noreferrer"><em>Unsplash</em></a></p>]]></content:encoded>
            <category>writing</category>
        </item>
        <item>
            <title><![CDATA[ Flappy Millennial: An HTML5 Canvas Game]]></title>
            <link>https://bynirav.com/blog/flappy-millennial</link>
            <guid>https://bynirav.com/blog/flappy-millennial</guid>
            <pubDate>Tue, 09 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Meet Flappy Millennial. He's an average guy in his mid 20's and the future looks]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/photo2-c5025b21c7e10ffdd933cef7fafc7c31.png" width="1536" height="864" class="img_ev3q"></p>
<p>Meet Flappy Millennial. He's an average guy in his mid 20's and the future looks
bleak for him. With the threats of climate change, mass-extinctions, rising
authoritarianism, economic depression, unprecedented wildfires and so much more
ever-looming, nihilism has become his background music.</p>
<p>But worry not. For he has an antidote—well, not so much an antidote as a
sedative. He has his phone! Come help this Flappy Millennial ignore reality
while he scrolls through Instagram or something. You should play this game not
because it's good or anything, but simply so you too can pretend that things are
okay for a while.</p>
<!-- -->
<a href="https://niravcodes.github.io/flappy-millennial"><img src="https://bynirav.com/assets/images/preview-1c87befe25f66062f1bb47b1c6704d7f.gif" class="img-75 img-spaceTop" alt="Preview of the game"></a>
<p><a href="https://niravcodes.github.io/flappy-millennial" target="_blank" rel="noopener noreferrer"><strong>Play Game</strong></a></p>
<p>Browse the source code on GitHub at
<a href="https://github.com/niravcodes/flappy-millennial" target="_blank" rel="noopener noreferrer">niravcodes/flappy-millennial</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-came-to-be">How it came to be<a href="https://bynirav.com/blog/flappy-millennial#how-it-came-to-be" class="hash-link" aria-label="Direct link to How it came to be" title="Direct link to How it came to be">​</a></h2>
<p>I began writing a different game for HTML5 canvas a month or so ago. As I was
programming the game, I realised that a lot of my code was game agnostic. The
abstractions and modules that had organically emerged could be packaged up and
used to make other games. So I separated the game logic from the lower level
management code, and lo! I had created my first game engine essentially as a
side effect of refactoring.</p>
<p>Over time, I began to notice some problems with the design of the game engine
API, and to investigate further, I asked some of my friends to try using it to
make a game and report issues. But apparently they had their own work to do and
"ain't nobody got time for fun and games, we're doing Serious Work". So like a
neglected grandpa weaving his own straw mat while his granddaughters make TikTok
videos, I began making Flappy Millennial.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="but-why-another-flappy-bird-clone">But why another Flappy Bird clone?<a href="https://bynirav.com/blog/flappy-millennial#but-why-another-flappy-bird-clone" class="hash-link" aria-label="Direct link to But why another Flappy Bird clone?" title="Direct link to But why another Flappy Bird clone?">​</a></h2>
<p>Because I'm unoriginal.</p>
<p>But also because Flappy Bird has an engaging gameplay with a remarkably simple
game mechanic. It's a child's play to write a clone and for some reason even the
worst clones turn out to be fun. To prove the assertion I wrote yet another
flappy bird clone right here. Turns out just 60 lines of code and about an hour
or two is enough to make a fun flappy clone.
Click the square below to focus the game.</p>
<hr>
<!-- -->
<div id="canvasContainer"></div>
<script>let container=document.querySelector("#canvasContainer"),C=document.createElement("canvas");container.appendChild(C),C.tabIndex=1;let pipe1,pipe2,snd=new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="),pnt=(A=.2)=>{snd.playbackRate=A,snd.play()},W=C.width=H=C.height=350,CC=C.getContext("2d");colH=S=P=1;{let A=()=>100*Math.random()+50|0,e=e=>{let o=e,Q=A();return C=>{if(C)return o=e,void(colH=0);(o-=2)<-50&&(o=W,Q=A()),o>70&&o<100&&(colH=Q),20==o&&(colH=0,++S,pnt(1)),CC.fillRect(o,0,50,Q),CC.fillRect(o,H,50,Q-H+140)}};pipe1=e(W+100),pipe2=e(W+300)}let y=h=w=30;window.vy=0,ay=.4;let LP=()=>{if(CC.fillStyle="#235789",CC.fillRect(0,0,W,H),P)return pt("Press any key to play",H/2),pt("Score: "+S,H/2+40),pipe1(1),void pipe2(1);CC.fillStyle="#f1d302",y+=vy+=ay,CC.fillRect(70,y,w,h),colH&&(y<colH||y+h>colH+140)&&(y=30,P=1,pnt()),y>H+h&&(P=1,vy=0,y=30,pnt()),pipe1(),pipe2(),pt(S,40),requestAnimationFrame(LP)};CC.font="24px 'Poiret One'";var pt=(A,e)=>{CC.fillStyle="#fff",CC.fillText(A,(W-CC.measureText(A).width)/2,e)};C.ontouchstart=C.onkeydown=A=>{A.preventDefault(),P?(P=0,S=1,LP()):vy=-8},LP()</script>
<style> #canvasContainer canvas:focus{outline: dashed 4px #000; }</style>
<hr>
<p>Once you've played this to your heart's delight, check out the JavaScript it
took to make it work:</p>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">style</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token style language-css">  </span><span class="token style language-css selector id">#c</span><span class="token style language-css selector pseudo-class">:focus</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:black">{</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token style language-css">    </span><span class="token style language-css property">outline</span><span class="token style language-css punctuation" style="color:black">:</span><span class="token style language-css"> dashed </span><span class="token style language-css number" style="color:red">4</span><span class="token style language-css unit">px</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#000</span><span class="token style language-css punctuation" style="color:black">;</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token style language-css">  </span><span class="token style language-css punctuation" style="color:black">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token style language-css"></span><span class="token tag punctuation" style="color:black">&lt;/</span><span class="token tag">style</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">link</span><span class="token tag"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token tag">  </span><span class="token tag attr-name">href</span><span class="token tag attr-value punctuation attr-equals" style="color:black">=</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag attr-value">https://fonts.googleapis.com/css2?family=Poiret+One&amp;display=swap</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token tag">  </span><span class="token tag attr-name">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:black">=</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag attr-value">stylesheet</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token tag"></span><span class="token tag punctuation" style="color:black">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">canvas</span><span class="token tag"> </span><span class="token tag attr-name">id</span><span class="token tag attr-value punctuation attr-equals" style="color:black">=</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag attr-value">c</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag"> </span><span class="token tag attr-name">tabindex</span><span class="token tag attr-value punctuation attr-equals" style="color:black">=</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag attr-value">1</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token tag punctuation" style="color:black">&lt;/</span><span class="token tag">canvas</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">script</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> snd </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name" style="font-weight:bold;color:black">Audio</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript string" style="color:red">"data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">pnt</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">r </span><span class="token script language-javascript parameter operator" style="color:black">=</span><span class="token script language-javascript parameter"> </span><span class="token script language-javascript parameter number" style="color:red">0.2</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    snd</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">playbackRate</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> r</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    snd</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">play</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">C</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript dom variable" style="font-weight:bold;color:black">document</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">querySelector</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">"#c"</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">W</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">width</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">height</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">350</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">getContext</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">"2d"</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  colH </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">S</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">P</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> pipe1</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> pipe2</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript known-class-name class-name" style="font-weight:bold;color:black">Math</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">random</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">*</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">100</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">|</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">pipe</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">off</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> x </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> off</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        h </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">return</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">rst</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">rst</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          x </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> off</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          colH </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">return</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> x </span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          x </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">W</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          h </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        x </span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">70</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;&amp;</span><span class="token script language-javascript"> x </span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">100</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">colH </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x </span><span class="token script language-javascript operator" style="color:black">==</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">20</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          colH </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          </span><span class="token script language-javascript operator" style="color:black">++</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">          </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pnt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fillRect</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">        </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fillRect</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> h </span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">140</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    pipe1 </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">100</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    pipe2 </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">300</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> y </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">h </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> w </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript dom variable" style="font-weight:bold;color:black">window</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">vy</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">ay </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0.4</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript dom variable" style="font-weight:bold;color:black">window</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method-variable function-variable method function property-access" style="font-weight:bold;color:black">onload</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:red">"#235789"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fillRect</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">W</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">"Press any key to play"</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">/</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">"Score: "</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">S</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">/</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">40</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe1</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe2</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">return</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:red">"#f1d302"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    y </span><span class="token script language-javascript operator" style="color:black">+=</span><span class="token script language-javascript"> vy </span><span class="token script language-javascript operator" style="color:black">+=</span><span class="token script language-javascript"> ay</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fillRect</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">70</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> y</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> w</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">colH </span><span class="token script language-javascript operator" style="color:black">&amp;&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">y </span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript"> colH </span><span class="token script language-javascript operator" style="color:black">||</span><span class="token script language-javascript"> y </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> h </span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript"> colH </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">140</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      y </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript constant">P</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pnt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    y </span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">H</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript"> h </span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">vy </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">y </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pnt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe1</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pipe2</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">40</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript function" style="font-weight:bold;color:black">requestAnimationFrame</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">font</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:red">"24px 'Poiret One'"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">var</span><span class="token script language-javascript"> </span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">t</span><span class="token script language-javascript parameter punctuation" style="color:black">,</span><span class="token script language-javascript parameter"> h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:red">"#fff"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fillText</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">t</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">measureText</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">t</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">width</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">/</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript"> h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  </span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">  c</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">ontouchstart</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> c</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method-variable function-variable method function property-access" style="font-weight:bold;color:black">onkeydown</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">e</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">    </span><span class="token script language-javascript constant">P</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">vy </span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript number" style="color:red">8</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:black">&lt;/</span><span class="token tag">script</span><span class="token tag punctuation" style="color:black">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That's about 60 lines of javascript which makes a playable Flappy Bird game,
complete with touch screen support and sound effects.</p>
<p>Now, that should have been the end of it. A game in 60 lines of code is good
enough. But something in me was begging to take it even further. And as if to
tempt me yet more, the power went out and with it the WiFi. What is a young man
in this lockdown to do without the umbilical cord of the Internet forever
pumping numbness into his thoughts?</p>
<p>So then I went ahead and made it even smaller.</p>
<!-- -->
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">canvas</span><span class="token tag"> </span><span class="token tag attr-name">id</span><span class="token tag attr-value punctuation attr-equals" style="color:black">=</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag attr-value">c</span><span class="token tag attr-value punctuation" style="color:black">"</span><span class="token tag punctuation" style="color:black">/&gt;</span><span class="token tag punctuation" style="color:black">&lt;</span><span class="token tag">script</span><span class="token tag punctuation" style="color:black">&gt;</span><span class="token script language-javascript constant">C</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript dom variable" style="font-weight:bold;color:black">document</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">querySelector</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">'#c'</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">width</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">height</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">350</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">h</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">w</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">vy</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">ay</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">.4</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">for</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">$ </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">in</span><span class="token script language-javascript"> </span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">C</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">getContext</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">'2d'</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">[</span><span class="token script language-javascript">$</span><span class="token script language-javascript punctuation" style="color:black">[</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">]</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">$</span><span class="token script language-javascript punctuation" style="color:black">[</span><span class="token script language-javascript number" style="color:red">6</span><span class="token script language-javascript punctuation" style="color:black">]</span><span class="token script language-javascript operator" style="color:black">||</span><span class="token script language-javascript string" style="color:red">''</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">]</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">[</span><span class="token script language-javascript">$</span><span class="token script language-javascript punctuation" style="color:black">]</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript parameter">_</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript known-class-name class-name" style="font-weight:bold;color:black">Math</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">random</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">*</span><span class="token script language-javascript number" style="color:red">99</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">pp</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">off</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="font-style:italic;color:black">let</span><span class="token script language-javascript"> x</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">off</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">ph</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">return</span><span class="token script language-javascript"> </span><span class="token script language-javascript parameter">r</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript">r</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">off</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">ph</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function" style="font-weight:bold;color:black">rH</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">|</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript number" style="color:red">70</span><span class="token script language-javascript operator" style="color:black">&amp;&amp;</span><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript number" style="color:red">100</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">ph</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">x</span><span class="token script language-javascript operator" style="color:black">==</span><span class="token script language-javascript number" style="color:red">20</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript operator" style="color:black">++</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript constant">B</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">400</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fc</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">ph</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fc</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">x</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">50</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">ph</span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript number" style="color:red">140</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">p1</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function" style="font-weight:bold;color:black">pp</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript number" style="color:red">100</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">p2</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function" style="font-weight:bold;color:black">pp</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript number" style="color:red">300</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">onload</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript parameter">_</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript string" style="color:red">"#258"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fc</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">if</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript string" style="color:red">"Score "</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript operator" style="color:black">/</span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">p1</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">p2</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript keyword control-flow" style="font-style:italic;color:black">return</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript string" style="color:red">"#fd0"</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">+=</span><span class="token script language-javascript">vy</span><span class="token script language-javascript operator" style="color:black">+=</span><span class="token script language-javascript">ay</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fc</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript number" style="color:red">70</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">y</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">w</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">&amp;&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">&lt;</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">||</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript">h</span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript">colH</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript number" style="color:red">140</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript constant">B</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">&gt;</span><span class="token script language-javascript constant">H</span><span class="token script language-javascript operator" style="color:black">+</span><span class="token script language-javascript">h</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">vy</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">y</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">30</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">B</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">p1</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">p2</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">40</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript function" style="font-weight:bold;color:black">requestAnimationFrame</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">font</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript string" style="color:red">"24px serif"</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">pt</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">t</span><span class="token script language-javascript parameter punctuation" style="color:black">,</span><span class="token script language-javascript parameter">h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">fillStyle</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript string" style="color:red">"#fff"</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">fx</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">t</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">W</span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript constant">CC</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">me</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript">t</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">width</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">/</span><span class="token script language-javascript number" style="color:red">2</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript">h</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">c</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">ontouchstart</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript function-variable function" style="font-weight:bold;color:black">onkeydown</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">e</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript operator" style="color:black">?</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">P</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">0</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">S</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript number" style="color:red">1</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">&amp;</span><span class="token script language-javascript constant">LP</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript operator" style="color:black">:</span><span class="token script language-javascript">vy</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript operator" style="color:black">-</span><span class="token script language-javascript number" style="color:red">8</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript"></span><span class="token script language-javascript constant">A</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript keyword" style="font-style:italic;color:black">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name" style="font-weight:bold;color:black">AudioContext</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function-variable function maybe-class-name" style="font-weight:bold;color:black">B</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript parameter">_</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript punctuation" style="color:black">{</span><span class="token script language-javascript">o</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript constant">A</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">createOscillator</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">o</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">frequency</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">value</span><span class="token script language-javascript operator" style="color:black">=</span><span class="token script language-javascript">_</span><span class="token script language-javascript operator" style="color:black">||</span><span class="token script language-javascript number" style="color:red">999</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token script language-javascript">o</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">start</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript">o</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">connect</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript constant">A</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript property-access">destination</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">;</span><span class="token script language-javascript function" style="font-weight:bold;color:black">setTimeout</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript parameter">_</span><span class="token script language-javascript arrow operator" style="color:black">=&gt;</span><span class="token script language-javascript">o</span><span class="token script language-javascript punctuation" style="color:black">.</span><span class="token script language-javascript method function property-access" style="font-weight:bold;color:black">stop</span><span class="token script language-javascript punctuation" style="color:black">(</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">,</span><span class="token script language-javascript number" style="color:red">99</span><span class="token script language-javascript punctuation" style="color:black">)</span><span class="token script language-javascript punctuation" style="color:black">}</span><span class="token tag punctuation" style="color:black">&lt;/</span><span class="token tag">script</span><span class="token tag punctuation" style="color:black">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Yeah, that's right. It is 15 lines of handwritten HTML and javascript code that
will make a flappy bird game in your browser. Pretty cool, huh? But line count
is not a valid metric for this code. Here's a proper one: this code is less than
970 bytes. That's about a 100 times smaller than the code size of flappy
millennial. And it still works! Of course, at that point I was left wondering
why my actual Flappy Millennial code is so huge.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how">How?<a href="https://bynirav.com/blog/flappy-millennial#how" class="hash-link" aria-label="Direct link to How?" title="Direct link to How?">​</a></h2>
<p>The main game logic is
in the <code>js/game.js</code> file. It begins by importing a bunch of classes and
functions from the library, including <code>Character</code>, <code>Spritesheet</code>, <code>Collider</code>,
and <code>StaticText</code>. These classes abstract the mechanism of animating on the
canvas and checking for collisions among other things. These things are very
helpful because the canvas API, while flexible, is very low level. For example,
if you wanted to play an animation using the bare canvas API, you'd have to
convert your GIF into a sequence of images and manually draw each image while
also taking care of the timing and positioning. Things like that don't scale
well as the game gets bigger. With my library, you can simply say
<code>Character.runAnimation()</code> and the rest is taken care of for you. The game is
gradually implemented using these primitives and very simple javascript. A
casual skim of the code in <code>js/game.js</code> on GitHub should be enough to get most
implementation details.</p>
<p>I made most of the art for the game myself, including
our titular character Flappy Millennial. It was made using
<a href="http://piskelapp.com/" target="_blank" rel="noopener noreferrer">Piskel</a> which is a great pixel art animation software.
It isn't as feature-rich as I'd like but works well right in the browser and I
love it for that.</p>
<img src="https://bynirav.com/assets/images/flappymillennial-0d638c094f7ca71b47582056c0b139f5.gif" style="width:30%;min-width:150px" alt="animation of character">
<p>This is the animation for our Flappy Millennial. I labored over it for a couple of
hours and I feel like it's turned out okay. But if I had to start again, I'd
definitely make the wings not look so stiff and cardboard-like. The beautiful
background art that I'm using was made by
<a href="https://vnitti.itch.io/" target="_blank" rel="noopener noreferrer">Vicente Nitti</a>.</p>
<h1>Build system</h1>
<p>I've acquired the habit of writing ES6 javaScript by default because I do so much work with React, Vue
and NodeJS. That's generally a good thing, but it also means that if I want my
javascript code to work on most browsers, I'll have to use external tooling.
That was the case with Flappy Millennial.</p>
<p>So I had to put together a set of
tools to convert my modern javascript dialect to standard javascript understood
by most browsers. Without this process, my code wouldn't work on current mobile
browsers and slightly outdated or extended support editions of desktop browsers.
It isn't a particularly difficult thing to do, because these tool makers have
already put in all the effort.</p>
<p>First we pass our javascript through Babel with
plugins that convert to ES5 javascript. Then output is then passed to
Browserify, which reads all the <code>import</code>s and <code>require</code>s, and puts all the code
together in a single, huge file. That file is finally passed to Google closure
compiler, which minifies the code and in our case, creates a file that's half
the size of the unminified code but with the exact behavior.</p>
<p>I could have used
something like Gulp to create this pipeline, but this time it isn't too
complicated so a simple bash script did the trick.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">#! /bin/bash</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Rebuilding Game"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">rm -rf dist</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">mkdir -p dist/js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">cp index_dist.html dist/index.html</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">cp favicon.ico dist/favicon.ico</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Copying Assets"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">cp -r assets dist/</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Transpiling with Babel"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">npx babel js/library -d dist/js/library</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">npx babel js/game.js -o dist/js/game.js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">npx babel js/LOGSCORE.js -o dist/js/LOGSCORE.js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Browserifying"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">npx browserify dist/js/game.js -o dist/js/game_browserify.js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Cleaning up"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">rm -rf dist/js/library</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Minifying"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">npx google-closure-compiler --js=dist/js/game_browserify.js --js_output_file=dist/js/game.js --jscomp_off=checkVars</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">rm dist/js/LOGSCORE.js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"># rm dist/js/game_browserify.js</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">echo "Done! (ignore the warnings)"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h1>Azure and Analytics</h1>
<p>One of the tangential goals of this project was to set up a simple analytics
system that logs what score you make and when you make it. With that data I can
look for interesting patterns like how many times the average player plays the
game before rage quitting, or the global high score, or if players come back to
play a second time.</p>
<p><strong><em>Side note</em></strong><em>: You don't have to worry about privacy. The data I collect is
totally anonymous and ridiculously harmless. I'll eventually publish interesting
findings from the data once I have enough of it.</em></p>
<p>So anyway, to make that system, I chose to use Azure Functions. Azure Function
(and its equivalent from other cloud providers) is an awesome service that makes
backend development, deployment and scaling so much easier. I've fallen in love
with it and all the possibilities it represents.</p>
<p>A cloud function is essentially some code that triggers when some event happens
(say a HTTP request, or a database modification), does some processing, and
creates some output (a HTTP response, a database entry modification). In my
case, every time the player dies, his score is sent to a cloud function that
does some verification and records the score in a CosmosDB database. All in all,
it took about 10 lines of code and some basic configuration. To do the same
thing with a virtual machine, I'd have to instantiate a new VM and a new disk to
go with it, configure the firewall, install all the software, <code>scp</code> local files
to the VM, <code>npm install</code> and wait, provision https certificates, and just so
much more.</p>
<p>But was it a smooth ride? Nope.</p>
<p>I actually have a lot of bad things to say about Azure's user experience and I'm
very tempted to say them. In fact there are a bunch of paragraphs just sitting
here in the drafts waiting to be unleashed. But they'll have to wait a lot
longer. I need to explore Azure a lot more to either articulate my opinions
properly or to be proven wrong.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="first-few-hours">First few hours<a href="https://bynirav.com/blog/flappy-millennial#first-few-hours" class="hash-link" aria-label="Direct link to First few hours" title="Direct link to First few hours">​</a></h3>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/photo-9f1605715b9f4023eb645ce2c15c2477.png" width="983" height="452" class="img_ev3q"></p>
<p>This is the data collected in the first few hours after I published the game on
GitHub. So far the highscore is 27. Think you can do better? Go play the game at
<a href="https://nirav.com.np/flappy-millennial" target="_blank" rel="noopener noreferrer" title="link to game">nirav.com.np/flappy-millennial</a>
and prove it. I won't know who you are, but I'll know you're a badass.</p>]]></content:encoded>
            <category>coding</category>
            <category>game</category>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[Making मनसा: a Nepali Programming Language]]></title>
            <link>https://bynirav.com/blog/making-मनसा</link>
            <guid>https://bynirav.com/blog/making-मनसा</guid>
            <pubDate>Sun, 09 Feb 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[I've been working on and off on a Nepali programming language with my friends]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAD6CAIAAADyT65HAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAHrtJREFUeJzt3YtfVGXCwPH3X3gFVyu3rLZ6267bbbdd691u79u+bW2AeAk107yXyk0uiooCiTdEVMTMW5KhKd7yrpGJpKxISCogKojIHeQ6MBffR8emaYYZ5n44c37fz/PZz67OOXOY8TO/fQ7nOfMftwAAULD/kPoAAACQEiEEACgaIQQAKBohBAAoGiEEACgaIQQAKBohBAAoGiEEACgaIQQAKBohBAAoGiEEACgaIQQAKBohBAAoGiEEACgaIQQAKBohBAAoGiEEACgaIQQAKBohBAAoGiEEACgaIQRMXatpiNv87eTk9OQdR6/XNUp9OADcixACvyHK96+YlX0DQv7z/en3DZsROC+trLpep9NJfVwA3IUQAr+qu9kanLpVJNB4DJ2/5nxZpdSHBsBdCCFwl6pLPXfTHpMK6sdzE+N2ZedLfYAA3IIQAnelZB574IPIbkMoxsCgqK+/y9VotVIfJgAXI4TAbXkl5QOGRViqoH70Gxw6bWVGa4dK6oMF4EqEELhVcLninzNTrFdQP3z9Q0QL+ZUh4E0IIZSuqbV9cnK6LRU0vnymuKJa6gMH4BqEEIrWqdYExK728Qu2K4RivDkjSepjB+AahBDKpdPpVu3O6jc41N4KivHgiGipDx+AaxBCKFe7qvON8KUOVFCMF6ckSH34AFyDEEK5Ojq7/jcy2YEKPjQiesPBk1IfPgDXIIRQtC8P5zgQwvmb93aqNVIfOwDXIIRQujXfHn98zBzbKzh3056m1napjxqAyxBCKF27qjMjK/flqQt6TGAfv+B/zkypbmx25um0Ot31usbCK9ez8ou2fX8m/egpMfb+WJBzvrS4oprEAp5HCIHbccotuvrY6BjrIXxi7NyL5Tccfha1RptXUp60/UhA7OrnJsaZ7Lx/YNgr0xdOTk4XVb5R3+TCnw6AdYQQuEtM9aatzNB/AVO3FSytrHVsz2KeJ6Z9In42LlgUURRTT9Fm0U7X/owAzBFC4FcVtY0Ltuw3v+no0+NiRckc2+epC5cnLtv80Ihoey/JeX5SXGLGAWaHgLsRQuA3xCRM5OfeoTOMm/RezArHvqo+53yp6JlJ4Xz8Qx6ZlDAobt27qzMD1u8T43+StvxlTtq9QaaxFFPDoIS1DS1tLv8xARgQQsBUwlf7fP1NT5AOnb/G3v1sPnLKZHL54NjYNxanf1Zat7JBbT6W16iCfzj/XERK/+G/+TaoV4MXXa2qc8dPCuAWIQRMdKo13d50TcwR7dqPmAuaVPAfy7fFnq9cUd/VbQUNI+lG27Ssc3+cutD4alXRQuaFgJsQQuA3qhubTS4f7R8Y9uyE+ZOT023fSUZWrvFOfv9hzNDNh6z3zzyHf4393NcoyW9HJhdcrnDfDw4oFiEEfkOt0YrJXNL2I6t2Z70/e5UokPjv565cr2lqsXEPu7LzX5qSYAjY/aNnj9mVLcJmVwjFiC+ueW3hl4YW+vgFB85Lyyspd+uPDygQIQQsWrBlvyiQvdeLvjkjyXhCOXJb1rKqdnsraGjhoLh1v15l4xf8yvSFTq7oB2CCEAIWORnC+0bM/ORovmMJNIyUus730nb+bki4IYdiupmVX+SmHxlQIEIIWJSSeUyEZ9XuLNs36dLdis/Kf2lW6rPhy8bvP728RuVkCMVYer1l6OZD/Yb+eunNWzOSaCHgKoQQsEjMBUV1xLzQxseLCuartHcudWldUtHsfAKNxzsrtxu3UMwLHb7TDQBjhBCwaPsPeSI50esyVV3qHh8sKniyXeva+JmMYemHjVv41LhYrp0BnEcIAYt+OFciejM5Od2WL4X4oU2b1ujGCoqxrKo9KOOY8ZU4ooXMCwEnEULAojPFZQ+PnBkQu9rS/dV25/z0/uxV78WsWHbinFsTaP0cKb8vBJxBCAGLfr5a+cKk+DdnJHU768rIyjWsF3x4/HyPhXBRedO7qzO5dgZwFUIIWHSlqu7tyOSnx8Wa39LF5AY0/YbO8FgI9S0U80Ljc6QiyawvBBxDCAGL6m62jlm8UWTmh3MlJn+lv6DUhesFHRhBGcc4Rwo4jxACFnWqNbPW7xSN2fb9GZO/Ol1SLvrnGxD6wEdzXLVe0N6xrKrd5DpSzpECDiCEgDX6NfXiP43/UL9ecOKBXP91e6d/X+j5BBoP1hcCTiKEgDW7c34SdQlP+8bwJx5YL2jvYH0h4AxCCFgjiiLSMjh2teFPPLBe0N7B+kLAGYQQsKaptV105fWwJdWNzWIuKCooefYsDdYXAo4hhEAPHv1w1rMT5mcVXjrZ3uvmgsaD9YWAYwgh0IPXQpf8fnjkrL3ZkqfOlhayvhCwFyEEehCe9o0oyj9StkneORuHyfrCJ8bONV/+AcCAEALWaG/dmp35Xd/A8OejVkheOBuHfn3hvUHRxvPCjKxcqV9LoJcihIBFooKXOnXTviu4f/TsBz6aI3nh7BrDtxy5b8RMQwsfGx2Tc75U6lcU6I0IIdA9UcF8lTa1QZ14peHJ6YtFS+ZdrJI8b3aN8ftPG7fwoRHRB3ILpX5dgV6HEALdy+/Qrv3lGtFXEzaIkHy0SwbXyxiP5TWqT47mG187I1rIvBAwQQiBX50pLpu1fmfS9iNZtS2pRkUZuvmQqMhfYz9fUd8led7sHUEZx0zOkfL7QsAYIQTuysov+p+IZT5+wf0DwwLX7zVuydSsAt/BoY9N/mxhWZPkYbN3JN1oM/l9IdfOAMYIIXBbdWOz4Vt2b9+iLHiJcUtmn7v2yKSEez6ImpVfJnnYHGuhyT3YxLywuKJa6lcd6BUIIXB7LmhcwX5DIyYcyDUOybKq9n+kbBN/NSz9sORVc3h8cjSfc6SAOUIIpRMVfGtGknEFRe1E+UwqMmHfafG3T4cmSd4zh8fyGpXJdaScIwVuEUIoXGllrclc8J2V27utyLyLVfrHLCqX368JjYf5tTNcRwqFI4RQrryS8qfGxZrMBa0k5JGJ8eJhJmdN5ThYXwgYI4RQKDEXNK6gGGKqZH5G1HgErN8nHvbPVTusP6z3D9YXAsYIIZTI/OoYS2dEjcfMs1f7D498eHxcTEG55DFzfrC+ENAjhFAc86tj3l2dactv/sRjHv800cc/ZNy3pyTPmPOD9YWAHiGEspisFxRDzAVtv/7lf5MzxCZvLv1K8oy5qoWsLwQIIRQkv/Taa6FLjOeCIgN2lSOhpLZvYNgjE+Kj865InjFXDdYXQuEIIZSi4HJF4Lw0H79g6+sFexzPhC0TLRyy6aDkAXPVMF9f+KcJ81fu+k6j1Ur9pgGeQAihCA0tbW9HJhtX0JarY7odAev3+Q4OfS4iRfKAuXaYXDszYFhE5omzWp1O6rcOcDtCCO93taru1eBFho94MZ8buvmQw8GYfe7aY5M/E/tJKK2TvF6uHaHZFx4aN8/wQt0zJHzToRyp3z3A7QghvJyYC4oK9vllLijGu6mZS663OFyLFfVdryVuuv31hDtl9vWEPY6Uus6of1/2DQg1nheyvhBejxDCm92obxqVuN7wse47OHRQ3Drxce9kMD45clZMK5+LSIkvrpG8Xi4fkw+deXDsr7caeH5S3KkLl6V+JwE3IoTwWmqNNmn7kf6BYYYKvrbwS5ekK76k5vmoFb8bEj75cJ7k3XL5WF6jGrv75O8/jDG0cFJyenNbh9TvJ+AuhBBeq+ByxctTFxg+zf8yJ81VE7gV9V0jt2XdXlC4ON35+WUvHEk32oZuPmR46f4waiYLKuDFCCG8VlDCWsNH+R+nLlxS0ezaVNzzQZSYNn1yNF/ybrlpvL5os+EFfHFKgtTvJ+AuhBDeqaapZcCwCP2HeP/hkZ8cPevyTgyKW+fjH/JqwgbJi+WmEfNT+f2jZ9+91DYghDvOwFsRQninvT8WGGYzz4QliQmcyzsh5oJiRijmhYlXGiSPljtGSl3nf3+20fAyspQC3ooQwgu1dqiCU7caPsHH7zvtjk4sr1ENmv+F/jeFK+q7JO+WO8bsgnLDyzhm8ca6m61Sv7eA6xFCeKGrVXX/F738l5vIzHDf1wdOPpznGxD64Mexcd64jkI/DJeP/m1aYtG1KqnfW8D1CCG80JnisodH3r1b2NOhS90XicXXbr5x54qSf63ZJXmx3DReikk1LK5nQSG8EiGEFzpReMlwW1H3XsxS3xWafcHHP+TeoGhvnRT+/c5tdPTjh3MlUr+3gOsRQngh8Xlt+OwWMza3diKlrvOp4Ntf7RSw/tvk6g7Ju+Xy8dbSrwghvBshhBc6knfB8Nn9lvu/RDc674qYEd7zQdT07wsl75bLxxtGqwkJIbwSIYQXMp4R/j1xk7tTsayqXb/2/L8/2+iOdRrSjkFxXxiWEmYXXpL6vQVcjxDCC+UWXR0YFKX/+H4heqUHajHvYlW/oREDRs2aeCBX8nS5djw5fbH+lXx0dExeSbnU7y3geoQQXuhSZc3rYUv1H9/3BkWv8MjtQN9Zud3HP+SPUxd6091Hl1xvMXwrk9+c1IraRqnfW8D1CCG8UFNr++TkdMPZ0YjcSx5ohpgUPv5Joni6qd8VSB4wV40Ptx83vIxRa3eoutRSv7eA6xFCeKf0o6cMn+B/jlntmes5P96T0zcw7Mnpi+cUVkjeMOfH4ms39WnXj6z8IqnfVcAtCCG8U1l1fb/Bd8/p3TdiZsSpEg+UY8Hl+lcTNvj4h/h9sXd5jUrykjk5xuzK/t2QcMM3MbV2qKR+VwG3IITwWq+FLjHMZl6aleqZX91F5paKp3vw49iwkxclL5kz47PSuoFj5upfPR+/4MnJ6VK/n4C7EEJ4raz8oqfGxRpa+I+UbYvKmzyQEPFEvoNDH52UIN+lFLPyy54NX2Z46V4PW1paWSv1+wm4CyGE11J1qSM/32G411q/oRFDNx/yQJzmFFY8HZrUxy/4/bV7kmvkd68ZUcE/x6zu88vrdv8HkRsOntTqdFK/n4C7EEJ4s+KK6jdnJBlmNveNmBmUccwDLfloZ3bfwDDxdJG5pZKHza4h/o+CmAsaKihGeNo3DS1tUr+TgBsRQni50srax0bHGD7Wxfh474/u+2KmX3LS+l7aTvFcD4yes6SiWfK82TgSSuteiV9neKF8/UOGzE/rVGukfg8B9yKE8H7Hzl58aES04fO939CIYemH3R2VxdduigqKp/Nft9fd3XXJWF6jenv5NuO5oKhgfTPfxAvvRwihCGeKy16akmDcwndWbnd3WsJOXrw3KLpvYNjIbVmeidmqBvXGJs3RNu1PKu11ta5Jq+sy+tVes/ZWlUZX1Kk72a7d2axJ/W0FB8Wt8/1lwUm/waGjEtczF4RCEEIoRVZ+0VtGvy/UzwvdOldLrukQ00Exx3r808QZp4rdmsA1jeq9LRrRvxqNTtXTdS2aO1Es7dIdb9Nm3NQsvdYs/m+BcQUnLttcVl3vkbcFkB4hhIKIFprMC9197YyYaT05fbFo4XMRKe5byPjVTU1eh7bL/us6dXeKOP/QaUMFxRBzQSoIRSGEUJbqxmbjFoohJkNuXV8YX1wjKiie6F9rdi293uLanW9sUpd06hxIoF6bqmvtgWzDS+HjF/x2ZDJ3kIHSEEIojvk50ndXZ7q1hZ8e+2ngmLn3BkV/uOO4pVuvpTao1zep029qMm5qtjdrdjZrMps1W29qvr6p2dik+bzR9PGrGtS7WzTX1Y6v7xMVTN17/JEPZxkqGDgvreByhQtfakAWCCGUyPwcqVuvnRHx+2jn7YnXw+Pnh5w4bzar0+xv1f67Q1vapavR6Jq1t/QzPPEfbdpbTdpb19S6CyrdiXatSOOaxrvVFKVsc26Nu5gLGioohpgLUkEoEyGEQpVW1hrfgE2MoIxjbr125s+zV/v4h4ipYXxJrfifXzSq97Roijvtq5n21q2fVbr8Dq3WiZ+9S6M5mHfB8IP38Qt+NXgRq+ahWIQQypVXUm7cQnevL4wvrtHfwPOFyBXbqlvE5E8t0W3LMnN+Mp4LigperaqT5lCAXoAQQtHEvNCT50hnn7360YqM3KKrEt660/iMqP7qGOaCUDhCCKXz2PrCDU3qH1vVta0dUv2kXRqN8VyQq2MAPUIIeGJ94ZpG9eUunbR3ajmYd4GrYwBzhBC4za3rC3c2a2o1Un6NEesFASsIIXCXm9YX7mrWVEl1VcwdrBcErCOEwK9cvr5wc5OmUeo7V284/CNnRAErCCHwGy5cX/jl7QpKORfU6nQFV66zXhCwjhACpszXFwas32fp1miWxuoG9TVJz4gK2T+XPjF2LusFAesIIdANk/WFvoNDB8Wts72Fnzeq8zqcufeLC+w7XWioIOsFASsIIdC9nPOl/nNTfX75xnbRwndWbl987aYtITzSqu3xSwHd6tyV609+PJerYwBbEELAIhEPMZEynhf+c9WOHr9WcFOTplLSk6LlNQ2vTF/I1TGAjQghYE1rh0qExDAvFGNQ3Lr44prbvwVsvP2NuHtaNEfbtIZxol3bKt05UZHfHy9cHjBshuFo35yRxHpBwDpCCPRATKcC56UZnyN9f3nG0Yb2a2pdvUYnstep+3VIOBUUz3zo3z+//OkCQwXfmpGUXXhJsgMCZIIQAj0zOUf6yIez1h7IlvqgTIm5oHEFX5qSkJVfJPVBATJACAGbNLS0vRq8qI/ROdKDeRe6NFKvlv9FeU2D8RnRp8bFllbWSn1QgDwQQsBWV6vqRAuN54WZOT9JfVC3/Xy10vjqGFHBvJJyqQ8KkA1CCNhBzAuNr53pDedIzc+IMhcE7EIIAfuYXDujnxdKdY5UzAVFBQ0H89aMJH4vCNiLEAJ2M7925mDeBc8fhsl6Qa6OARxDCAFHmK8vXHsgu03V5ZlnN18vKCpY3djsmWcHvAwhBBxkfo40de9xD7Sw2/WCzAUBhxFCwHGSrC9kvSDgWoQQcIqH1xeyXhBwOUIIOMtj6wtZLwi4AyEEXMBkfeH9QVExG/e49ilyzrNeEHALQgi4hsm1MwOGRSzPPNqu6nTJzguvXme9IOAmhBBwmfNllUPnrzFM2kQLU/d87/xuK2obB7FeEHAbQgi4TGuHauWu7wzF0o/oLzLrb7Y6vM8LZTeemTDPeIcLvj7AVwwCLkQIAdcQcUrJPPaHUTNNQijmhaKF12ob7N1hc3vH19/lvmJ0GY5+iKdYtPVgnRNxBWCMEAKusWp3lnkF9aPf4NDB89Ku1zXZvjdVlzpmw65HP5zV7Q5FXKPW7nDfzwIoCiEEnNWp1qz59ni3xTKpl2jbxfIqjdba19jfqL+ZmX32jfClPe4wPO0bV12MAygZIQScJSp479AZPXZLDB+/YDHJ85+bunrP9xW1jcZFbGxp23Xyp6krv35xcvw9Q8Jt2ZuYaIoWSviDA96BEAKOU3Wp1x3ItiValrr4h1Eznxk/z8bydTsWbNnPtTOAMwgh4LgjeReeGDvX4Ya5ZIiUZp44K/UrAcgYIQQcJKaDYxZvlLaC+hE4L41JIeAwQgg46EBu4eNj5kheQf2kcPsPeVK/HoBcEULAQYu2HuwbECJ5BcXw9Q9ZsGW/1K8HIFeEEHBQcOpWyRNoGJ+u+Frq1wOQK0IIOGjaygzJ+2cYospSvx6AXBFCwEGLth709e8Vp0b7DQ5NyTwm9esByBUhBByUlV/01LhYySsoxvOT4nKLrkr9egByRQgBB7V2qIIS1kpeQTHGL/1S1aWW+vUA5IoQAo7blZ0/MChK2go+NjqGrycEnEEIAcdpdboDuYUDhkVIWEFOigJOIoSAUzrVmswTZ9+OTPbkmsI+fsH3fxA5ZH6amAuKGEv9GgDyRggBF7hW0xC3+dv3YlY8OjrGesMGBkU9PS7WmfFa6JKJyzZvOpTDbdUAlyCEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEkA21Rnulqq7gcgWjlw/xNok3S+p/L4CtCCFkY9OhnGcnzB8YFMXo5UO8TVuOnZb63wtgK0II2ZicnP6f709nyGKIN0vqfy+ArQghZIMQymgQQsgIIYRsEEIZDUIIGSGEkA1CKKNBCCEjhBCyQQhlNAghZIQQQjaCU7dK/vnOsHGIN0vqfy+ArQghZKPgcsWIz754NXiRYTwxdq6Vz+K/fLrA+MEmY9D0hf0Gh1radsCwCCvbOjasPN2DI6LF8di+q79OTRwYFGVpb/cMCf/btERL24oXzdc/pNsNxZ8/NS7WfJNXpi+08lKLn+vFKQnGjxdvk3izpP73AtiKEEJOVF3qptZ2w9iVnW/p0/mx0TE1TS3GDzYZDS1tw+M/t7T53E17rGzr2AiIXW3p6eLT94njsX1XdTdbZ2/YbWlvE5I21ze3Wtp236lzonbdbih6durCZfNNGlvajuRdsPR04ucqrqg2frx4m6T+lwLYgRBCxn44V2Lp0/npcbE9bm7ll46rdme5/GitPF360VP27k1sYmlvUWt3WNmwrLpeTNq63VD8ufhbS1tZejrxc4n42Xv8QO9BCCFjhJAQAs4jhJAxQkgIAecRQsgYISSEgPMIIWSMEBJCwHmEEDJGCAkh4DxCCBmTVwjHL/2SEAK9ECGEjEkewqtVdftOnRNN6nFsOHjyvz6aTQiBXogQQsakCmFpZe2CLfv/OHaOj1+wpT3YNVwbwtkbdlvZkBACJgghZEySEO7Kzn9nZkr/wDCXJNDhEG46lGNpb18ezrGyISEETBBCyJjnQ5hzvvSx0TEuTKBjIdTqdIu2HrS0tzPFZVa2JYSACUIIGfNwCPNLr/1h1EyXV9CBEIof/MUpCd3u6rXQJda3zS26+vykOEIIGBBCyJiVEA4Mijp14XLB5QpLI6+k/PWwpXaFcMryr/q46JeCtoTw0vWa5ZlHRWZMxpjFG1+eusDSrydfmBxvvonx+L/o5ZbO6xJCKBMhhIxZCaEYD4+cKeaFlsajVs9wmodQfNZb+R4ld4RwVOJ6V12MY+MghFAmQggZsx5CZ4Z5CI+dvei+AnUbwgHDIjxZQUIIxSKEkDFPhnDLsdPWN3luYlxA7GpLJyQ/XrLJyoSy2xB6uIKEEIpFCCFjngyhlXV7j4+Zk114qcejHbN4IyEEeiFCCBnrJSEclbherdH2eLT23muUEAKeQQghY54MYUZWrqUHW7+lmQEhBHonQggZ82QIc4uuWnrwezErmBE68PYBvQQhhIxZCaGPX/A7M1PenbXCynjgg0jbQ1jd2OzrH9LtgwdNX9jQ0tbj0dobwuHxn/8uINTSJn/5dIEtN/s2H9NWZvx+ePfXoxJCKBMhhIxZCeHDI2f2OEsTpbE9hMIr0xd2++Anxs4trazt8WjtDWHB5QpLzyjGgGER4gE2vlDGzpdViogSQsCAEELGPHyLtcNnzt8zJNz8wQODomxpkgNfzCue8aER0Za2eiN8qS0zURPcaxQwQQghYx4OoapLnbzjqPmDX5gUX1nX5MzTWQqhpWfUj74BIV/sP9Hj85oghIAJQggZk+RrmEora7MLL4mnNozqxmZbjtaBEAqtHSpL3RKj3+DQ82WVtjy7ASEETBBCyNiJwkuW7sbpmW+ot4tjIRS+PXXOynU9Yrc2lliPEAImCCFk7Exx2cMju/9epJenLuhxc7mEsF3VOSpxvaVt+weG2fUtToQQMEEIIWOqLvXeHwvMb+wZunpbVn5Rj5vLJYS37pwgfW5i918iKMafJszPOV9q42EQQsAEIYS8aXU68SlsMkQ2bNlWRiEU1nx73NIVpH0DQobHf27Lov5bhBAwQwihXPIKoYhNUMJaS3sQLcwrKbflMAghYIIQQrnkFULh9MUr//XRbEs7eX/2KksZM0YIAROEEMoluxB2qjUpmccs7cTHL3jZ9iM97oQQAiYIIZRLdiG8deeqmWfGz7O0n6fGxfZ4lRAhBEwQQiiXHEMoJO84amlZoa9/iN+cVDFxtLI5IQRMEEIol0xDWHezNXBemqVdibErO9/K5oQQMEEIoVwyDeGtO3cSsLKs8KUpCVbuNUMIAROEEMo1d9Oebj/ZffyCM7JyXf50oau39enuhnDi6b45fsauXam61Gv3nbBUpkdHxxRdq7K07fW6xr+HLO52wzfCl1oq6I36Jkt3swtO3drSbtPCTaB3IoRQLjGv+tu0xKfHxZqMtyOTr1TVufzpjuRdeHNGkvnTBcSuvlh+w969tXaoghLWmu9NjJELvrDy9UwiorPW7zTfSkwxEzMOWNpKrdEOnb/m2Qnzzbc6kFuo1ensPX6g9yCEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARSOEAABFI4QAAEUjhAAARft/JNJ32IQzDpgAAAAASUVORK5CYII=" width="600" height="250" class="img_ev3q"></p>
<p>I've been working on and off on a Nepali programming language with my friends
for the last few months. It's called मनसा (IAST: <em>mansā</em>) and I think it's ready
for an alpha release. If you'd like to try the language out, visit
<a href="http://mnsa.cc/" target="_blank" rel="noopener noreferrer">mnsa.cc</a> - the official website. You can play around with the
language right in the browser without having to download anything, not even a
Devanagari keyboard layout.</p>
<p>This post is a collection of random things I want to say about the language,
including how the idea came about, the interesting things I learnt making the
project, and the problems faced.</p>
<!-- -->
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-all-started">How it all started<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#how-it-all-started" class="hash-link" aria-label="Direct link to How it all started" title="Direct link to How it all started">​</a></h3>
<p>In the sixth semester, we are required to submit a team project by the end of
the term. Most teams in my class were making boring things, like hotel
management systems, or polling websites. If you get to chose your own project,
why not do something exciting and new? We settled on making a programming
language. "Why not in Nepali?", I said, and after a long debate, we settled on
building a Nepali programming language.</p>
<p>In the beginning, we thought a Nepali programming language wouldn't have any
practical use at all. We thought that all this project would ever be is a
novelty, a fun thing to play with and forget about, something like Brainfuck or
Befunge. But as we continued to look into things to include in our proposal, we
realized that a Nepali programming language might have a few very niche but very
practical uses.</p>
<p>After some more deliberation, we decided that it had to be a compiled language,
because that was the most difficult to make in terms of code, and the "coolest".
It was exciting and somewhat uncertain because we don't have Compiler
Construction classes in our syllabus, so we had basically zero idea on how we'd
proceed. And we didn't know how to work with Nepali characters in the program.
It was a great learning experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-language">The language<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#the-language" class="hash-link" aria-label="Direct link to The language" title="Direct link to The language">​</a></h3>
<p>The language is actually very tentative at this point and we're still refining
it. You should be able to get the general idea of the syntax by the small
example code below. If you don't, wait for the official documentation to be
finished. It's in the works.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/programmnsa-71466d0298cca507cea2f62e9cca8627.jpg" width="807" height="445" class="img_ev3q"></p>
<p>We have made a few changes to the conventional structure of a program statement
to make it more expressive. For example, in function calls, the name of the
function comes after the parameters, as verb comes at the end of sentence in
Nepali. So "print Something" becomes "something लेख". We similarly modified
other constructs such as conditionals and loops to fit into the Nepali grammar
structure more. Technically, it is a very small change but it really does help
make the programs more readable in Nepali. It was surprising how fluid the
language becomes by changes so simple.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-compiler">The compiler<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#the-compiler" class="hash-link" aria-label="Direct link to The compiler" title="Direct link to The compiler">​</a></h3>
<p>The compiler was written in C++ completely from scratch. I didn't want to use
lexer or parser generators because these tools hide the interesting and
complicated details. That is a good thing if your goal is to make good,
maintainable compilers but, as a student, I wanted to explore all the gory
details and learn everything I could. I should mention here that the
<a href="https://www.youtube.com/playlist?list=PLDcmCgguL9rxPoVn2ykUFc8TOpLyDU5gx" target="_blank" rel="noopener noreferrer" title="Compiler Making Lectures Alex Aiken">series of lectures by Alex Aiken</a>
is an amazing resource, and if you're planning on doing compilers too, you can
at least skim through the videos to see the big picture.</p>
<p>I used Visual Studio Code to write C++ code this time. I actually started coding
using plain old vim as always, but eventually it became so unmanageable with
files all over the place that I had to find a more manageable tool. I went with
vscode, and I'm glad I did because vscode is incredibly well made. And the c/c++
extension is so good. It apparently makes an AST for my code on the fly and
checks for all kinds of errors. I had never before used these sophisticated
tools for writing C++. I generally used vanilla sublime with vim extention, or
just command line vim. But really it's so nice. It's like discovering geysers
for the first time when you've been showering with cold water all your life
(strangely specific metaphor? sorry).</p>
<p>When writing the compiler, I used many new C++17 features. I was drawn into
modern C++ first because of constexpr which allows you to make functions that
are evaluated at compile time. I wanted to build a fast but manageable lexical
analyser using a composition of constexpr functions but I realised that I was
trying to prematurely optimize again, so I controlled myself. Maybe in version
0.2.</p>
<p>I also used C++17 lambda functions to declare nested functions to eliminate
repeated actions that are only relevant inside a specific function. Here's an
example:</p>
<div class="language-c++ codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-c++ codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">auto makeDeclNode = [&amp;](ast::astType a) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   stmt.reset(new ast::Ast);</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   astNode declaration;</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   if (declaration = declList()) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      stmt-&gt;type = a;</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      stmt-&gt;left = std::move(declaration);</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   } else</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      errQuit("declarations");</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">};</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">if (accept(lexer::tokenType::_int)) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   makeDeclNode(ast::astType::_intDecl);</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">} else if (accept(lexer::tokenType::_str)) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   makeDeclNode(ast::astType::_strDecl);</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">} else if (accept(lexer::tokenType::_bool)) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   makeDeclNode(ast::astType::_boolDecl);</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Maybe it's because I've coding a lot in javascript these days, but nested
functions feel like an important language feature to have. मनसा has nested
function support too.</p>
<p>I also tried to use C++ smart pointers everywhere. They make memory management
so pleasant and take away most of the issues I used to deal when using raw
pointers. But I did find the lack of good observer pointer idiom annoying and
dangerous. Maybe they'll make it better by C++20, but hopefully I'll already be
using Rust by then.</p>
<p>In v0.1, I have only implemented the lexer, parser, semantic analyzer and a
rudimentary code generator with emits C++ code. In the new versions, I will
progressively add new modules like optimizer, and redo some old ones.</p>
<ol>
<li>
<p>The <strong>Lexical Analyser</strong> is a simple finite state machine which iterates over
each each UTF8 encoded character and converts them into tokens. I learnt a
lot about Unicode while making the lexer. I am interested in world languages
and scripts, so reading the Unicode documentation and other articles was
fascinating to me. If you're interested in languages too, I cannot recommend
at least skimming through
<a href="http://www.unicode.org/versions/Unicode12.0.0/UnicodeStandard-12.0.pdf" target="_blank" rel="noopener noreferrer" title="the Unicode Standard">the Unicode Standard</a>
enough. If you're in love with writing scripts like I am, do read
<a href="https://www.smashingmagazine.com/2010/05/the-beauty-of-typography-writing-systems-and-calligraphy-of-the-world/" target="_blank" rel="noopener noreferrer">this article</a>
on Smashing Magazine. I have written about Unicode in another
<a href="https://nirav.com.np/2019/10/16/on-the-nepali-language-and-unicode-1.html" target="_blank" rel="noopener noreferrer">blog post</a>
so maybe also check that out.</p>
<p>The encoding of Unicode characters is also a fascinating topic. I find UTF-8
particularly beautiful. And as it turns out, it was designed by
<a href="http://doc.cat-v.org/bell_labs/utf-8_history" target="_blank" rel="noopener noreferrer">Ken and Rob</a> from Bell Labs.
I'm a big fan of the Bell Labs people.</p>
</li>
<li>
<p>I wrote the <strong>Parser</strong> using the Recursive Descent algorithm. It's crazy how
simple yet powerful Recursive Descent is. I learnt it using only the
<a href="https://en.wikipedia.org/wiki/Recursive_descent_parser" target="_blank" rel="noopener noreferrer">Wikipedia article</a>,
wrote my first parser in a weekend, and it works like magic. It's just so
elegant. In the current code base, the parser takes up the most volume at
about a thousand lines. But I do believe that I should have mixed in some
Pratt parsing to parse the operators, because recursive descent has to make a
lot of function calls even for trivial tasks, which makes it inefficient. Oh
well, maybe next time.</p>
<p>The Parser makes an AST. Because the AST is vital, I wrote some routines to
generate actual pictures from the AST. I've detailed the process in
<a href="https://nirav.com.np/2019/12/08/visualize-c-data-structures-using-graphviz-and-dot-language.html" target="_blank" rel="noopener noreferrer">another blog post</a>
but this is what the AST's visualization looks like:</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/astgraph1-fc3aa657d7190b6b8fd5e1e2882f43b5.png" width="545" height="1051" class="img_ev3q"></p>
</li>
<li>
<p>The <strong>Semantic Analyser</strong> is all about recursively getting to all nodes in
the AST and checking their types and making sure everything is according to
rules.</p>
</li>
<li>
<p>I had to write my own <strong>Symbol Table</strong>, which was awesome because I got to
play with STL containers like pairs and unordered maps. Once you discover
these tools, you can never go back to hand-coding data structures (which I'll
admit was stupid, but I'm slowly fighting my not-invented-here syndrome).</p>
</li>
<li>
<p>The actual <strong>Code Generator</strong> is not done yet. In it's place is a simple
function which recursively navigates the AST and generates C++ code. For
variable names, I just base64 encoded all Devanagari identifiers and replaced
the illegal characters in base64 with underscore. The generated code looks
like this:</p>
</li>
</ol>
<div class="language-c++ codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-c++ codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">int main(){</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   auto v4KSo4KSv4KS_pX_pCksuCkvuCkh_pCkqATT1 = [&amp;]() {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      cout &lt;&lt; "\n";</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   };</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   int v4KSG4KSH = 100;</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   string v4KSV4KWB4KSw4KS_p = "नमस्ते";</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   while  (v4KSG4KSH &gt; 0) {</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      cout &lt;&lt; v4KSV4KWB4KSw4KS_p;</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      v4KSo4KSv4KS_pX_pCksuCkvuCkh_pCkqATT1();</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      v4KSG4KSH= (v4KSG4KSH - 10) ;</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">   };</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-website">The Website<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#the-website" class="hash-link" aria-label="Direct link to The Website" title="Direct link to The Website">​</a></h3>
<p>Making the website was like a pleasant stroll in the morning sun. It was not
particularly challenging. I used Adobe XD to make a prototype and then designed
it with vanilla CSS. I decided that unless there's an online compiler a website
for a programming language is no use. I also fell in love with
<a href="https://www.haskell.org/" target="_blank" rel="noopener noreferrer">Haskell's online shell</a>. But making it was going to
be difficult.</p>
<p>I used vanilla javascript, socket.io library and Codemirror to make the compiler
part. Learning to write the syntax highlighting was somewhat complicated so I
just modified a preexisting one. I wanted anybody with a computer or a mobile
phone to be able to go in, type code and try it out. So I also made an
in-browser keyboard layout switcher which reads input keys and converts them to
Nepali based on
<a href="https://nirav.com.np/2020/02/07/an-easier-nepali-keyboard-layout.html" target="_blank" rel="noopener noreferrer">this</a>
keyboard layout, which we also made. I have yet to make the keyboard work on the
phone, but I'm so busy these days that I don't yet have the time.</p>
<p>Then I made a nice keyboard layout switching drawer that I love to play with.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/mnsakeyboardpop-588f07760f977702e9eb59e61ac2c6cc.gif" width="589" height="250" class="img_ev3q"></p>
<p>I apologize for the low quality GIF. I had to run the screen recording through
so many online converters that all compressed the original in some form or
another that now it looks like it came straight from early 2000s.</p>
<p>The backend part is also interesting, but it still needs lots of work. I
basically instantiated a linux server on Azure and ran a simple NodeJS program
on it which listens to socket.io requests for programs in मनसा, compiles the
program, runs it in a sandbox, and pipes the input and output to the web
terminal. I have put some primitive rate limiting and protections in the code
but at some point I intend to use recaptcha or something to that effect to guard
the API. I might also look to use cloud functions instead of running a full
linux box all the time. I wrote a blog post documenting a part of the process
<a href="https://nirav.com.np/2019/10/08/sandboxing-small-executables-on-linux-many-tries.html" target="_blank" rel="noopener noreferrer">here</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-ide">The IDE<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#the-ide" class="hash-link" aria-label="Direct link to The IDE" title="Direct link to The IDE">​</a></h3>
<p>I've hated ElectronJS with a passion I only reserve for a few things in life
(like
<a href="https://nirav.com.np/2018/03/09/the-cursed-child-sucks.html" target="_blank" rel="noopener noreferrer">the Cursed Child</a>)
The hate is a result of a few factors. I use a 6 year old Dell laptop as my
computer which is so dilapidated at this point that it stutters when I have lots
of chrome tabs and VScode running at the same time. So I appreciate parsimony
from the developer's side. I'm also kind of annoyed at this developer-first
culture we developers are promoting, piggybacking simply on the fact that
computers are getting faster and with more memory than before.</p>
<p>But then the night before a major demonstration of the project I was in such a
rush because I had so many things to make and refine, that I broke all my rules
and made a deal with the devil itself. <em>Oh mighty devil, oh accomplice of the
photon, oh sinful chimera of chromium and nodejs, oh gods of chaos and
asynchronicity, I implore you.</em></p>
<p>Anyway, the results were astounding. In about three hours, I had a perfectly
working syntax-highlighting enabled (thanks again, CodeMirror), beautiful IDE
for demonstration. It could compile and run the code and upload it to Arduino
too (with some avrdude magic, of course). ElectronJS is incredibly fast and
simple (for the developer, at least). Even though the reasons for hating
ElectronJS are still valid, I got a new perspective by actually working on it,
and I've added it into my toolbox. Thank you, ElectronJS, for taking me back to
my childhood days of Visual Basic and RAD.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-arduino-interface">The Arduino interface<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#the-arduino-interface" class="hash-link" aria-label="Direct link to The Arduino interface" title="Direct link to The Arduino interface">​</a></h3>
<p>मनसा can also write code for Arduino. The idea came when I was trying to teach
my cousin (who's 12) this programming language. I realized that it's difficult
to get a kid to relate to the world inside the computer. For example, when
teaching the concept of looping for the first time, it's way easier to show him
a led blinking 10 times and explain the code than to show him ten instances of
'Hello World'.</p>
<p>So I added in some features to the language, mainly the <code>external</code> mechanism
which allows you to write C code inside मनसा functions. The resulting system is
kind of hacky but surprisingly flexible. The embedded C code does most of the
register twiddling and bit flipping, and exposes high level functions to मनसा.
That code is written as library. Then, using the import mechanism of the
language, you can import these functions and access them like normal मनसा
functions. I will put in a video demonstration when I have the time.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="random-interesting-observations">Random, interesting observations<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE#random-interesting-observations" class="hash-link" aria-label="Direct link to Random, interesting observations" title="Direct link to Random, interesting observations">​</a></h3>
<ol>
<li>It's nice to have a small code diary, if you will, to jot down all complex
ideas that you think up while coding. I made a <code>diary.md</code> file on the root of
the source tree to keep a chronological log of my thoughts, snippets of
codes, things I had to do next, of bugs and other things in the file.</li>
<li>C++11 range based loops are awesome. I know about these before.</li>
<li>Makefiles get very sloppy very fast and annoying to maintain. I must learn to
use more sophisticated build system soon. Maybe Cmake? The build system
should be able to build on both Linux and on WSL, install all required
programs if they don't exist, and only compile the libraries that actually
changed.</li>
<li>Most of the 3000+ lines of code I've written is worthless. I read somewhere
lines of code are not investments, rather they are loans. The more you add to
the codebase, the more expensive you make it to maintain it. It takes more
time for a prospective contributor to make sense of the whole project. The
more lines you write, the more bugs you hide. I would have been far far
better using a parser generator and making the language interpreted instead
of compiled. That would reduce complexity of the system and let me focus on
the big picture and on the applications of the language.</li>
<li>At some point, you <em>really</em> need a second, vertical monitor.</li>
<li>Compiling larger code bases takes far more time than you expect.</li>
</ol>]]></content:encoded>
            <category>project</category>
        </item>
        <item>
            <title><![CDATA[Visualize C++ Data Structures using Graphviz and the DOT language]]></title>
            <link>https://bynirav.com/blog/visualize-cpp-data-structures</link>
            <guid>https://bynirav.com/blog/visualize-cpp-data-structures</guid>
            <pubDate>Sun, 08 Dec 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Data structures help structure and organize data effectively, and provide]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/browntrunk-12570d4364e77cc392cee1043f9519fb.jpg" width="1918" height="1279" class="img_ev3q"></p>
<p>Data structures help structure and organize data effectively, and provide
several abstracted operations on the data. They are elegant and convenient, and
computer scientists love to use them. Implementing these data structures in the
computer require the programmer to flatten the structure into a one-dimensional
model using pointers or references because the memory is actually arranged as a
one-dimensional run of data elements.</p>
<p>It is often necessary to inspect the data structure in debugging and program
verification phases. But some data structures happen to be particularly
graphical, in that they have multiple associations and elaborate hierarchies or
layers. Think of a Rope or a Graph. Due to many associations between nodes, it's
not possible to properly display the graph on the terminal.</p>
<!-- -->
<p>I recently ran into such problem, and found an interesting solution. In this
post, I will try to document it. I've written mainly about the Abstract Syntax
Tree in this post, but it should be trivial to translate it to any other
deterministically traversable data structure.</p>
<p>I'm currently working on writing a compiler for my own Nepali programming
language. The front-end part of a compiler converts the program code into a data
structure called AST. AST, or Abstract Syntax Tree, is a tree-based
representation of the source code. It's much more suitable to further
transformations in the semantic analysis, optimization and code generation
phases.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/wikiast-7d9ce22c9f75fdf3cdd7daaf6c71d30d.svg" width="1147" height="1294" class="img_ev3q"></p>
<p><em>This picture of Abstract Syntax Tree taken from Wikipedia page on AST</em></p>
<p>But AST is also an incredibly complex data structure. It has to store a bunch of
information and maintain a tree structure. It is not immediately obvious how one
might present it on the terminal screen. Several ideas to exist, but they don't
scale well. Two solutions that I thought up were:</p>
<ol>
<li>Print in the terminal</li>
<li>Unparse the AST back to source code.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="unparse-the-ast-back-to-source-code">Unparse the AST back to source code<a href="https://bynirav.com/blog/visualize-cpp-data-structures#unparse-the-ast-back-to-source-code" class="hash-link" aria-label="Direct link to Unparse the AST back to source code" title="Direct link to Unparse the AST back to source code">​</a></h2>
<p>The AST is a lossless transformation of the source code as far as intent is
concerned. So it should be possible to go the other direction and retrieve the
source code back from the AST. If the AST doesn't have any errors, then it's
unparsing should result in code that's nearly identical to the original source
code. This step is also essential when trying to verify compiler correctness.</p>
<p>I'm going to have to explore this option further in the future. But because this
method doesn't allow me to directly observe the AST at several stages of the
compilation process, I didn't use this.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="print-in-the-terminal">Print in the terminal<a href="https://bynirav.com/blog/visualize-cpp-data-structures#print-in-the-terminal" class="hash-link" aria-label="Direct link to Print in the terminal" title="Direct link to Print in the terminal">​</a></h2>
<p>I had written a compiler for my minor project in my 6<sup>th</sup> semester but
the language it accepted was very basic. So, back then, I got away with simply
printing the tree in the terminal. For example, this code</p>
<img src="https://bynirav.com/assets/images/ide-ffee7e56dee51a21e12c90c63cf1932f.png" class="img-60p">
<p>generates this AST:</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/term-383c1ab7c6dc0ca1e93d2d77aafe1477.png" width="1104" height="586" class="img_ev3q"></p>
<p>The AST is printed in the terminal rotated 90° counter-clockwise such that the
root of the tree is at the bottom-left. This was served me well at the time.
Frankly, for a language that didn't even have an else if clause, there's are
limited ways to complicate the AST other than by writing longer code.</p>
<p>But the language I'm working on right now is extensive. And so the tree it
creates is immense. I had to come up with some other way to analyse the AST.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="enter-graphviz">Enter Graphviz<a href="https://bynirav.com/blog/visualize-cpp-data-structures#enter-graphviz" class="hash-link" aria-label="Direct link to Enter Graphviz" title="Direct link to Enter Graphviz">​</a></h2>
<p>Brian Kernighan has given an
<a href="https://www.youtube.com/watch?v=Sg4U4r_AgJU" target="_blank" rel="noopener noreferrer" title="Brian Kernighan's talk on successful computer language design">amazing talk</a>
on successful language design, where he also talked about Pic, a language he
designed for specifying graphs. I was immediately taken by the idea because this
was a much better way to make graphs than the clumsy touchpad.</p>
<p>Well, Brian's Pic is antiquated now, but <a href="http://www.graphviz.org/" target="_blank" rel="noopener noreferrer">Graphviz</a>
does the same kind of thing. Graphviz uses the DOT graph specification language.
DOT is extremely simple. It literally takes 5 minutes to be able to make nearly
any graph you want. For example, consider the DOT code below</p>
<div class="language-graphviz codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphviz codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">digraph any_other_name{</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    Brahma-&gt;Ram</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    Brahma-&gt;Hari</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    Ram-&gt;Tom</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    Hari-&gt;Dick</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    Hari-&gt;Harry</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>It produces the Graph:</p>
<img src="https://bynirav.com/assets/images/graph1-d519b8e7707e6dfa80b116a0872e365a.png" class="img-60p">
<p>If you're interested, you should try some online Graphviz software to get the
hang of it. I used
<a href="https://dreampuf.github.io/GraphvizOnline/" target="_blank" rel="noopener noreferrer" title="online graphviz">this one</a> but
there are a lot of choices one web search away.</p>
<p>I can only imagine how many hours this thing could have saved me the previous
semester when I was stuck making elaborate graphs for my minor project report
and presentation.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="generating-the-dot">Generating the DOT<a href="https://bynirav.com/blog/visualize-cpp-data-structures#generating-the-dot" class="hash-link" aria-label="Direct link to Generating the DOT" title="Direct link to Generating the DOT">​</a></h3>
<p>Generating the DOT for Graphviz is generally trivial. For linked list, a
recursive function such as the one below suffices (for c++):</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">void</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">printElement</span><span class="token punctuation" style="color:black">(</span><span class="token plain">listElement</span><span class="token operator" style="color:black">*</span><span class="token plain"> el</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> nodeNumber</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  string DOT</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  DOT </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">nodeNumber</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label="</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  DOT</span><span class="token operator" style="color:black">+=</span><span class="token plain"> el</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">name</span><span class="token operator" style="color:black">+</span><span class="token string" style="color:red">"\"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">el</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">right</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    DOT </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">nodeNumber</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    DOT </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">nodeNumber</span><span class="token operator" style="color:black">+</span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">printElement</span><span class="token punctuation" style="color:black">(</span><span class="token plain">el</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">right</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> nodeNumber</span><span class="token operator" style="color:black">+</span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> DOT</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>It is a little more complex for the AST. Because trees are recursive structures,
it's easy to write elegant recursive functions that process the trees. In this
case, the <code>genDOT(astNode,bool)</code> function helps recursively descend the AST
tree, and print out it's nodes.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> rootNum </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">void</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">Parser</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:red">"digraph G{\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:red">"graph[fontname=Rajdhani, color="</span><span class="token plain">#</span><span class="token number" style="color:red">242038</span><span class="token string" style="color:red">"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:red">"node[fontname=Rajdhani, color="</span><span class="token plain">#</span><span class="token number" style="color:red">242038</span><span class="token string" style="color:red">", shape=square]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:red">"edge[fontname=Rajdhani, color="</span><span class="token plain">#</span><span class="token number" style="color:red">242038</span><span class="token string" style="color:red">"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">root</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token boolean" style="color:red">false</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> </span><span class="token string" style="color:red">"}\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">void</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">Parser</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">astNode </span><span class="token operator" style="color:black">&amp;</span><span class="token plain">n</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">bool</span><span class="token plain"> isLeft</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  std</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">string print</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// DOT for current node</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  print </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=&lt; &lt;B&gt;"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain">   </span><span class="token function" style="font-weight:bold;color:black">translateTypeStr</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"&lt;/B&gt;"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token function" style="font-weight:bold;color:black">translateDataStr</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">!=</span><span class="token plain"> </span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"&lt;BR/&gt;"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">translateDataStr</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" &gt;"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">" &gt;"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">isLeft</span><span class="token punctuation" style="color:black">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">", color="</span><span class="token plain">#FF595E</span><span class="token string" style="color:red">", fontcolor="</span><span class="token plain">#FF595E</span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">", color="</span><span class="token plain">#</span><span class="token number" style="color:red">274690</span><span class="token string" style="color:red">", fontcolor="</span><span class="token plain">#</span><span class="token number" style="color:red">274690</span><span class="token string" style="color:red">""</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type </span><span class="token operator" style="color:black">==</span><span class="token plain"> ast</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">astType</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">numericConstant </span><span class="token operator" style="color:black">||</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type </span><span class="token operator" style="color:black">==</span><span class="token plain"> ast</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">astType</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">stringConstant </span><span class="token operator" style="color:black">||</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type </span><span class="token operator" style="color:black">==</span><span class="token plain"> ast</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">astType</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">boolConstant</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">", shape=egg"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> rootNumBackup </span><span class="token operator" style="color:black">=</span><span class="token plain"> rootNum</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  rootNum</span><span class="token operator" style="color:black">++</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type </span><span class="token operator" style="color:black">==</span><span class="token plain"> ast</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">astType</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">_if</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">cond</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=condition]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">cond</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_if</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=if]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_if</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_elseIf</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=elseif]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_elseIf</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_else</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=else]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_else</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">type </span><span class="token operator" style="color:black">==</span><span class="token plain"> ast</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">astType</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">_while</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">cond</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=condition]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">cond</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_if</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=do]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">_if</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">left </span><span class="token operator" style="color:black">||</span><span class="token plain"> n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">right</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">left</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [color="</span><span class="token plain">#FF595E</span><span class="token string" style="color:red">"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">left</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=x]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      rootNum </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">right</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [color="</span><span class="token plain">#</span><span class="token number" style="color:red">274690</span><span class="token string" style="color:red">"]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        </span><span class="token function" style="font-weight:bold;color:black">genDOT</span><span class="token punctuation" style="color:black">(</span><span class="token plain">n</span><span class="token operator" style="color:black">-&gt;</span><span class="token plain">right</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token boolean" style="color:red">false</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">else</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">" [label=x]\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">        print </span><span class="token operator" style="color:black">+=</span><span class="token plain"> </span><span class="token string" style="color:red">"n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNumBackup</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"-&gt;n"</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">          </span><span class="token function" style="font-weight:bold;color:black">to_string</span><span class="token punctuation" style="color:black">(</span><span class="token plain">rootNum</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> </span><span class="token string" style="color:red">"\n"</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  cout </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> print </span><span class="token operator" style="color:black">&lt;&lt;</span><span class="token plain"> endl</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Of course, this is not the complete code. It only covers if and while loops, but
not function bodies and other blocks. But this is the essence. Funnily enough, I
spent less time writing code to actually generate the graph than I spent trying
to make it look cooler. But given how much time I'm going to have to stare at
and navigate these graphs, I think the it was worth the effort.</p>
<p>The <code>rootNum</code> keeps track of the parent node at each recursion. The parent node
needs to point to all it's the children, and <code>rootNum</code> helps keep track of the
that. The <code>genDOT()</code> function is simply the public interface which first prints
out the necessary DOT boilerplate and then calls the main <code>genDOT(astNode,bool)</code>
function. The <code>genDOT(astnode,bool)</code> function recursively prints out all the DOT
code. Here's the kind of DOT code it produces:</p>
<div class="language-dot codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-dot codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">digraph G{</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    graph[fontname=Rajdhani, color="#242038"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    node[fontname=Rajdhani, color="#242038", shape=square]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    edge[fontname=Rajdhani, color="#242038"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n3 [label=&lt; &lt;B&gt;Declare Var&lt;/B&gt;&lt;BR/&gt;नाम &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n2 [label=&lt; &lt;B&gt;chain&lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n2-&gt;n3 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n5 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n2-&gt;n5</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n1 [label=&lt; &lt;B&gt;Declare String &lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n1-&gt;n2 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n6 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n1-&gt;n6</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n10 [label=&lt; &lt;B&gt;dataEl&lt;/B&gt;&lt;BR/&gt;नाम &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n12 [label=&lt; &lt;B&gt;string&lt;/B&gt;&lt;BR/&gt;नीरब &gt;, color="#274690", fontcolor="#274690", shape=egg]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n9 [label=&lt; &lt;B&gt;=&lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n9-&gt;n10 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n9-&gt;n12 [color="#274690"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n17 [label=&lt; &lt;B&gt;string&lt;/B&gt;&lt;BR/&gt;नमस्ते मालिक &gt;, color="#FF595E", fontcolor="#FF595E", shape=egg]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n16 [label=&lt; &lt;B&gt;chain&lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n16-&gt;n17 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n19 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n16-&gt;n19</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n15 [label=&lt; &lt;B&gt;FunctionCall&lt;/B&gt;&lt;BR/&gt;लेख &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n15-&gt;n16 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n20 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n15-&gt;n20</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n14 [label=&lt; &lt;B&gt;Statement&lt;BR/&gt;3&lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n14-&gt;n15 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n21 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n14-&gt;n21</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n8 [label=&lt; &lt;B&gt;If&lt;/B&gt; &gt;, color="#FF595E", fontcolor="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n8-&gt;n9 [label=condition]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n8-&gt;n14 [label=if]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n7 [label=&lt; &lt;B&gt;Statement&lt;BR/&gt;2&lt;/B&gt; &gt;, color="#274690", fontcolor="#274690"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n7-&gt;n8 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n25 [label=x]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n7-&gt;n25</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n0 [label=&lt; &lt;B&gt;Statement&lt;BR/&gt;1&lt;/B&gt; &gt;, color="#274690", fontcolor="#274690"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n0-&gt;n1 [color="#FF595E"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    n0-&gt;n7 [color="#274690"]</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>After the code was working, I wrote a Makefile that saves the output, generates
a PNG image of the graph and opens that image in the feh image viewer.</p>
<div class="language-make codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-make codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">test_ast: parser/parser.C parser/parser.h tests/parser/parser.C lexer/lexer.C lexer/token.C lexer/characters.C</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    $(CC) $(CFLAGS) parser/parser.C parser/ast.C parser/helper.C tests/parser/parser.C lexer/characters.C lexer/token.C lexer/lexer.C file_handler/file_handler.C -o tests/parser/parser.out</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    @echo "Starting Parser Test"</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    @echo</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    @tests/parser/parser.out &gt; .graph</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    dot -Tpng &lt; .graph &gt; .png</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    feh .png</span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    @echo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This makefile simply redirects the DOT output from STDOUT to a file, and uses
the graphviz program <code>dot</code> to generate a image that can be opened with feh.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="results">Results<a href="https://bynirav.com/blog/visualize-cpp-data-structures#results" class="hash-link" aria-label="Direct link to Results" title="Direct link to Results">​</a></h2>
<p>After the set up, the whole thing just fit into my workflow.</p>
<!-- -->
<video controls="" loop="" muted=""><source src="/assets/medias/graphvizdemo1-a896c862bce0aad67249c7a998efba6e.mp4" type="video/mp4"></video>
<p>Here's an example graph generated from the makefile.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/astgraph1-fc3aa657d7190b6b8fd5e1e2882f43b5.png" width="545" height="1051" class="img_ev3q"></p>
<p>So the next time you're trying to debug or inspect a complex data structure or a
tangle of pointers, try taking some time out to write code which generates DOT
so that you can inspect the graph. I tell you, a picture <em>is</em> worth a thousand
words. The AST below is worth much more:</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/astgraph2-0c10331c08cf771206661c7da5c3d953.png" width="3898" height="3140" class="img_ev3q"></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Daydream]]></title>
            <link>https://bynirav.com/blog/how-to-daydream</link>
            <guid>https://bynirav.com/blog/how-to-daydream</guid>
            <pubDate>Mon, 04 Nov 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[In the classroom, the teacher drones on and on in his maroon colored t-shirt]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/beautiful-blooming-blossom-374134-5ea7f9202bc3e73da9a0d37ece13b61d.jpg" width="1280" height="853" class="img_ev3q"></p>
<p>In the classroom, the teacher drones on and on in his maroon colored t-shirt
that doesn’t suit him. His empty vibrations ripple through out the room,
bouncing off the glass windows shut tight against the summer breeze, mixing with
the clickety-clack of the ceiling fan to create a subtle dissonance, and
stretching indefinitely and interminably in time and in space.</p>
<!-- -->
<p>The only consolation, the only medicine is a certain girl who is facing a
certain degrees away from that maroon-T-shirt-wearing teacher; looking into the
window-pane with a certain temperament; certainly thinking of beautiful thoughts
about who knows what. Yes, that girl between two other girls in the second
bench. We will call her Sabina because she is also the unintentional witch who
ensnared my lonely heart with no intention of ever doing so, not knowing that
that intentlessness was the strongest incantation.</p>
<p>That girl, with her pretty red cap and her long neck, has set up an irrevocable
residence in the little part of my heart where I plant roses and other flowers.
It is of little consequence that she probably keeps me in a humdrum study table
of her heart in a small unimportant box where she keeps her useless pencils-that
is if she keeps me at all. When I dream of her, I find myself in an
incomprehensible universe where I am without ground or sky, the angry stars
murmur and roar; where she is the absolute and unequivocal queen of the cosmos
such that when she walks the space ripples in her feet and inside her
incomprehensible home is the absolute pool of swirling rainbows and sweet water
where she lounges with her grandmother. Where she fills me up with the eternal
promise of fragrant flowers of all colors and emotions. It is of little
consequence that most likely she doesn’t even dream of me.</p>
<p>Yes her. We will daydream about her today. We will first pretend that we are
secret artists and that we possess all the curves that exist in the universe. We
will then pretend to draw her profile with the expert application of those
curves which flow gracefully out of the pencil oddly sharpened with a knife and
tucked in our ears when not in use, while in reality we are just absentmindedly
writing her name and circling it repeatedly with a dazed, upward gaze. We will,
in our reverie, first draw her nose. The small inward curve beneath the
brow-ridge, followed by a beautiful nose - made with two curves: the first
subtly bumps upward and falls, then the next smoothly turns from the tip to the
philtrum. Then we draw the lips gently, as though we are carefully tracing it’s
outlines without daring touch the flesh. We then continue on to draw her chin,
then with one fluid line we conjure her jaw, then her small, pretty ear. We
continue on in this fashion, drawing her hair, and her shirt’s collar and what
not. The result is a beautiful picture of a beautiful girl, which is, naturally,
to be expected seeing how we are secret artists who possess all the curves in
the universe.</p>
<p>After the picture is drawn, we will imagine tearing it off our notebook and keep
it inside our shirt right next to our beating heart that pumps red hot blood
through our body and skips a beat when it hears her name.</p>
<p>Now, because this is a daydream, and we are the sole masters of the events that
unfold in this contrived sphere, we will engineer the circumstances so that in
the recess, as we enter the classroom engrossed in our secret artistic thoughts,
she happens to be walking out perhaps agitated by a similarly beautiful
preoccupation, such that the scene resolves itself in a mild collision, a whiff
of the intertwining fragrances of her shampoo, of her hair, and of her skin; a
little bit of that summer breeze; and my own unwittingly committed blunder that
allows that little piece of paper to find a way away from my heart and out of
the shirt, where it traces a flourish in that thin summer breeze to land right
next to her feet.</p>
<p>By pure chance she looks down and notices the prettiest curves of the universe
which we had employed to trace the profile of the prettiest girl in the
universe. She realizes the lines, plucked from a rose for her ears, borrowed
from a butterfly for her nose, and taken from the celestial darkness with an
astral sprinkling for her eyes - could only have been drawn by someone in love.
But because we are ourselves secret artists and because we like for it to stay
that way, we have no choice but to grab her by the wrist, and guide her through
between the various bodies and obstacles to a private spot in the staircase
which leads to the terrace but which is currently blocked, thus forming a sort
of staircasey cul-de-sac. There we look into her radiant eyes and say that we
like her very much and so on and so forth until she looks right into our eyes
too and smiles that bemused smile that says she has understood everything that
hasn’t yet been said and says something back but we can’t hear it because now
the maroon-T-shirt-wearing teacher has stopped producing those turbulent
vibrations to focus his ugly energy into spotting the inattentive students and
remarking on their inattentiveness. With our head back in the classroom, we
realize that the notebook page is covered with various instances of her name in
various sizes and with various flourishes, so we must first take care of that.</p>
<p>Then we borrow a book from the guy behind us and try to make sense of whatever
the hell is being taught.</p>]]></content:encoded>
            <category>writing</category>
        </item>
        <item>
            <title><![CDATA[On the Nepali Language and Unicode]]></title>
            <link>https://bynirav.com/blog/nepali-language-and-unicode</link>
            <guid>https://bynirav.com/blog/nepali-language-and-unicode</guid>
            <pubDate>Wed, 16 Oct 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[The Nepali language gets very little representation on the internet. Take, for]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/old_linotype-273d769a705fdfd06fe729edad33ce23.jpg" width="1279" height="853" class="img_ev3q"></p>
<p>The Nepali language gets very little representation on the internet. Take, for
example, the Nepali Wikipedia which has about 33 thousand articles. The
Esperanto Wikipedia boasts 8 times that number (at around two hundred thousand
articles), which is kind of sad, because Esperanto is an artificial language
created by <strong>one</strong> person in the 19th century. It is spoken by a meager 2
million people worldwide. Compare this to the Nepali language, which has more
than 25 million speakers.</p>
<!-- -->
<p>It's as they say, “whoever controls the media controls the mind”. And the media
of the 21st century, the internet, is so desperately out of Nepali's hands that,
not only do we read the news, articles, the weather, and novels in English, but
we go on to caption our photos of warm, intimate moments in English. Our pop
culture is stuffed full of references to Hindi media. My little brother, who is
not even 10, will sniff my phone from a mile away and hide out in some corner to
watch Motu Patlu on YouTube. He might not be as fluent in Hindi as he is in
Nepali. But in his little world, Hindi is the language that superheroes speak.
And Nepali? Only his annoying brother.</p>
<p>I'm not saying that I'm any better. If anything, I'm far worse. I'm one of those
people who, after being told a phone number, says, "Okay, repeat that. But in
English". Ask me to translate this very post to Nepali and watch how fast I run
away. My friends are, frankly, no better.</p>
<p>The problems are much worse for other languages of Nepal. The Newari Language is
listed by UNESCO as being “definitely endangered”. The Kusunda language has
speakers in single digit numbers, which is particularly unfortunate because
Kusunda happens to be a language isolate, so once it’s gone, we’ll lose any
chance of accurately reconstructing it. Half of the 123 languages of Nepal are
endangered.</p>
<p>In this post, I will talk about Unicode for Nepali language in hopes that I can
shed some technical light on Unicode in Nepali context for the uninitiated. The
idea is to let interested people know of the tools and ideas in Unicode,
specially in context of the Nepali language to encourage adoption and usage.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="some-background">Some background<a href="https://bynirav.com/blog/nepali-language-and-unicode#some-background" class="hash-link" aria-label="Direct link to Some background" title="Direct link to Some background">​</a></h2>
<p><em>Note: The numbers starting with ‘0x’ and 'U+' are Hexadecimal numbers. 'U+'
prefix additionally implies that the number following it is a Unicode code
point.</em></p>
<p>Computers fundamentally think in numbers. To a computer, a picture is a 2d
matrix of color intensity at each pixel as recorded by the camera. An audio
recording is, similarly, a sequence of amplitudes of a sound wave recorded
several thousand times each second. It goes without saying that text is also
read by the computer as a sequence of numbers.</p>
<p>Of course, what the numbers mean to the computer is entirely dependent on the
program that reads the data. In case of a picture, the numbers are used to vary
the brightness of color elements on the monitor. For an audio, the data sequence
is used to proportionally adjust the voltage across the speaker coil, which
causes the membrane to vibrate and create sound. For text, these numbers will be
used to do a wide variety of task. If you’re typing, numbers corresponding to
the alphabets you press will be stored in the memory. These numbers will be used
to look up characters inside the font file, which stores a visual glyph for each
displayable number. That will be drawn on the screen (after many more steps).</p>
<p>So, it seems that for the computer system to support text at all, characters
will have to have a standardized mapping to numbers. If the font file and the
keyboard don’t agree on what the number 65 is, then the wrong character will be
displayed on the monitor.</p>
<p>ASCII is the standard mapping of these numbers to characters. It assigns the
numbers from 0 to 127 to English alphabets and symbols. Because the early
development of computers was centralized in the US and UK, ascii encoding became
the primary method of text representation on computers.</p>
<p>Computers almost universally store data in blocks of 8 bits (a byte) which can
represent 256 numbers (28). ASCII only uses half of that (128 characters). So,
with ASCII, half of the representational space of a byte goes unused. There have
been several extensions to ASCII which make use of the unused space from 128
to 255.</p>
<p>So how do you type Nepali in ASCII? Well, you don't. ASCII is, by its very
definition, American. In the early ‘90s, Bureau of Indian Standards came up with
its very own encoding scheme called ISCII. ISCII is an extension of ASCII, so it
retains all characters from ASCII in their rightful place. From 128 to 255, it
stores characters used in the languages of India. Interestingly, ISCII actually
unified a bunch of similar scripts like Devanagari, Tamil, Bengali, and Oriya.
So, a number 164 (0xA4) in ISCII can mean all of the following: अ, அ, অ, ଅ and
more. The idea was that, since all these scripts are descendants of the same
Brahmi script, they behave similarly and represent similar sounds, which is
true, so all four of the above letters represent the same /ʌ/ sound.</p>
<p>To switch between scripts in ISCII, you just change the fonts rendering the
numbers. If a Devanagari font is selected, computer displays Devanagari
characters. If a Tamil font was selected, it displays the same text in Tamil.
The equivalent for English language would be to do assign numbers to the 26
English alphabets, and switch cases by changing fonts. The phonetic information
stays the same but the representing characters seem different. ISCII used a
special ATR byte to specify which script the fragment of text was in. ISCII is
important historically, because Unicode specification for Devanagari and other
Indic scripts is based almost entirely on ISCII. The ATR byte was not adopted by
Unicode because font attributes are not a part of Unicode.</p>
<p>In Nepal, however, the government didn't initiate any efforts. What I think
happened instead was that people or groups (like Muni Shakya) independently
assigned the 256 numbers to various characters and ligatures. Which character a
specific number represented was completely up to the font you chose. That must
have been messy. Fonts are meant to change how the text looks, not what it
represents!</p>
<p>The table below shows the character mapping of two Nepali fonts from the late
‘90s. You’ll notice how same field of the tables doesn’t encode the same
character. Both learning to type in these fonts and changing the fonts must have
been an inconvenience.</p>
<p><img decoding="async" loading="lazy" alt="unicodenepalione.png" src="https://bynirav.com/assets/images/unicodenepalione-3748267cb417ade7003bed3b41bc08d1.png" width="939" height="717" class="img_ev3q"></p>
<p>So far, I have talked exclusively about the representation of text. Typing was a
different beast entirely. Suppose that you were using the <em>Annapurna</em> font.
Since keyboards come in the standard QWERTY layout, if you pressed the A key
(which is internally ASCII 65), an अ would appear. But on changing the font to
<em>Sabdatara</em> and it would change to a द्ब. The image below demonstrates how,
typing कलम in <em>Sabdatara</em> font, and then changing it to Annapurna results in
garbage.</p>
<p><img decoding="async" loading="lazy" alt="kalamin3fonts.png" src="https://bynirav.com/assets/images/kalamin3fonts-dca7459b101619c78666c734dbd56afa.png" width="270" height="143" class="img_ev3q"></p>
<p>But thankfully, over time these mappings stabilized to the what is now known as
the Traditional or Remington's keyboard layout. Generally, if someone over 30
tells you that they can type in Nepali, what they probably mean is that they can
type in the traditional keyboard layout. It is what you type if you use the
Sagarmatha or the Preeti font.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="unicode">Unicode<a href="https://bynirav.com/blog/nepali-language-and-unicode#unicode" class="hash-link" aria-label="Direct link to Unicode" title="Direct link to Unicode">​</a></h2>
<p>Naturally, India was not alone in wanting an encoding for its scripts. The late
‘80s and the ‘90s saw the rise of encoding schemes such as PASCII, VSCII, JIS X,
many ISO standards, and much more, each developed by a particular country or a
group of countries to encode their language. All this was fine and dandy for the
systems back then. But then came the Internet.</p>
<p>The Internet pretty much broke everything. Computers all over the world were
expected to understand each other, but they spoke in different encodings. If you
didn’t encode your data in the same format as the receiving computer was set to,
your text would render as garbage. The problem was that a number in one computer
in one country represented something entirely different in another computer in
another country.</p>
<p>Unicode was designed from the ground up to support all scripts of the world. It
currently has 1,37,994 characters from 150 writing scripts. Unicode puts each
character its own unique identifying number. For example, the number 2325
(U+0915) uniquely identifies the Devanagari letter क, the number 70658
(U+11402) identifies the Newari letter 𑐂, the number 65 (0x41) represents the
English capital letter A and the number 24859 (0x611b) the unified Chinese,
Japanese and Korean ideograph 愛. These numbers mean the same thing no matter
where in the world you are or what computer you are using. These numbers are
also immutable, meaning that, Unicode won’t ever change what a number means,
hence maintaining backward compatibility.</p>
<p><img decoding="async" loading="lazy" alt="codepoint_table.png" src="https://bynirav.com/assets/images/codepoint_table-e1e423475fa60a600e2c6fe464db4d69.png" width="1205" height="892" class="img_ev3q"> <em>This table lists all
Nepali Characters in the Unicode Devanagari block with their codepoint numbers.</em></p>
<p>Characters of the same script live in the same block. A block is essentially a
range of numbers. For example, Devanagari characters live in the U+0900 to
U+097F block. Newa is in the U+1900 to U+194F block. The Limbu writing
system, Sirijanga Script, lives in U+1900 to U+194F block.</p>
<p>The advantage of separating language into blocks, is that each block can get its
own kind of treatment from the software. We know that different scripts behave
differently. In Devanagari, some characters go above the previous character,
some under. Some change the character itself. In Tibetan, diacritics stack up
vertically. A single Urdu character, when typed, can change how the entire word
looks. Not to mention that scripts have different directions of reading. Chinese
is written from top to bottom. Urdu is written from right to left. All these
quirks can be handled by software based on what block the characters come from.</p>
<p>The Devanagari block is shown below. It was taken from Wikipedia.</p>
<p><img decoding="async" loading="lazy" alt="wikipediaunicodetable.png" src="https://bynirav.com/assets/images/wikipediaunicodetable-9f7f3fc0ec0703c5a46afdd580cd5ba3.png" width="711" height="415" class="img_ev3q"></p>
<p>Now, if you look at the table above, you will notice a lot of characters
missing. Where is क्ष? Or द्य? Or all the half forms like क्‍ , ग्‍ , and the
rest? Well, because Unicode was based on ISCII, and since Hindi considers क्ष,
त्र and ज्ञ to be compound characters, they aren’t allocated separate code
points. That doesn’t mean you cannot type it, though. You just have to input the
constituent characters and the text-rendering system will take care of the rest.
क्‌ष makes क्ष, त्‌र makes त्र and ज्‌ञ makes ज्ञ automatically.</p>
<p><img decoding="async" loading="lazy" alt="consonantforms.png" src="https://bynirav.com/assets/images/consonantforms-30719c0ba30f9cc3cd1c25fcf37be03b.png" width="597" height="354" class="img_ev3q"></p>
<p><em>Unicode Specification on how a software should handle compound characters in
Indic scripts.</em></p>
<p>So then, what if you want to type out क्‌ष explicitly? Unicode provides a
character called Zero Width Non-Joiner (ZWNJ) (zero width because it doesn’t
take up any space in the text). But it prevents the Halant ्‌ from changing
characters to their half forms. Similarly, there is a Zero Width Joiner which
explicitly asks for the half form to be displayed, even if there isn’t a
character next to it.</p>
<p>Now, if you look at the table for <em>Sabdatara</em> and <em>Annapurna</em> font above, you’ll
notice that the half forms are explicitly encoded. That is probably an artifact
from the printing press era. When typesetting for the printing press, or when
using a Linotype, a क followed by a ्‌ wouldn’t magically change into क्‍. You
would have to select the correct type blocks manually. That kind of thinking
could have carried over into the font design process.</p>
<p>But computers are smarter than that. They will easily substitute the glyphs for
you. The only thing to keep in mind is to use your ZWJs and the ZWNJs when you
want the other forms.</p>
<p>Unicode intends to depict the underlying characters rather than the renderings.
Think of it this way: प्राप्त is the rendering and प + ्‌ + र + ा‌ + प + ्‌
+ त is its underlying character composition. Unicode delegates the rendering to
the display system. This model of text encoding is called the Virama-based model
(<em>virama</em> meaning <em>halanta</em>), and is not unique to Devanagari.</p>
<p>The Unicode 12.0 specification has an insightful image to clarify further.</p>
<p><img decoding="async" loading="lazy" alt="purtiunicode.png" src="https://bynirav.com/assets/images/purtiunicode-ad234ec7647cb7ab93063af676558e5d.png" width="427" height="467" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="utf">UTF<a href="https://bynirav.com/blog/nepali-language-and-unicode#utf" class="hash-link" aria-label="Direct link to UTF" title="Direct link to UTF">​</a></h2>
<p>Unicode is mostly concerned with assigning <em>abstract</em> numbers to characters, and
describing their properties. Unicode Transformation Format, or UTF is the
<em>implementation</em> of the Unicode specification. UTFs are the algorithms which
convert these abstract numbers into bits and bytes that are eventually stored in
the memory, processed or transmitted.</p>
<p>Only three Unicode Transformation Formats are in widespread use: UTF-8, UTF-16
and UTF-32. The numbers in their name signify the number of bits they use. So
UTF-8 uses 8 bits (one byte), UTF-16 uses 2 bytes and UTF-32 uses 4 bytes. The
figure below will try to demonstrate how UTF8 works. It’s okay if it ends up
confusing you instead. Unless you are writing multilingual computer programs, it
is not generally necessary to know how these encoding schemes work. Just
remember that most all of internet uses utf-8 because it is the most efficient
encoding.</p>
<p><img decoding="async" loading="lazy" alt="utf8rocketinggraph.png" src="https://bynirav.com/assets/images/utf8rocketinggraph-ba7747d29fa2b8b25f20d8c8a0f080ab.png" width="1389" height="817" class="img_ev3q"></p>
<p><strong>Nepali Input</strong></p>
<p>Unless you can already type in the traditional layout, I recommend that you try
out the <a href="http://ltk.org.np/keyboard_layouts.php" target="_blank" rel="noopener noreferrer">Phonetic layout</a> by Nepali
Language Technology Kendra. I’m sure any reasonably dedicated person can learn
this layout in a day.</p>
<p>As it turns out, it is a fairly simple exercise to create a new keyboard layout
from scratch. I was able to make myself a modified version of the Phonetic
layout in less than an hour. To make your own layout, download and install the
<a href="https://www.microsoft.com/en-us/download/details.aspx?id=22339" target="_blank" rel="noopener noreferrer">Microsoft Keyboard Layout Creator tool</a>.</p>
<p>Nepal Language Technology Kendra website also provides keyboard layouts for
Nepali Keyboard layouts for Linux. On Android phones, you can install either
Hamro Keyboard or Google Indic keyboard, both of which are excellent. On iPhones
and iMac, simply activating the required input method in Settings should
suffice.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="fonts">Fonts<a href="https://bynirav.com/blog/nepali-language-and-unicode#fonts" class="hash-link" aria-label="Direct link to Fonts" title="Direct link to Fonts">​</a></h2>
<p><img decoding="async" loading="lazy" alt="compositionsdevanagari.png" src="https://bynirav.com/assets/images/compositionsdevanagari-a88fffe8220728fddd4346196d9a30e8.png" width="856" height="588" class="img_ev3q"></p>
<p>Google Fonts has a usable selection of fonts for Devanagari. To filter the fonts
by the language, find the <em>Language</em> dropdown and select Devanagari (even though
it isn’t a language).</p>
<p><em>Featured photo of Linotype by werner moser from FreeImages.com</em></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sandboxing Unsafe Executables in Linux for an Online Compiler with Minijail]]></title>
            <link>https://bynirav.com/blog/sandboxing-small-executables-in-linux</link>
            <guid>https://bynirav.com/blog/sandboxing-small-executables-in-linux</guid>
            <pubDate>Tue, 08 Oct 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[I wrote a toy compiler few months back. I wanted people to see it, so I put the]]></description>
            <content:encoded><![CDATA[<p>I wrote a toy compiler few months back. I wanted people to see it, so I put the
code up on Github. But as it turns out, not everyone is willing or capable of
going through the convoluted process of cloning the repository, compiling the
program, installing a Nepali language keyboard and learning an obscure
half-baked programming language just because some idiot put it on Github.</p>
<p>So, I started to write a web app to make the program easily
accessible. The web app lets user write code in their browser, then
compiles and executes the program on the server, and allows the user to send
input from the browser to the server as it executes.</p>
<!-- -->
<p>My first instinct was to use something like AWS Lambda to compile and run each
process as a cloud function, but then I looked into the deep abyss of my wallet
and found myself lost in the darkness.</p>
<p>Another idea was to forego the cloud altogether. Compiling code into assembly
can be done in any under-powered Virtual Private Server. I can write an
implementation of a simple virtual machine in JavaScript, then I can add a new
backend to my compiler to generate code for the virtual machine. Then I can
embed the JS virtual machine in the webpage, and when the user hits compile, all
server has to do is compile the language into machine code for the virtual
machine and send that back to the client. Execution becomes client-side
headache. Something like (a slightly saner version of) Brainfuck could be
perfect for this kind of application. It's relatively simple to make a
<a href="https://https//thorstenball.com/blog/2017/01/04/a-virtual-brainfuck-machine-in-go/" target="_blank" rel="noopener noreferrer">Brainfuck Virtual machine</a>.</p>
<p>Anyway, I decided that AWS Lambda is too wasteful for my needs. Virtual Machine
on Webpage idea is going to significantly increase code maintenance related
tasks in the future. I tried to find some other way of executing user's programs
on the server.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="issues-with-executing-unsafe-binaries-on-server">Issues with executing unsafe binaries on server<a href="https://bynirav.com/blog/sandboxing-small-executables-in-linux#issues-with-executing-unsafe-binaries-on-server" class="hash-link" aria-label="Direct link to Issues with executing unsafe binaries on server" title="Direct link to Issues with executing unsafe binaries on server">​</a></h3>
<p>But huge security issues emerge by allowing user-generated executables to run on
your server. Just to name a few:</p>
<ol>
<li>The executable can start an <strong>expensive infinite loop</strong> (for example: listing
all prime numbers above 10^5), which makes the system unbearably slow for
other processes.</li>
<li>It can generate and <strong>store a huge amount of data</strong> which either completely
fills up the RAM, the storage system, or both, causing the system to slow
down or crash, and making it physically impossible for other users to store
and run their executables.</li>
<li>It can <strong>overwrite important files</strong> in the server (for example, the very
node.js program responsible for compiling and executing user programs) and
infect all clients with malicious payloads.</li>
<li>It can utilise the program bugs or kernel bugs to <strong>elevate it's status to
root</strong> to install stealthy rootkits or bitcoin mining software to use our
servers for their benefit.</li>
</ol>
<p>This is just the tip of the iceberg. So many other malicious attacks are
possible depending on the system and infrastructure arrangement. The system
designer has to be very careful in setting up the system where untrusted and
potentially unsafe executables are run, without causing significant lags for
genuine users.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="solutions-and-preventive-measures">Solutions and preventive measures<a href="https://bynirav.com/blog/sandboxing-small-executables-in-linux#solutions-and-preventive-measures" class="hash-link" aria-label="Direct link to Solutions and preventive measures" title="Direct link to Solutions and preventive measures">​</a></h3>
<p>This was the first time I had to design a system like this, so I had to research
quite a bit. In this post, I highlight some results of my research. First, lets
see how the above issues can be dealt with in a general way.</p>
<ol>
<li>To prevent expensive infinite loops, we can limit the maximum CPU percentage
allowed to each user process and kill it after a fixed time.</li>
<li>To prevent memory overuse, simply limit the maximum memory allowed per
process.</li>
<li>Either completely block file writes, or have a sandboxing file layer which
redirects all file accesses of the process to a safe temporary directory. Or
run the process on a virtual file system in a separate mount namespace.</li>
<li>Use redundant security measures and tightly constrain the execution
environment using whitelists to minimize the kernel attack surface.</li>
<li>Execute the user process in a <em>sandbox</em>, which essentially manages most of
the above concerns and provides more isolation.</li>
</ol>
<p>These are, of course, just the general guidelines. In my case, because <em>i.</em> the
users actually can't directly craft the machine code that runs in the server and
<em>ii.</em> I have full control over and knowledge of the assembly code that is being
generated, things are a little easier security-wise. But this will eventually
change as I add more features and as more contributors join. So taking some time
to tighten the security is more future-proof.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="features-the-linux-kernel-provides">Features the Linux Kernel provides<a href="https://bynirav.com/blog/sandboxing-small-executables-in-linux#features-the-linux-kernel-provides" class="hash-link" aria-label="Direct link to Features the Linux Kernel provides" title="Direct link to Features the Linux Kernel provides">​</a></h3>
<p>I'll start with the features already provided by a relatively recent Linux
kernel by default.</p>
<ol>
<li><strong>Users and Groups:</strong> It's obvious, but by simply ensuring that there's no
case in which the unsafe binary will be run as root and that no program
started with sudo executes the unsafe binary, we cut off a big chunk of
attacks. But let's take it a step further. Make a new user account with
limited privileges and run the unsafe binary as that user. Set up permissions
accordingly so that the new user account cannot read what need not be read.
Add the user only to groups which it absolutely requires.</li>
<li><strong>Namespaces:</strong> Namespace is a feature of Linux kernel that allows you to
isolate a process from other processes in certain respects. For example, if
you run the untrusted executable in a separate process namespace, the process
is not able to see or interact with any other process running in the system.
It literally becomes the <code>init</code> process in it's view. Namespaces allow
containers like dockers to fake isolated systems without the overhead of the
full Virtual Machine.</li>
<li><strong>Control groups:</strong> Control groups (also called cgroups) allow you to
allocate resources and set limits on CPU time and memory, among other things.
This, when used in conjunction with namespaces allows for effective
containerization of apps.</li>
<li><strong>Capabilities:</strong> Capabilities in Linux allows selective provisioning of root
privileges. If you really have to allow the untrusted program to do things
that only root is able to, then capabilities allows you to allocate only the
required root-only operations to the running process</li>
<li><strong>Seccomp-bpf:</strong> Seccomp-bpf stands for Secure Computing mode-Berkeley Packet
Filter (although no one calls it this). Seccomp by itself blocks all syscalls
except four (exit(), sigreturn(), read() and write() on already open file
descriptors) so unsafe compute-bound processes can be run without many risks,
as almost 99% of the syscalls are blocked by the kernel. BPF is an addon to
seccomp which allows you to block any syscalls you want. <em>strace</em> is a linux
tool that allows you to trace syscalls made by a process.</li>
</ol>
<p>Because these features are provided natively by the Linux kernel, we can apply
them using corresponding syscalls and parameters and make with a relatively
robust sandbox. I toyed with the idea of making my own restricted
micro-sandboxing program (and I really wanted to) but decided not to because I
was already juggling more things than I like to.</p>
<p>There are programs which use these kernel features and more to sandbox
applications for us. I had expected there to be many, specially in this age of
cloud computing and lambda functions.</p>
<p><strong>nsjail:</strong> I couldn't get it to compile because of some strange protobuf
dependency error. It doesn't help that the GitHub readme doesn't have any build
steps or the versions of dependencies required. Which is a shame because this
was almost exactly what I was looking for: a lightweight application sandbox. I
might look into it some more later.
<a href="https://nsjail.com/" target="_blank" rel="noopener noreferrer" title="https://nsjail.com">This</a> is the official site for nsjail.</p>
<p><strong>mbox:</strong> It doesn't seem to work in 2019. The example usages in GitHub fail to
do any kind of blocking. The <code>-n</code> still doesn't block internet access. I'm
guessing that it relies on some old kernel specific features. It was last
updated 3 or 4 years ago on github. Also, reading the author's paper and
ycombinator comments, I got the feeling that he's much more proud of his
filesystem layering work than his sandboxing work. Also, Mbox seems more like
some academic/proof-of-concept work. Doesn't fit my requirements.
<a href="https://pdos.csail.mit.edu/archive/mbox/" target="_blank" rel="noopener noreferrer" title="Mbox website">This</a> is the official
site for Mbox.</p>
<p><strong>Docker:</strong> Heavy and not built for my use case. It is also not as
security-focused, and apparently it can be broken out of. At any rate, I'm not
gonna be instantiating full containers for executing a sub-megabyte programs.
Although Docker running small distros like Puppy linux is an interesting idea.
<a href="https://docker.com/" target="_blank" rel="noopener noreferrer" title="Docker">This</a> is the official site for Docker.</p>
<p><strong>systemd-nspawn</strong> is really interesting. It needs a full chown-able filesystem
I didn't use it this time, but I'm definitely going to use this in some future
project.</p>
<p><strong>minijail:</strong> This little software is apparently used by Google to sandbox
chromium programs. It is not as feature rich as nsjail so I ended up using this
in conjunction with cgroups and some other programs to isolate the unsafe
binary.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/oGmj6CUEup0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<p><a href="https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations" target="_blank" rel="noopener noreferrer" title="https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations">https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations</a></p>
<p>PS <a href="https://mosh.org/" target="_blank" rel="noopener noreferrer" title="Mosh website">Mosh</a> is really cool substitute to SSH,
specially when you're using vim to code directly on the server. Plus, the fact
that I don't have to restart SSH connection every time I wake my laptop is such
a convenience.</p>
<p><strong>Resources</strong></p>
<ol>
<li><a href="https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations" target="_blank" rel="noopener noreferrer" title="https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations">https://en.wikipedia.org/wiki/OS-level_virtualisation#Implementations</a><br>
<!-- -->This page has a list of many sandboxing tools that don't use full VMs.</li>
<li><a href="https://chromium.googlesource.com/chromiumos/docs/+/master/sandboxing.md" target="_blank" rel="noopener noreferrer" title="https://chromium.googlesource.com/chromiumos/docs/+/master/sandboxing.md">https://chromium.googlesource.com/chromiumos/docs/+/master/sandboxing.md</a><br>
<!-- -->Explains how minijail can be used for security. If you're using Minijail,
also check out the embedded video.</li>
<li><a href="https://people.csail.mit.edu/nickolai/papers/kim-mbox.pdf" target="_blank" rel="noopener noreferrer" title="https://people.csail.mit.edu/nickolai/papers/kim-mbox.pdf">https://people.csail.mit.edu/nickolai/papers/kim-mbox.pdf</a><br>
<!-- -->The author's paper explaining Mbox.</li>
<li><a href="https://blogs.rdoproject.org/2015/08/hands-on-linux-sandbox-with-namespaces-and-cgroups/" target="_blank" rel="noopener noreferrer" title="https://blogs.rdoproject.org/2015/08/hands-on-linux-sandbox-with-namespaces-and-cgroups/">https://blogs.rdoproject.org/2015/08/hands-on-linux-sandbox-with-namespaces-and-cgroups/</a><br>
<a href="https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces" target="_blank" rel="noopener noreferrer" title="https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces">https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces</a><br>
<!-- -->Use these two links if you're going baremetal. Also try finding pages in
chromium.googlesource.com about sandboxing. They have done a lot of work in
that area. A representative page is below:
<a href="https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md" target="_blank" rel="noopener noreferrer" title="https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md">https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md</a></li>
<li><a href="http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/34913.pdf" target="_blank" rel="noopener noreferrer" title="http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/34913.pdf">http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/34913.pdf</a><br>
<!-- -->This is the paper explaining Native Client, a sandboxing system developed by
Chrome developers to allow execution of C/C++ programs in the web browser
with near-native speed.</li>
<li><a href="https://blog.golang.org/playground" target="_blank" rel="noopener noreferrer" title="https://blog.golang.org/playground">https://blog.golang.org/playground</a><br>
<!-- -->The Go language website has an online code compiler similar to ours. In this
blog post, they describe how they used Native Client (see resource 5) and
other ideas to provide the safe online compilation and execution service to
users. Particularly interesting is their decision to
<a href="https://github.com/golang/go/issues/16667" target="_blank" rel="noopener noreferrer" title="golang issue raised on whether to allow interactive input or not">disallow any interactive input </a>to
favour caching results and to reduce CPU time per program.<br>
<!-- -->They also seem to be using a separate branch of compiler to generate Native
Client executable for executables. I had contemplated on whether I should add
an extra backend in my compiler which generates secure code at compile time.
But I decided that the maintenance burden was not worth it.</li>
</ol>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Animating WALL-E on a LED dot-matrix display with AVR]]></title>
            <link>https://bynirav.com/blog/animating-walle</link>
            <guid>https://bynirav.com/blog/animating-walle</guid>
            <pubDate>Wed, 12 Jun 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[I was asked to animate a dot-matrix display for the robotics club recently. They]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/two-15184a277e8b102047da62c4f60d6734.jpg" width="2048" height="1007" class="img_ev3q"></p>
<p>I was asked to animate a dot-matrix display for the robotics club recently. They
wanted something that said "Robotics Club" to hang over their door. We had some
old <code>P10(1r)</code> DMDs which I had worked on in the past to make a little scoreboard
for a robot football match. And, even though I am not very good at it, I really
love animating things. So I decided to give it a shot. I ended up writing an
animation software for the DMD in JavaScript which is unfortunately only as
functional as a flipbook. But I had fun animating little person carrying a
balloon, ugly gear trains and a little pixel Wall-E blinking.</p>
<!-- -->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/zjk1e-JFNFA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<p>Yeah, that's a little Wall-E looking at you. After thinking long and hard about
it, I decided that Wall-E is the best robot to look over us all while we do our
robotics stuff. Wall-E was also, thanks to his angular design and distinctly
recognizable shape, much better suited to a low resolution display than some
other things I wanted to do.</p>
<p>Another thing I animated was a little man who carries a balloon and strolls into
the DMD where "Robotics Club" is written and just stands there idly for a while,
then goes away. I thought it was a cool thing to do, but no one else agreed. So
I reluctantly scrapped that idea. I also wanted to animate some other things,
like a gear train driven by a hamster, and GIR from Invader Zim (remember that
show?). But of course, a monochrome 32x32 matrix doesn't give you much space to
play with. I was also limited by time. I'm working almost full time on our
<a href="https://nirav.com.np/2019/05/27/a-nepali-programming-language.html" target="_blank" rel="noopener noreferrer">minor project</a>,
and I also have to attend my classes. For the next version of this screen, I'm
planning a much cooler animation, that uses the whole 32x32 screen and the whole
32KB of the AVR program space, and maybe also some form of compression. In this
post, I document all the major portions of the project, while also trying to be
helpful to people designing DMDs.</p>
<p>I made all the electronics for the project last semester with
<a href="https://bhuwanadhikari.com.np/" target="_blank" rel="noopener noreferrer">Bhuwan</a>. We made the circuit board by hand,
doing everything from hack-sawing the PCBs, etching the copper traces with a
fumigating solution of FeCl<sub>3</sub>, drilling the boards and soldering the
components. That process, while manual, was very enjoyable. The resulting
circuit looks nice and is so robust that from the time it was built, there has
never been any hardware bug in the system. I mean, sure, being a MCU based
digital circuit doesn't leave much room for bugs. But still, considering the
many many many hardware bugs we encountered while doing the robot MIMO (we ended
up making 6 iterations for the circuit board), this one was a walk in the park.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/one-f992aac8001b773a48d9ef6665e7d067.jpg" width="1779" height="951" class="img_ev3q"></p>
<p>The board is straightforward. It's an Atmega32A with it's support circuitry
(oscillators, decoupling capacitors and such) and a bunch of headers: one for
connecting the In-System Programmer, one for connecting to a control remote, and
one for the Dot-Matrix display.</p>
<p>The display itself (<code>P10(1r)-V70</code>) is a matrix of LEDs all connected to a bunch
of <code>74HC595</code> shift registers in series. The DMD takes the following inputs:</p>
<ol>
<li>Output Enable (OE)</li>
<li>Row Selectors (A and B)</li>
<li>A data line (D)</li>
<li>A clock line (CLK)</li>
<li>A Latch line (SCLK)</li>
<li>A ground</li>
</ol>
<p>The data line D inputs the data serially, clocked by the CLK line. On the rising
edge of the SCLK pin, the data shifted in is displayed on the LEDs. So far, it
is exactly as if we were using the 74HC595 directly. But the row selectors
complicate things slightly. The people who designed this board have done
something really cool. Perhaps to reduce part count, or to keep the board layout
simple, or maybe because of fanout issues, they have connected 4 consecutive
LEDs to the same set of shift registers. Which rows of the matrix you are
addressing depends on the inputs to the selector pins. That is, for A = LOW, B =
LOW, the first of the four rows is selected; for A = LOW, B = HIGH, the second;
and so on. I will talk more about this further below.</p>
<h1>The Animation Software</h1>
<p>For various reasons, I had to write the animation software myself. The last
time, I had written an animation program on Python using Tkinter. Actually,
'written' is a bad verb to describe that process. I had jerrybuilt the whole
system in an hour. And over the course of the next week, I had haphazardly stuck
various appendages and functions which made the code very difficult to navigate.
On top of that, the program itself was very ugly.</p>
<p>This time, I decided to go with a HTML canvas based approach because I didn't
want to download a GUI designer for python, and I sure as heck wasn't going to
sit around and waste my precious time learning Tkinter's packs and grids and
what not. So anyway, I surprised myself by jerrybuilding the entire system in a
few hours, complete with animation frames, onion skinning and the undo feature.
The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" target="_blank" rel="noopener noreferrer">canvas API</a>
was so simple, and JavaScript so forgiving, that I didn't even run into any time
consuming bug. And the most interesting part? The complete HTML file (with JS
and CSS in the same document) is 500 lines of code! It is still bad code, and is
very inefficient in many respects. But because it is a means to an end, I
allowed myself to take shortcuts. The result is the screenshot below.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/screenshot-d244a81543da675dbd6c9087d503c6dd.png" width="1362" height="670" class="img_ev3q"></p>
<p>It was so fun to make animations in my own animation program. The only seriously
desirable feature that this program lacks is the select and the move feature.
The old python version actually had that feature. But I was already pressed for
time so I didn't implement it.</p>
<p>The software can be accessed at
<a href="https://nirav.com.np/Animator-inator" target="_blank" rel="noopener noreferrer">nirav.com.np/Animator-inator</a>. Feel free
to check it out.</p>
<h1>The Firmware</h1>
<p>I used the same firmware I had written a semester ago. The code itself is
straightforward. But I remember it took me a long time to write it, because I
didn't have a lot of documentation to consult. So I had to sit there, with the
DMD board and it's various pins and wires, and I had to prod this and poke that
to figure out how it worked, rather like a puzzle. Thankfully I had worked with
the shift registers before, so it took a lot less work than it otherwise would
have. This piece of code below is pretty much the only part of the code that
counts.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token comment" style="font-style:italic;color:red">// Slightly altered from original</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token comment" style="font-style:italic;color:red">// for readablity</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">void</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">clock_selected_lines</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">char</span><span class="token plain"> selector</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> i </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> i </span><span class="token operator" style="color:black">&lt;</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">WIDTH </span><span class="token operator" style="color:black">/</span><span class="token plain"> </span><span class="token number" style="color:red">8</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> i</span><span class="token operator" style="color:black">++</span><span class="token punctuation" style="color:black">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">for</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> j </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">3</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> j </span><span class="token operator" style="color:black">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> j</span><span class="token operator" style="color:black">--</span><span class="token punctuation" style="color:black">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">      </span><span class="token function" style="font-weight:bold;color:black">clockbyte</span><span class="token punctuation" style="color:black">(</span><span class="token plain">display</span><span class="token punctuation" style="color:black">[</span><span class="token plain">j </span><span class="token operator" style="color:black">*</span><span class="token plain"> </span><span class="token number" style="color:red">4</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> selector</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">[</span><span class="token plain">i</span><span class="token punctuation" style="color:black">]</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">setselector</span><span class="token punctuation" style="color:black">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">sendpulse</span><span class="token punctuation" style="color:black">(</span><span class="token plain">LATCH</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">main</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">init</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  OCR0 </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0xff</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  TIMSK </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">2</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  TCCR0 </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0X0b</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token function" style="font-weight:bold;color:black">sei</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> frame </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">while</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">cli</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">disableoutput</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">assign_to_display</span><span class="token punctuation" style="color:black">(</span><span class="token plain">frame</span><span class="token operator" style="color:black">++</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">enableoutput</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">sei</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token keyword" style="font-style:italic;color:black">if</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">frame </span><span class="token operator" style="color:black">&gt;=</span><span class="token plain"> framecount</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> frame </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    </span><span class="token function" style="font-weight:bold;color:black">_delay_ms</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">10</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>clock_selected_lines()</code> function takes a value from 0 to 3, and based on
that value, extracts the relevant bits from the <code>display</code> bit matrix to send
into the DMD. Keep in mind that, at one time, only 4 rows (every fourth row) of
the 16 total rows in the DMD can be activated. This is because every group of 4
LEDs, row-wise, is connected to the same pin in the same shift register. Which
of the 4 connected LED lights up is controlled by the 2 selector pins A and B.
To show a complete picture, we have to cycle between the four SEL pins fast
enough that it is below the persistence of vision (10 ms). And each time we
switch rows, we also have to clock in the data in those rows. I know it sounds
complicated, but if you think about it, this little design ingenuity reduced the
part count in the board by a factor of four and minimized the signal propagation
delay inherent in such shift registor based system.</p>
<p>That process is called time-multiplexing, and is used in many kinds of displays
throught electronics. The slow mo guys have an amazing video on how displays
work. Definitely watch the video, even if you don't see yourself working with
displays any time soon. It gives you a new perspective on time.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/3BJU2drrtCM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<p>The <code>main()</code> function simply sets up a timer which calls the
<code>clock_selected_lines()</code> function every certain microseconds and increments the
<code>selector</code> variable by one and makes sure it warps around at 4. Then it enters a
while loop which swaps the display frame every few milliseconds. Keep in mind
that the 10ms value is not the real frame change time. The value increases
somewhat due to being frequently interrupted. I should have set up another timer
for changing frames but I don't think it was necessary for such a simple
program. The <code>sei()</code> and <code>cli()</code> functions turn interrupts on and off. We turn
interrupts off before entering sensitive portion of the code. For example, we
don't want to be interrupted when we copy the next frame from the PROGMEM
(flash) into RAM because we don't want to display half copied frames to the
viewer.</p>
<h1>Final thoughts</h1>
<p>I enjoyed making this. This DMD gave me a much needed break from the extremely
formal and dry world of compiler literature which I have been poring over for
weeks in order to make the
<a href="https://bynirav.com/blog/making-%E0%A4%AE%E0%A4%A8%E0%A4%B8%E0%A4%BE">साक्षर (now मनसा) compiler</a>.</p>
<p>But there is one decision that I regret immensely. In hindsight, it would have
been much better if I had written a program to convert any GIF file into a data
format suitable for the DMD. It would have been much less glamorous to work on,
sure, but it would have given me the free license to work with any pixel based
animation software that already exists, and already supports select, move,
multi-level undo and all that fancy stuff.</p>
<p>In the next version, I also think it would be awesome if I could implement some
form of compression in the animation data. I'm interested in performing some
kind of Run-Length Encoding on the delta frames. What I mean is, unless you are
animating a moving checkerboard, very little actually changes between a frame
and the next. So, if we calculate the delta matrix between every frame and it's
successor, we should get a sequence of sparse matrices which we can encode with
RLE or some other compression algorithm to achieve good compression on the
frames while also being very simple to decompress sequentially. The 2KB RAM on
the AVR system should be more than enough.</p>
<p><strong>The whole project is available on my GitHub</strong>
<a href="https://github.com/niravcodes/Animator-inator" target="_blank" rel="noopener noreferrer"><strong>here</strong></a></p>]]></content:encoded>
            <category>electronics</category>
            <category>embedded</category>
        </item>
        <item>
            <title><![CDATA[Animating a Skeleton in Pixel Art]]></title>
            <link>https://bynirav.com/blog/animating-a-skeleton-in-pixel-art</link>
            <guid>https://bynirav.com/blog/animating-a-skeleton-in-pixel-art</guid>
            <pubDate>Sat, 06 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[I animated this a while back. I remember it took me days. First I had to learn]]></description>
            <content:encoded><![CDATA[<p>I animated this a while back. I remember it took me days. First I had to learn
how to actually draw the human skeleton (<em>The Atlas of Human Anatomy for the
Artist</em> by Stephen Peck is an amazing resource). Then I had to distill the ideas
into the bare minimum required to get the picture across. Finally I drew and
animated the whole thing in <a href="https://www.piskelapp.com/" target="_blank" rel="noopener noreferrer">piskel</a>. The animation
process was quite tedious, at least in part because this was my first try.</p>
<!-- -->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/f0SJTEIYIHE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>]]></content:encoded>
            <category>animation</category>
        </item>
        <item>
            <title><![CDATA[Implementing the Huffman Compression Algorithm in C++]]></title>
            <link>https://bynirav.com/blog/huffman-compression-cpp</link>
            <guid>https://bynirav.com/blog/huffman-compression-cpp</guid>
            <pubDate>Thu, 14 Feb 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[The final code is at github/niravcodes/huffman_compression]]></description>
            <content:encoded><![CDATA[<p><strong>The final code is at <a href="https://github.com/niravcodes/huffman_compression" target="_blank" rel="noopener noreferrer">github/niravcodes/huffman_compression</a></strong></p>
<p>Da Vinci is quoted saying, "Art is never finished, only abandoned". I don't see
why it should be any different for code. With that said, I'd like to declare my
latest project: an
<a href="https://github.com/niravcodes/huffman_compression" target="_blank" rel="noopener noreferrer">implementation of the huffman's algorithm</a>
abandoned. It works well as it is, but it can be made a lot better.</p>
<!-- -->
<p>So anyway, I've been working on it for about a week. I started a day before my
Data Communication assessment inspired by a chapter on the Information Theory.
There I was, at 11 in the night, having read for the first time in my life about
huffman's algorithm and <strong>I was thrilled!</strong> I decided then, in the spur of the
moment, to pull an all-nighter and write code for the huffman algorithm. Then I
boiled some water, made myself a cup of strong coffee.</p>
<p>I thought I could finish it that night.But it took a lot longer than I had
estimated. Why? well,</p>
<ol>
<li>The code doesn't use C++ templates. I implemented all necessary data
structures as it would be a nice learning experience.</li>
<li>I didn't know istream ignores the bytes that represent whitespace in ASCII
<strong>even in binary input mode</strong>!</li>
<li>I was using <code>unsigned char</code>s instead of <code>int</code>s for short for-loops (habit
carried over from programming AVRs), and one of them overflowed in special
edge cases, causing me days of debugging.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="huffman-compression">Huffman Compression<a href="https://bynirav.com/blog/huffman-compression-cpp#huffman-compression" class="hash-link" aria-label="Direct link to Huffman Compression" title="Direct link to Huffman Compression">​</a></h2>
<p>For those of you who don't know, huffman's algorithm takes a very simple idea
and finds an elegant way to implement it. At its heart is the observation that
the more a thing is mentioned, the shorter its name should be. This idea
manifests itself in daily life too. For example, we use nicknames for people we
call often, we have abbreviations for long words we often have to use and even
the word ok was once an abbreviation for "all correct".</p>
<p>Translated to the world of computers, it means that if a chunk of data repeats
itself more than another chunk of data in the same group, it is best to encode
the more occurring chunk with smaller code word. Practically what it means is
that the compressed file has two parts. First there is a dictionary of code
words and their corresponding chunks of data. And then there is a the data
itself, encoded using codewords (often called payload in compression jargon).
During decompression, the dictionary is read and the codewords are sequentially
translated into actual data.</p>
<p>Of course, the implementation of this idea requires us to first solve a few
problems. For one, uncompressed data is easy to read. The specification of the
file format is all you need to extract relevant information from uncompressed
files. In uncompressed audio, say, a fixed number of bytes unambiguously make up
a sample i.e a single amplitude in the sound wave. Simply by reading one sample
at a time and setting a proportional voltage across the speaker you convert the
digital representation into real sound. And if you time it right, you might even
hear the music. But once you compress that raw file with the scheme I mentioned
above things start to get tricky.</p>
<p>Say this is the data you want to compress:</p>
<blockquote>
<p>BANANA</p>
</blockquote>
<p>The ASCII codes for the alphabets in binary are:</p>
<blockquote>
<p>B : 01000010</p>
<p>A : 01000001</p>
<p>N : 01001110</p>
</blockquote>
<p>Thus the ASCII encoding of BANANA is:</p>
<blockquote>
<p>01000010 01000001 01001110 01000001 01001110 01000001</p>
</blockquote>
<p>Keep in mind that when the computer is reading ASCII text files, it always does
so in chunks of 8 bits per character. That's the standard. So the computer
always knows that every 8 bits can be read from the file and matched against the
ASCII table already in it's memory to find which character was typed.</p>
<p>Let's try to compress this with the aforementioned scheme of calling more
frequent chunks of data with smaller nicknames. We will start with a naive
interpretation.</p>
<blockquote>
<p>A : Occurs thrice. Let's call it a 0</p>
<p>N : Occurs twice. Let's call it a 1</p>
<p>B : Occurs once. Let's call it a 10</p>
</blockquote>
<p>The compressed data thus turns out to be:</p>
<blockquote>
<p>1001010</p>
</blockquote>
<p>Lets see the uncompressed data again.</p>
<blockquote>
<p>01000010 01000001 01001110 01000001 01001110 01000001</p>
</blockquote>
<p>That's a massive shrinkage. Now let's try decompressing it. We come across a
massive problem. There are multiple ways to decode the compressed string based
on how you divide the codewords. Here are a few:</p>
<blockquote>
<p>10-0-1-0-1-0 : BANANA</p>
<p>1-0-0-10-10 : NAABB</p>
<p>1-0-0-1-0-1-0 : NAANANA</p>
</blockquote>
<p>See the problem? We wanted to say BANANA but started singing Havana instead. Of
what use is a compression scheme if you can't decompress deterministically?
Think about it. It is mathematically impossible to derive the original message
using only the compressed message and the the dictionary without also sending
other information about the message (which ends up making the compressed file
larger than the original).</p>
<p>This is where we introduce the concept of prefix code (also called prefix-free
code). The idea is simple. In our naive compression scheme, we introduce a
constraint. No codeword can start with another codeword. In other words, no
codeword in the system is the prefix of another codeword. So if you read the
bitstream from left to right, if you come across a valid entry in the code
dictionary, it can be safely translated to the original symbol. We essentially
scan the compressed data sequentially, recognize codewords, translate them, and
carry on.</p>
<p>Applied to the BANANA example, the prefix constraint results in the following
correction:</p>
<blockquote>
<p>A : Occurs thrice. Let's call it a 0</p>
<p>N : Occurs twice. Let's call it a 10</p>
<p>B : Occurs once. Let's call it a 11</p>
</blockquote>
<p>Notice how, in this system, no codeword is the prefix of another codeword.
BANANA now compresses to <code>110100100</code>. This can be deterministically recovered to
BANANA.</p>
<p>And this is what the huffman compression does. Given a set of symbols and their
respective frequencies, it churns out the smallest prefix codewords to represent
them all. That is the huffman compression. And there are other algorithms to do
this, most notably Shannon-Fano algorithm (which they also expect me to memorize
for exams), but as wikipedia says,
"<a href="https://en.wikipedia.org/wiki/Shannon%E2%80%93Fano_coding" target="_blank" rel="noopener noreferrer">Shannon–Fano</a> is
almost never used;
<a href="https://en.wikipedia.org/wiki/Huffman_coding" target="_blank" rel="noopener noreferrer" title="Huffman coding">Huffman coding</a>
is almost as computationally simple and produces prefix codes that always
achieve the lowest expected code word length [as opposed to Shannon-Fano]".</p>
<p>How huffman's algorithm does that is actually pretty interesting too. I am far
too lazy to describe it all in this post, but this video by computerphile (along
with all others related to compression) are great if you're just starting.</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/umTbivyJoiI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-implementation">The Implementation<a href="https://bynirav.com/blog/huffman-compression-cpp#the-implementation" class="hash-link" aria-label="Direct link to The Implementation" title="Direct link to The Implementation">​</a></h2>
<p>The implementation is really the simplest I could find. It is very slow and not
optimized for anything except coding efficiency. The alphabets are <em>always</em>
bytes, for the sake of simplicity. This means that the 'chunk of data' that I
talked about is always a single byte.</p>
<p>Follow <a href="https://github.com/niravcodes/huffman_compression" target="_blank" rel="noopener noreferrer">this link</a> to see the
full code in GitHub.</p>
<p>Here is how it compresses a file:</p>
<ol>
<li><code>count_frequency()</code> returns an array of size 256 with the byte alphabet as
index and it's corresponding frequency as the value. If, for instance, the
byte 0x25 (37 in decimal) occurs 50 times in the file, the array[37] has
value of 50.</li>
<li>The <code>tree::node</code> class represents one single alphabet with a data and a
frequency property. 256 new tree::node objects are created, one for each
alphabet. They are pushed into a priority queue. The priority queue takes in
elements in an arbitrary order, but dequeues them in a fixed order. In this
case, the lowest frequency alphabets are always popped first.</li>
<li>The <code>make_huffman_code()</code> function pops two elements from the priority queue,
makes a new element (say X) with the two elements as two leaves and puts the
new element X back in the queue. X is a node in the huffman's tree. This goes
on in a loop until only one element is left in the priority queue. That is
the root of the huffman tree, and all other elements are it's descendants.</li>
<li>The huffman tree is traversed for every alphabet and a codeword is generated
by the <code>generate_code()</code> function. This function returns an array of objects
of class <code>huffman_code</code>. The class <code>huffman_code</code> encodes the huffman's code
which needs to pieces of information to be correctly understood: the code
itself, and the length of the code as that can vary too.</li>
<li>Using the array, we encode the original file. A class <code>bitstream</code> is used
here to pack the variable-bit-length huffman codes. The <code>bitstream</code> class
uses a little buffer in memory to pack the codes. Once the buffer overflows,
it signals the buffer to be flushed to the file and restores the buffer with
the overflowed contents. This helps keep the memory requirements independent
of the size of file being compressed. The details of the file format are in
the
<a href="https://github.com/niravcodes/huffman_compression/blob/master/README.md" target="_blank" rel="noopener noreferrer">README.md</a>.</li>
</ol>
<p>The soul of this entire code base is the following code.</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">tree </span><span class="token operator" style="color:black">*</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">make_huffman_tree</span><span class="token punctuation" style="color:black">(</span><span class="token plain">input_param options</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">//open the file for inspection</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  ifstream in_file</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  in_file</span><span class="token punctuation" style="color:black">.</span><span class="token function" style="font-weight:bold;color:black">open</span><span class="token punctuation" style="color:black">(</span><span class="token plain">options</span><span class="token punctuation" style="color:black">.</span><span class="token plain">input_file</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> ios</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">binary </span><span class="token operator" style="color:black">|</span><span class="token plain"> ios</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">in</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// count the frequency of all 256 bytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token operator" style="color:black">*</span><span class="token plain"> count </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">count_frequency</span><span class="token punctuation" style="color:black">(</span><span class="token plain">in_file</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> options</span><span class="token punctuation" style="color:black">.</span><span class="token plain">input_file_size</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  priority_queue </span><span class="token operator" style="color:black">&lt;</span><span class="token plain"> tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">node </span><span class="token operator" style="color:black">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:black">*</span><span class="token plain"> x </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">generate_alphabets</span><span class="token punctuation" style="color:black">(</span><span class="token plain">count</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">//count[] is no longer needed</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">delete</span><span class="token punctuation" style="color:black">[</span><span class="token punctuation" style="color:black">]</span><span class="token plain"> count</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> cnt </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">node </span><span class="token operator" style="color:black">*</span><span class="token plain"> a</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token operator" style="color:black">*</span><span class="token plain"> b</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> element</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> c</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">while</span><span class="token plain"> </span><span class="token punctuation" style="color:black">(</span><span class="token plain">x </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">element_count</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">&gt;</span><span class="token plain"> </span><span class="token number" style="color:red">1</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    element </span><span class="token operator" style="color:black">=</span><span class="token plain"> x </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">dequeue</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    a </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">node</span><span class="token punctuation" style="color:black">(</span><span class="token plain">element</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    element </span><span class="token operator" style="color:black">=</span><span class="token plain"> x </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">dequeue</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    b </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">node</span><span class="token punctuation" style="color:black">(</span><span class="token plain">element</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    c </span><span class="token operator" style="color:black">=</span><span class="token plain"> tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">node</span><span class="token punctuation" style="color:black">(</span><span class="token number" style="color:red">0</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> a </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_frequency</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token plain"> </span><span class="token operator" style="color:black">+</span><span class="token plain"> b </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_frequency</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> a</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">    x </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">enqueue</span><span class="token punctuation" style="color:black">(</span><span class="token plain">c</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token punctuation" style="color:black">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">//there is only one element in the priority queue now: The root.</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  element </span><span class="token operator" style="color:black">=</span><span class="token plain"> x </span><span class="token operator" style="color:black">-&gt;</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">dequeue</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token plain">node </span><span class="token operator" style="color:black">*</span><span class="token plain"> root </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> tree</span><span class="token double-colon punctuation" style="color:black">::</span><span class="token function" style="font-weight:bold;color:black">node</span><span class="token punctuation" style="color:black">(</span><span class="token plain">element</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  tree </span><span class="token operator" style="color:black">*</span><span class="token plain"> huffman_tree </span><span class="token operator" style="color:black">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">new</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">tree</span><span class="token punctuation" style="color:black">(</span><span class="token plain">root</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  in_file</span><span class="token punctuation" style="color:black">.</span><span class="token function" style="font-weight:bold;color:black">close</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">return</span><span class="token plain"> huffman_tree</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Since the huffman codes are of variable lengths, I had to write a special bit
stream packing class. It can work with arbitrarily sized buffers and has a
mechanism to avoid buffer overflows. I had the most fun working on that class.
The header is below:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:black;--prism-background-color:white"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:black;background-color:white;font-weight:normal;font-style:normal"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token keyword" style="font-style:italic;color:black">typedef</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">char</span><span class="token plain"> byte</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token keyword" style="font-style:italic;color:black">class</span><span class="token plain"> </span><span class="token class-name" style="font-weight:bold;color:black">bitstream</span><span class="token plain"> </span><span class="token punctuation" style="color:black">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">protected</span><span class="token operator" style="color:black">:</span><span class="token plain"> byte </span><span class="token operator" style="color:black">*</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> buffer_size</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">//in bytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> bit_pos</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">//in bits</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> remainder</span><span class="token punctuation" style="color:black">;</span><span class="token plain"> </span><span class="token comment" style="font-style:italic;color:red">// to store overflowing data</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> remainder_size</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_byte_pos</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_bit_offset</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">inline</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_free_bits</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">micropack</span><span class="token punctuation" style="color:black">(</span><span class="token plain">byte</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// after the buffer has been emptied,</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// pack remainder inside buffer</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">bool</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">add_remainder</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">public</span><span class="token operator" style="color:black">:</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">bitstream</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> buffer_size_in_bytes</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token operator" style="color:black">~</span><span class="token function" style="font-weight:bold;color:black">bitstream</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">get_occupied_bytes</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// packs data into buffer upto specified size</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// returns true if okay</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// returns false if the buffer has filled up</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">// if pack is false, flush then reset buffer</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">bool</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">pack</span><span class="token punctuation" style="color:black">(</span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> huffman_code</span><span class="token punctuation" style="color:black">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic;color:black">unsigned</span><span class="token plain"> code_length</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">//gives you a pointer to the buffer</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">const</span><span class="token plain"> byte </span><span class="token operator" style="color:black">*</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">flush_buffer</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token comment" style="font-style:italic;color:red">//clears the buffer then packs remainder in</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain">  </span><span class="token keyword" style="font-style:italic;color:black">int</span><span class="token plain"> </span><span class="token function" style="font-weight:bold;color:black">reset_buffer</span><span class="token punctuation" style="color:black">(</span><span class="token punctuation" style="color:black">)</span><span class="token punctuation" style="color:black">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:black;font-weight:normal;font-style:normal"><span class="token plain"></span><span class="token punctuation" style="color:black">}</span><span class="token punctuation" style="color:black">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>During decompression:</p>
<ol>
<li>The compressed file is checked for the file signature.</li>
<li>The table is read and stored in memory as an array (lets call it dictionary).</li>
<li>The <code>pluck_bit()</code> plucks successive bits from the file. Every bit of the file
is appended to a variable, then the variable is checked with all 256 entries
of the dictionary. If it matches, the corresponding byte is appended to the
decompressed file and the variable is cleared.</li>
</ol>
<p>This is the most naive way I can think of to decompress the file. But one good
thing about a slow decompression is that I got to make a progress bar. This
might be the first time I wrote a program that takes long enough to make
progress-bar mandatory (apart from file-uploads, of course).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="results">Results<a href="https://bynirav.com/blog/huffman-compression-cpp#results" class="hash-link" aria-label="Direct link to Results" title="Direct link to Results">​</a></h2>
<p>The resulting program is able to compress and decompress files from command
line.</p>
<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/huffmanconsole-18f2a24e6692dd34b731689243a044be.png" width="681" height="240" class="img_ev3q"></p>
<p>The details for usage are in the readme.md file on github but here's a summary:</p>
<ol>
<li>To compress, <code>./huff &lt;filename&gt;</code>. The compressed file will be named <code>a.huff</code>
by default. To specify output file name, use
<code>./huff -o &lt;output filename&gt; &lt;filename&gt;</code></li>
<li>To decompress, <code>./huff -v -d &lt;compressed file&gt;</code>. The <code>-v</code> flag turns on a
progress bar, because decompression is slow with this naive implementation.</li>
</ol>
<p>The compression performance varies wildly with the nature of file, but text
files generally compress to half the size. In a representative test, a sample
6.3 MB text file compressed to 3.6 MB. Trying to compress the already compressed
file brought the size down to 3.5 MB.</p>
<p>By comparison, gZip compressed the same file down to 2.3 MB and bZip compressed
the text file to 1.7 MB, the smallest in all the compared comparison schemes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="closing-remarks">Closing remarks<a href="https://bynirav.com/blog/huffman-compression-cpp#closing-remarks" class="hash-link" aria-label="Direct link to Closing remarks" title="Direct link to Closing remarks">​</a></h2>
<p>When I set out to implement Huffman's algorithm, I had two main objectives:</p>
<ol>
<li>Compare it with gzip to see how well it fares. Obviously gzip is better at
compressing, but I found out just by how much. There is a huge difference. If
you want to try for yourself,
<a href="https://github.com/niravcodes/huffman_compression" target="_blank" rel="noopener noreferrer">clone the repo from github</a>.
But that is not the whole story. Gzip is itself a combination of LZ77
followed by a series of huffman compressions. Gzip is built with huffman
compression as one of it's pillars (see also:
<a href="https://en.wikipedia.org/wiki/DEFLATE" target="_blank" rel="noopener noreferrer">DEFLATE</a>). So I suppose huffman wins
in the end.</li>
<li>See if it is feasible in memory constrained embedded systems (like atmega or
at89c2051). It seems doable. Huffman decompression doesn't require a lot of
RAM (with the compression table stored in PROGMEM) and it doesn't matter if
the decompression is slow for me because it's okay to do it one sample at a
time, every 1/8000th of a second (for storing and playing sounds). This might
be my next project after the exams end.</li>
</ol>
<p>I learnt a <strong>lot</strong> of things with this project. I got a glimpse of the immense
mathematical complexity that is hidden underneath the abstractions and the tools
of compression. I learnt a lot more about gzip compression and LZ77 algorithm. I
learnt how a code can be slow, and
<a href="https://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art007" target="_blank" rel="noopener noreferrer">how to make it faster</a>.
But new things were not all that I learnt. I got to learn more about the good
old C++. It's various idiosyncrasies, it's weaknesses and strengths, memory
management, code organisation and better use of test programs. I know, I still
have a long way to go, but this project has been a important step towards that
destination.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Maybe those really were the good old days]]></title>
            <link>https://bynirav.com/blog/maybe-those-really-were-the-good-old-days</link>
            <guid>https://bynirav.com/blog/maybe-those-really-were-the-good-old-days</guid>
            <pubDate>Sun, 27 Jan 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[This line popped in my head yesterday with no context whatsoever. Then I spent]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" src="https://bynirav.com/assets/images/DT9036-d6802bf7f90116dcf1dd7e31857b6003.jpg" width="3811" height="2542" class="img_ev3q"></p>
<p>This line popped in my head yesterday with no context whatsoever. Then I spent
the next many hours trying to remember where I'd read it. The answer came just
as suddenly. This line is from the book "Hear the Wind Sing" by Haruki Murakami.</p>
<!-- -->
<p>I love how it evokes a sense of deep longing for the past. In many ways, I think
this line is the essence of the entire novel. Time erodes away the humdrum
reality from memories and leaves you with fragments of faded images. Nostalgia
colors everything in warm hues of the sunset. When you revisit these flimsy
translucent images, you yearn to be in them. A sweet ache; a dull craving to
exist in that distorted universe. The prospects of disappearing into the fog of
past, where nothing ever surprises.</p>
<p>The novel is beautiful in it's entirety. I find myself rereading it during sunny
afternoons as the tea is boiling and the laundry has been done.</p>]]></content:encoded>
            <category>writing</category>
        </item>
    </channel>
</rss>