<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CS Journey's RSS Feed]]></title><description><![CDATA[CS Journey's RSS Feed]]></description><link>https://abhirath.me</link><generator>GatsbyJS</generator><lastBuildDate>Sun, 01 Feb 2026 06:56:48 GMT</lastBuildDate><item><title><![CDATA[Life's Great. Things Could Always Get a Whole Lot Worse - Stories from 2025.]]></title><description><![CDATA[Life’s great as it is. Every time I look back at the year that passed, I’m reminded that things could get a whole lot worse. 2025 hit a…]]></description><link>https://abhirath.me/things-could-get-worse-stories-2025/</link><guid isPermaLink="false">e6e60ae2-1d10-4c53-b9fc-998de506c349</guid><pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Life’s great as it is. Every time I look back at the year that passed, I’m reminded that things could get a whole lot worse. 2025 hit a little different.&lt;/p&gt;
&lt;p&gt;This isn’t to say that I didn’t come across happy stories in 2025. Maybe for another time.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;A stark reminder that life’s been great despite a few challenges.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A friend whose saving had been depleted by her family on wasteful expenditure while her brother’s salary remained untouched.&lt;/li&gt;
&lt;li&gt;A student who’s the sole breadwinner at his home after his dad. Working multiple jobs and taking on loans for an event only for the outcome to be less than ideal.&lt;/li&gt;
&lt;li&gt;A random Google search to learn more about a man who provided me some information over a WhatsApp group. Turns out he’s a 83 year old gentleman helping out people all over India while being a caregiver for his daughter for over 30 years. He runs a WhatsApp group, patiently types out super long replies despite having tremors in his hands, get on calls to provide encouragement and words of support, advocates for rights and has played a role in changing laws. He was also a caregiver for his late wife during her battle with cancer - Amrit Sir &lt;a href=&quot;https://www.instagram.com/p/DLAWO1dT6Jd/&quot;&gt;1&lt;/a&gt; &lt;a href=&quot;https://www.instagram.com/reel/DA-t8gJtC77/&quot;&gt;2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4e708ac033c8f854acb5c818b14489d1/47311/amrit-sir.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAABA//aAAwDAQACEAMQAAABrvzokXCxp//EABsQAAICAwEAAAAAAAAAAAAAAAERAAIDEiET/9oACAEBAAEFAq+4CzkGvduC7jU//8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEDESH/2gAIAQMBAT8Bcdmn/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bh//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhEhIP/aAAgBAQAGPwKksNnEfH//xAAbEAEAAgIDAAAAAAAAAAAAAAABABExQSFR0f/aAAgBAQABPyGnpaYgRQswh5ECUu9RR2l14xBiif/aAAwDAQACAAMAAAAQK/8A/8QAGREBAAIDAAAAAAAAAAAAAAAAAQARIZHh/9oACAEDAQE/EFV412ACp//EABURAQEAAAAAAAAAAAAAAAAAAAAh/9oACAECAQE/ECP/xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMVFhgf/aAAgBAQABPxAKILcLLvxFDqDCemHzAhRR8gboutWKEJxrCFFHJ//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;amrit-sir&quot;
        title=&quot;&quot;
        src=&quot;/static/4e708ac033c8f854acb5c818b14489d1/1c72d/amrit-sir.jpg&quot;
        srcset=&quot;/static/4e708ac033c8f854acb5c818b14489d1/a80bd/amrit-sir.jpg 148w,
/static/4e708ac033c8f854acb5c818b14489d1/1c91a/amrit-sir.jpg 295w,
/static/4e708ac033c8f854acb5c818b14489d1/1c72d/amrit-sir.jpg 590w,
/static/4e708ac033c8f854acb5c818b14489d1/a8a14/amrit-sir.jpg 885w,
/static/4e708ac033c8f854acb5c818b14489d1/47311/amrit-sir.jpg 1080w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A friend (Doctor) who put her own treatment at hold because she’d been helping address financial constraints at home.&lt;/li&gt;
&lt;li&gt;A conversation with a 74 year old mother who’s worried about the survival of her n year old son (PMI - Personal with Mental Illness) when she and her husband stop being around. They’re looking to move to a different city and exhaust their savings to live in an assisted living facility where their son will be taken care of after them.&lt;/li&gt;
&lt;li&gt;A caregiver recounting the story of her son (unmarried) who believes he has to travel to a certain country to find his lost wife and kid.&lt;/li&gt;
&lt;li&gt;Stumbled up this &lt;a href=&quot;https://www.reddit.com/r/AskReddit/comments/qlcvr7/how_old_are_you_and_what_is_the_biggest_problem/&quot;&gt;Reddit post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A Doctor shared a story about his PMI who believed that she ruled a certain country and had to get there. She lives alone in India and manages by herself while her family lives abroad.&lt;/li&gt;
&lt;li&gt;A mental rehabilitation nurse showing the ward with PMIs who had arrangements to live there for life (for various reasons).&lt;/li&gt;
&lt;li&gt;Sharings from strangers in a WhatsApp group. Stories about a mom taking care of her son, stories of a mom and daughter admitted in psychiatric wards and so on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2520b0b2b6073996baf53fac6262db4c/9d3af/sharing.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.64864864864865%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHNmUljD//EABcQAAMBAAAAAAAAAAAAAAAAAAABEAL/2gAIAQEAAQUCHHMn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAAAEgMUH/2gAIAQEABj8C0px//8QAGxAAAgMAAwAAAAAAAAAAAAAAAAERMVEhgZH/2gAIAQEAAT8hlZ4OTDpoZzZL0of/2gAMAwEAAgADAAAAEGgv/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QV//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB4QAAICAgIDAAAAAAAAAAAAAAEhABExkVFhccHR/9oACAEBAAE/EAjD4fIAQRcV6goWMjBli252NxjJbn//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;sharing&quot;
        title=&quot;&quot;
        src=&quot;/static/2520b0b2b6073996baf53fac6262db4c/1c72d/sharing.jpg&quot;
        srcset=&quot;/static/2520b0b2b6073996baf53fac6262db4c/a80bd/sharing.jpg 148w,
/static/2520b0b2b6073996baf53fac6262db4c/1c91a/sharing.jpg 295w,
/static/2520b0b2b6073996baf53fac6262db4c/1c72d/sharing.jpg 590w,
/static/2520b0b2b6073996baf53fac6262db4c/9d3af/sharing.jpg 878w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A friend who’s been depressed, working a really stressful job, has monetary constraints but still had to be on a leave of abscence to tend to her own health. To top this multiple family members have been falling sick.&lt;/li&gt;
&lt;li&gt;A fellow caregiver who’s been trying to get her brother treated from the last x years, but to no avail. She has since given up on the medical system and has been resorting to spirituality as a means to cope.&lt;/li&gt;
&lt;li&gt;A Doctor shared the story of a patient who’s been confined to the walls of a hospital for the last 12 years but hasn’t been responding to Meds.&lt;/li&gt;
&lt;li&gt;2 perfectly normal seeming friends who’ve experienced intense psychosis.&lt;/li&gt;
&lt;li&gt;A friend’s sibling who needed to be admitted and undergo ECT (shock treatment) to treat MDD from a certain trauma.&lt;/li&gt;
&lt;li&gt;A relative who’s been living in delusions at a time before new age medicines for the same. Violence at the mental rehabilitation facilities, shock treatment been through it all.&lt;/li&gt;
&lt;li&gt;A relative’s young daughter who passed away in an unfortunate car accident.&lt;/li&gt;
&lt;li&gt;A friend (Doctor) recalling patients suffering from cerebral palsy, still needing assistance in their 30s with basic hygiene, parents holding on to hope and having to break the news to them&lt;/li&gt;
&lt;li&gt;A friend’s brother and his battle with addiction.&lt;/li&gt;
&lt;li&gt;A student’s young relative and his recovery from hallucinations and being on the journey to become a Doctor. More power to him.&lt;/li&gt;
&lt;li&gt;A student’s mom’s stint with talking walls.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Really puts things into perspective.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Song Analysis - Fix You by Coldplay]]></title><description><![CDATA[Lyrics copied verbatim from Genius. General Slow, Time Signature: 4/4 Major Scale Diatonic Chords Short Chorus Really picks up after the 2nd…]]></description><link>https://abhirath.me/song-analysis-fix-you-coldplay/</link><guid isPermaLink="false">d9d4e406-c42d-42b1-9a53-859360fb57ce</guid><pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lyrics copied verbatim from &lt;a href=&quot;https://genius.com/Coldplay-fix-you-lyrics&quot;&gt;Genius&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;General&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Slow, Time Signature: 4/4&lt;/li&gt;
&lt;li&gt;Major Scale Diatonic Chords&lt;/li&gt;
&lt;li&gt;Short Chorus&lt;/li&gt;
&lt;li&gt;Really picks up after the 2nd Chorus&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Verse 1 and 2&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;When you try your best, but you don’t succeed&lt;br&gt;
When you get what you want, but not what you need&lt;br&gt;
When you feel so tired, but you can’t sleep&lt;br&gt;
Stuck in reverse&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;And the tears come streamin’ down your face&lt;br&gt;
When you lose somethin’ you can’t replace&lt;br&gt;
When you love someone, but it goes to waste&lt;br&gt;
Could it be worse?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Rhymes&lt;/li&gt;
&lt;li&gt;Grouped similar beat and melodic triplets
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;try your best&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;succeed&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;what you want&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;what you need&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Repetition - &lt;code class=&quot;language-text&quot;&gt;when you&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;but you&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ambient chords&lt;/li&gt;
&lt;li&gt;Verse 2 the harmonies are more prominent&lt;/li&gt;
&lt;li&gt;Overall the pitch range is small. However there are a few big jumps in pitch
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;when you&lt;/code&gt; -&gt; &lt;code class=&quot;language-text&quot;&gt;try&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Chorus 1&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Lights will guide you home&lt;br&gt;
And ignite your bones&lt;br&gt;
And I will try to fix you&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Similar beat &amp;#x26; melodic structure&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;guide you home&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;ignite your bones&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Addition of keys to the harmony&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Song title used&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Overall pitch range similar to the Verse&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Song Analysis - Baarishein by Anuv Jain]]></title><description><![CDATA[Lyrics copied verbatim from Genius. General Slow, Time Signature: 4/4 Prominent vocals Chord Progression: 4 chords  from the Major Scale…]]></description><link>https://abhirath.me/song-analysis-baarishein-anuv-jain/</link><guid isPermaLink="false">fa284f0c-552c-4dca-b620-ad06a9226ae2</guid><pubDate>Fri, 02 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lyrics copied verbatim from &lt;a href=&quot;https://genius.com/Genius-romanizations-anuv-jain-baarishein-romanized-lyrics&quot;&gt;Genius&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;General&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Slow, Time Signature: 4/4&lt;/li&gt;
&lt;li&gt;Prominent vocals&lt;/li&gt;
&lt;li&gt;Chord Progression: 4 chords &lt;code class=&quot;language-text&quot;&gt;I vi IV V&lt;/code&gt; from the Major Scale throughout the song&lt;/li&gt;
&lt;li&gt;Feels like there’s a key change from &lt;code class=&quot;language-text&quot;&gt;Ab tere bina yahan meri saansein&lt;/code&gt; but after referring a few sites doesn’t seem to be the case&lt;/li&gt;
&lt;li&gt;Chorus doesn’t repeat which is unusual for a pop song&lt;/li&gt;
&lt;li&gt;Doesn’t loop back to the chorus, keeps progressing forward. Climax at the Bridge and fades in the outro.&lt;/li&gt;
&lt;li&gt;Breathy exhales/donkey breathing at the end of few lines&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Verse 1&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Haule se, dheeme se&lt;br&gt;
Mujhko baahon mein bhar lo na tum&lt;br&gt;
Narm si saanson mai&lt;br&gt;
Mujhko aahon main bhar lo na tum&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Filled with rhymes (internal and strong)&lt;/li&gt;
&lt;li&gt;Minimal harmonies - ambient sustained wobbly chords at the 1 beat&lt;/li&gt;
&lt;li&gt;Simple beat (a shaker)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Chorus 1&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Sun zara, mere paas aa&lt;br&gt;
Ab baithe hain hum bhi yahaan&lt;br&gt;
Dil ke darmiyaan&lt;br&gt;
Baarishein hain, baarishein hain&lt;br&gt;
Teri hi baaton pe maine saja li hai duniya yahaan&lt;br&gt;
Dil ke darmiyaan&lt;br&gt;
Baarishein hain, baarishein&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Almost felt that it’s at the same intensity as the Verse&lt;/li&gt;
&lt;li&gt;Chorus made stronger by repetition &lt;code class=&quot;language-text&quot;&gt;Dil ke darmiyaan Baarishein hain, baarishein hain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Repetition of the song’s name&lt;/li&gt;
&lt;li&gt;Call to action? &lt;code class=&quot;language-text&quot;&gt;Sun zara, mere paas aa&lt;/code&gt;..&lt;/li&gt;
&lt;li&gt;Scene setting &lt;code class=&quot;language-text&quot;&gt;Ab baithe hain hum bhi yahaan&lt;/code&gt;..&lt;/li&gt;
&lt;li&gt;Exaggeration and metaphors&lt;/li&gt;
&lt;li&gt;Some phrases have backing vocals. Eg: &lt;code class=&quot;language-text&quot;&gt;Sun zara&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Baarishein hain&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bridge&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Ab tere bina yahan meri saansein&lt;br&gt;
Jaise bina nindiya ki raatein hain toh&lt;br&gt;
Aur tu hi mere dil ki raza hai&lt;br&gt;
Tere bina dil bhi khafa hai toh&lt;br&gt;
Teri aankhon ka kajal na faile ab kabhi bhi&lt;br&gt;
Tujhe itna pyaar doon, haan&lt;br&gt;
Teri khushiyon ki khatir yeh duniya main meri&lt;br&gt;
Ek pal mein waar doon main&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Picks up a little after the Verse 2. 8 bars of just chords and rhythm before breaking into the Bridge&lt;/li&gt;
&lt;li&gt;On referencing a few sites, here the first chord is a &lt;code class=&quot;language-text&quot;&gt;IV&lt;/code&gt; and he sings higher giving the illusion of a key change&lt;/li&gt;
&lt;li&gt;Imagery and metaphor &lt;code class=&quot;language-text&quot;&gt;Teri aankhon ka kajal..&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Outro&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Ab bikhri teri ye zulfon se aankhein teri jab dikhti hain&lt;br&gt;
Dikhta hai mujhe woh aasmaan&lt;br&gt;
Ki kholun pankh main mere, ud jaaun main, kho jaaun main&lt;br&gt;
Iss aasmaan main patangon ki tarha, haan&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Simile - &lt;code class=&quot;language-text&quot;&gt;aankhein teri jab dikhti hain Dikhta hai mujhe woh aasmaan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remarkedly lower energy from the bridge indicating the end&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Song Analysis - Perfect by Ed Sheeran]]></title><description><![CDATA[Lyrics copied verbatim from Genius. General Slow, waltz like rhythm, 3/4 Triplets, prominent vocals Time Signature: 6/8 because it fits…]]></description><link>https://abhirath.me/song-analysis-perfect-ed-sheeran/</link><guid isPermaLink="false">a140620d-7c14-46b5-b692-783e5b5857e8</guid><pubDate>Sat, 27 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lyrics copied verbatim from &lt;a href=&quot;https://genius.com/Ed-sheeran-perfect-lyrics&quot;&gt;Genius&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;General&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Slow, waltz like rhythm, 3/4&lt;/li&gt;
&lt;li&gt;Triplets, prominent vocals&lt;/li&gt;
&lt;li&gt;Time Signature: 6/8 because it fits better with the lyrics&lt;/li&gt;
&lt;li&gt;Chord Progression: 4 chords &lt;code class=&quot;language-text&quot;&gt;I vi IV V&lt;/code&gt; from the Major Scale throughout the song&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=O1IBpqTJQDU&quot;&gt;Ending the Chorus with Tonight&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Verse&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;I found a love for me&lt;br&gt;
Oh, darlin’, just dive right in and follow my lead&lt;br&gt;
Well, I found a girl, beautiful and sweet&lt;br&gt;
Oh, I never knew you were the someone waitin’ for me&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Filled with rhymes
&lt;ul&gt;
&lt;li&gt;me, lead, sweet, me (weak rhymes and strong rhymes)&lt;/li&gt;
&lt;li&gt;found - love, dive - right, love, love - follow, knew - you, never - were (weak rhymes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Call to Action
&lt;ul&gt;
&lt;li&gt;follow my lead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Harmonies are minimal. Can just hear a guitar&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pre-Chorus&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;‘Cause we were just kids when we fell in love&lt;br&gt;
Not knowin’ what it was&lt;br&gt;
I will not give you up this time&lt;br&gt;
But, darlin’, just kiss me slow&lt;br&gt;
Your heart is all I own&lt;br&gt;
And in your eyes, you’re holdin’ mine&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Stronger than the verse&lt;/li&gt;
&lt;li&gt;Again, filled with rhymes (eyes - mine, slow - own etc)&lt;/li&gt;
&lt;li&gt;kiss me slow, heart, in your eyes (imagery?)&lt;/li&gt;
&lt;li&gt;Harmony addition: Dreamy/ambient textured Chords at the 1 beat&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Chorus&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Baby, I’m dancin’ in the dark with you between my arms&lt;br&gt;
Barefoot on the grass while listenin’ to our favourite song&lt;br&gt;
When you said you looked a mess, I whispered underneath my breath&lt;br&gt;
But you heard it, “Darlin’, you look perfect tonight”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Vocals a lot higher. Verse and Pre-Chorus were kept low to create space for the Chorus.&lt;/li&gt;
&lt;li&gt;Melodic tension
&lt;ul&gt;
&lt;li&gt;Dancin in the dark - minor 2nd tension to root, 7th to root&lt;/li&gt;
&lt;li&gt;Barefoot on the grass - same as above&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Vivid descriptions of the scene engaging multiple senses.
&lt;ul&gt;
&lt;li&gt;between my arms, barefoot on the grass (touch)&lt;/li&gt;
&lt;li&gt;favourite song, whispered underneath my breath (sound)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=O1IBpqTJQDU&quot;&gt;Ending the Chorus with Tonight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Harmony - The ambient chords are a lot more prominent.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[(WIP) Python cachetools - Source Code Walk]]></title><description><![CDATA[I’ve been wanting to get back to reading papers and open source code for some time now.
As part of a workshop conducted by a friend, I’ve…]]></description><link>https://abhirath.me/python-cache-tools-source-code-walk/</link><guid isPermaLink="false">783269f6-4463-4b93-b03e-b846ce19bb57</guid><pubDate>Mon, 08 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been wanting to get back to reading papers and open source code for some time now.
As part of a &lt;a href=&quot;https://rationalityworkshops.com/workshops&quot;&gt;workshop&lt;/a&gt; conducted by a friend, I’ve set a goal of grokking 12 pieces over the next 12 months.&lt;/p&gt;
&lt;p&gt;A piece meets the criteria if&lt;br&gt;
- It excites me (or)&lt;br&gt;
- It’s around a problem I’m interested in (or)&lt;br&gt;
- It has some side benefit (career or otherwise)&lt;/p&gt;
&lt;p&gt;My goal for this week is to finalise at least 4 pieces from my bookmarks and notes.&lt;/p&gt;
&lt;p&gt;Vatsal has created a small accountability group to ratchet up the pressure :D&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9f4580dfcf0ee93eed76ff3a12f12af6/47311/check-in.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 89.1891891891892%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAeakipNNmcjSHP8A/8QAGhAAAgIDAAAAAAAAAAAAAAAAAAEQIQMRMv/aAAgBAQABBQJUOzSlKMfR/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGRAAAgMBAAAAAAAAAAAAAAAAARAAITFB/9oACAEBAAY/Aqmh8ZX/xAAdEAACAgEFAAAAAAAAAAAAAAAAARFBECFRYXGB/9oACAEBAAE/IYO28diWBOoWm3o3yGQXm//aAAwDAQACAAMAAAAQi8C+/8QAFxEBAQEBAAAAAAAAAAAAAAAAEQEAEP/aAAgBAwEBPxAi5mvP/8QAFREBAQAAAAAAAAAAAAAAAAAAEAH/2gAIAQIBAT8QIf/EAB0QAQADAAIDAQAAAAAAAAAAAAEAESFBsVFhccH/2gAIAQEAAT8QIBthlai6dR6OoBbZebYkUpL5RUw37KH8lC8m7vD3Cf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;check in&quot;
        title=&quot;&quot;
        src=&quot;/static/9f4580dfcf0ee93eed76ff3a12f12af6/1c72d/check-in.jpg&quot;
        srcset=&quot;/static/9f4580dfcf0ee93eed76ff3a12f12af6/a80bd/check-in.jpg 148w,
/static/9f4580dfcf0ee93eed76ff3a12f12af6/1c91a/check-in.jpg 295w,
/static/9f4580dfcf0ee93eed76ff3a12f12af6/1c72d/check-in.jpg 590w,
/static/9f4580dfcf0ee93eed76ff3a12f12af6/a8a14/check-in.jpg 885w,
/static/9f4580dfcf0ee93eed76ff3a12f12af6/47311/check-in.jpg 1080w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And quoting his presentation, “If nothing works, you can just blackmail people to make them accountable.” :P&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;For the first piece, I’ve decided to start with a Python library that I find myself using often &lt;code class=&quot;language-text&quot;&gt;cachtools&lt;/code&gt;. I had a note as such: &lt;code class=&quot;language-text&quot;&gt;TTL Cache Python (timed dictionary)&lt;/code&gt; reminding me to check out the implementation.&lt;/p&gt;
&lt;p&gt;It’s a nifty library that provides caching functionality out of the box. It’s similar to &lt;code class=&quot;language-text&quot;&gt;Caffeine&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;Guava&lt;/code&gt; in the Java world.&lt;/p&gt;
&lt;p&gt;I generally start off by understanding the major data structures (&lt;a href=&quot;http://oldblog.antirez.com/post/redis-manifesto.html&quot;&gt;thanks Antirez&lt;/a&gt;) and going through the Unit Tests. However, since this code base is really small, I’ve decided to get answers for the following questions that were on my mind instead.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How does it maintain global state for every permutation/combination of configuration?&lt;/li&gt;
&lt;li&gt;How does it handle concurrency or does it just rely on the GIL?&lt;/li&gt;
&lt;li&gt;TTL - Does it run a janitor in the background or is it on demand?&lt;/li&gt;
&lt;li&gt;What sort of optimisation does it use to quickly delete expired items?&lt;/li&gt;
&lt;li&gt;How are equivalent deep/pass by reference objects handled when creating the hashkey?&lt;/li&gt;
&lt;li&gt;General re-usability patterns to handle different eviction policies.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Constraints are Real. For some Acceptance Comes after Hesitation.]]></title><description><![CDATA[I’ve been a cautious person in general for as long as I can remember. However, I’ve always felt that I’m immune to the realities of growing…]]></description><link>https://abhirath.me/constraints-are-real/</link><guid isPermaLink="false">b4e3e31b-99ad-40a7-9ab9-2157b7e9ddee</guid><pubDate>Thu, 29 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been a cautious person in general for as long as I can remember. However, I’ve always felt that I’m immune to the realities of growing up. I felt I could circumvent these outcomes with time management, discipline and control. Incredibly naive of me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Family getting older
&lt;ul&gt;
&lt;li&gt;I can minimise the impact of time by controlling their lives towards healthier habits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Losing touch with friends/family once I move to a different city
&lt;ul&gt;
&lt;li&gt;I will never tire. I could frequenly hop between Chennai and Bangalore&lt;/li&gt;
&lt;li&gt;I will create a rotation and talk to every friend group&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hadn’t seen death&lt;/li&gt;
&lt;li&gt;Overly optimistic about the time taken to accomplish goals
&lt;ul&gt;
&lt;li&gt;Will just work harder for a few more months and then I can go back to balanced life&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Also, time and again I’ve failed to change myself, what made me think I could change others 😅?&lt;/p&gt;
&lt;p&gt;This approach (call it Mr Sunshine or delusional living) hadn’t worked with teenage Abhirath and neither is it working now. Why do I cling to this mechanism? Have I just been trying to avoid the truth? I can’t have everything, heck even the few most important things in life are really difficult to acquire and maintain, it’s time to grow up.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Grandmother, Music and Memory]]></title><description><![CDATA[Music is powerful, music is lovely. So is my grandmother. Music has this strange effect where it brings back associated memories of the time…]]></description><link>https://abhirath.me/grandmother-music-memory/</link><guid isPermaLink="false">966a5aea-5d05-488e-9bad-3b6f5ad5d313</guid><pubDate>Sun, 25 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Music is powerful, music is lovely. So is my grandmother.&lt;/p&gt;
&lt;p&gt;Music has this strange effect where it brings back associated memories of the time and context one heard it in. Why the heck does one remember melodies from years ago? :D&lt;/p&gt;
&lt;p&gt;When I’m home with my family, it’s a given that I will be participating in a short drive for coffee. My grandmother decided to join us for a change. I fire-up some old Hindi hits on Spotify and enquire if she recognises them. Lo and behold, she murmurs out the name “Noor Jehan” and the song “Jawan Hain Mohabbat”.&lt;/p&gt;
&lt;p&gt;She hadn’t heard of or heard the song in more than 20 years. Amogst other things and grandfather passing away - 2024 and 2025 haven’t been easy on her on mentally.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fb5b07e4af231f63e71ff4099e3075b2/80e3c/dilip-kumar-songs.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 222.2972972972973%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAsABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwAEAf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABPN3uT2agSQdxIqNJhNLDH//EABoQAAMAAwEAAAAAAAAAAAAAAAABEQISIRD/2gAIAQEAAQUC4227wUuxsPJlKjL19NSF9//EABYRAQEBAAAAAAAAAAAAAAAAABABIf/aAAgBAwEBPwEhh//EABYRAAMAAAAAAAAAAAAAAAAAAAEgIf/aAAgBAgEBPwERv//EAB8QAAEDBAMBAAAAAAAAAAAAAAEAEBEhIjFBIDJRcf/aAAgBAQAGPwJGIgNdKMEATSjbbKHz1xdpdlkcP//EAB4QAQACAgIDAQAAAAAAAAAAAAEAETFBIXEQUYGR/9oACAEBAAE/IQ0Qq8WwX1wnSJF/CGAkqU8CUXj1L7jw0sc8SvphCHs8DIcIhcO1jXd1BZ2QyGmXP//aAAwDAQACAAMAAAAQ+xFzGC//xAAcEQEAAgEFAAAAAAAAAAAAAAABABEQITFBUWH/2gAIAQMBAT8QdtMJSV7BHEs6n//EABgRAAMBAQAAAAAAAAAAAAAAAAABESFR/9oACAECAQE/EI0yDWkI+kZ//8QAHxABAQACAgMAAwAAAAAAAAAAAREAITFRQWFxEIHx/9oACAEBAAE/EB5TJVJPAGPAoQqOg59+MrlOHBBxsUpTXrI7YgSiM2nhm3PvF4BCUaIY25fvBFJa6XrEjdncf58xDQzqv4gpIHO/nGeROA3PoWBAMQj1iXrlxa5//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;dilip-kumar-hits-music-memory&quot;
        title=&quot;&quot;
        src=&quot;/static/fb5b07e4af231f63e71ff4099e3075b2/1c72d/dilip-kumar-songs.jpg&quot;
        srcset=&quot;/static/fb5b07e4af231f63e71ff4099e3075b2/a80bd/dilip-kumar-songs.jpg 148w,
/static/fb5b07e4af231f63e71ff4099e3075b2/1c91a/dilip-kumar-songs.jpg 295w,
/static/fb5b07e4af231f63e71ff4099e3075b2/1c72d/dilip-kumar-songs.jpg 590w,
/static/fb5b07e4af231f63e71ff4099e3075b2/80e3c/dilip-kumar-songs.jpg 720w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Yet, music prevailed.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Portfolio - Live Algo Trading Platform]]></title><description><![CDATA[This is a small demonstration of a project I’ve been working on. Mainly meant to showcase it to interviewers or clients :)  Context Issues…]]></description><link>https://abhirath.me/portfolio-project-live-trading-distributed-platform/</link><guid isPermaLink="false">96235cce-533e-40a1-a4ac-1621e2c4d567</guid><pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a small demonstration of a project I’ve been working on. Mainly meant to showcase it to interviewers or clients :)&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABhElEQVR42pWSzXPSUBRHyWeHJC+GAkEg0IQQIBAIYKClFIfRdjqOdVzqSrd26f+/OIaoRbqyi9/czb3nnjf3lYxaC6fTx4smVNs+puthtwLsdoho+Whlk1Kp9P8pAF7Exeya9OoW0exg5SAzj+X1UQ3xMuBh+Lw3oRFnRIsNF/GSWjCmGia88uMToCRJKIqKpmnoul5EVdVToMifeRiuD9/gp1vm24/00xvG2Y5mcoUuKk/Nsixj2zaWZWMYJpYQmJb1DOgFhaE7XNAar1jvPrDa3DOZLelO15Sd+rFZkpEU7Wgsa/mSZ4ZOx6fWG+CGQ15HUxab93z7+p04WbK43OO4raOhWcXYPiJuHnF2PzD3Pznr7/8sk/4aetTDkNvrOUmaMFpmfHm45+7tljRbU3Pd3zbFkIJcdoooxqFWkHTj1HAa97jbzPi8XxEFHUaRz2U6YB6HBEEXIV74bd5lEz7lwGQ0oJHbVCrndL02od+l2XAxDQNZUVDyaz4lv7T6b9Rj/QWVX9sYDA2kpwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;algo-trading-login-screen&quot;
        title=&quot;&quot;
        src=&quot;/static/235107f8e4d61fb214df64fc79aed7d4/fcda8/login-screen.png&quot;
        srcset=&quot;/static/235107f8e4d61fb214df64fc79aed7d4/12f09/login-screen.png 148w,
/static/235107f8e4d61fb214df64fc79aed7d4/e4a3f/login-screen.png 295w,
/static/235107f8e4d61fb214df64fc79aed7d4/fcda8/login-screen.png 590w,
/static/235107f8e4d61fb214df64fc79aed7d4/efc66/login-screen.png 885w,
/static/235107f8e4d61fb214df64fc79aed7d4/c83ae/login-screen.png 1180w,
/static/235107f8e4d61fb214df64fc79aed7d4/8963a/login-screen.png 1918w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;Login Screen. &lt;a href=&quot;https://unsplash.com/@wildhoney&quot;&gt;Image Credits&lt;/a&gt;&lt;/p&gt;
&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#context&quot;&gt;Context&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#issues&quot;&gt;Issues with Paid APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#objectives&quot;&gt;Objectives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#features&quot;&gt;Features&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#distributed-web-sockets&quot;&gt;Distributed Web Sockets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#run-everywhere-control-anywhere&quot;&gt;Run Everywhere, Control Anywhere&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#centralised-risk-management&quot;&gt;Centralised Risk Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#unified-interface&quot;&gt;Unified Interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ease-of-access&quot;&gt;Ease of Access&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#tech-stack&quot;&gt;Tech Stack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;
&lt;h3 id=&quot;issues&quot;&gt;Issues with Paid APIs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Most algotrading APIs are quite restrictive. You can only call them a few times per minute. We can fetch prices of multiple scripts at once at the cost of making our code complex. Your classes and functions would start needing an additional higher order iterator to deal with a single class/function acting on one security.&lt;/li&gt;
&lt;li&gt;Real time prices -&gt; via blocking web sockets (one thread or process will need to be dedicated for this). Historical prices via REST API. This undeniably increases code complexity.&lt;/li&gt;
&lt;li&gt;Limits on the number of web socket connections -&gt; Each algo of yours would run as a separate process. Brokers limit the number of web socket connections to 3 or 5. This stops us from running more processes.&lt;/li&gt;
&lt;li&gt;Difficult to make it system agnostic (centralise using the cloud) given that in most cases we need our own custom handlers apart from the paid APIs.&lt;/li&gt;
&lt;li&gt;Restrictive clients provided by service providers.
&lt;ul&gt;
&lt;li&gt;Need to restart if a configuration change takes place.&lt;/li&gt;
&lt;li&gt;Difficult to parallelise.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Difficult to use multiple data providers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;objectives&quot;&gt;Objectives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;abstract away all the above mentioned complexities.&lt;/li&gt;
&lt;li&gt;cater to a much larger scale by relying on in-house infrastructure.&lt;/li&gt;
&lt;li&gt;smarter and faster client side code to better handle faults.&lt;/li&gt;
&lt;li&gt;one unified system to handle data from different service providers.&lt;/li&gt;
&lt;li&gt;reduce data provider cost.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;h3 id=&quot;distributed-web-sockets&quot;&gt;Distributed Web Sockets&lt;/h3&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABgUlEQVR42nVSXU/CQBAsJoaPQmlpS3t3/SYY4YEEjIiQqMQXnzTxR/m3x52DEjXxYXI3u7dzs3vnLJdLHI9HrFYraK2RZRmMMXbN8/yCoih+8RMkZhTyNEQ8dvHy/ASnmc3Q6/XQ7XXhugO4A8JFv9+H4zj/o9Ox65WnMF5/4Hr+iuVmD6euCkRRiLquYTIj++jsqITneRiNRgiCwLqfTCaW+74v3CAMfIyTCtn2HWr9hs1OHKrPL+S3dyhzjSRJMZ1OkUt78/kcaZpKLEEmFywWCytquYyjqioopZBMI+jIRzjq42F7D6e4WSHVmRUKw9CChWVZyj6ynMIUoHtyijLGPWPk3nCIx720TGfGnB6DSYKPUtUV4ji2nO1xJC2nM6NP42FMieBYBA+HAxzOi46Ivw5bR61DFrecoheH0p3nutjTId0w2R4gGGtmzUWQuZn8hp+CWumLYHoWtA6bprECdMUCgrwocjtX25Lk+Oqx8IhcLmjP84ySCwL5EbvdDt884+i6EzU7KAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;distributed-web-sockets&quot;
        title=&quot;&quot;
        src=&quot;/static/366e7f1c6fca89dd38d7a2819cde6f83/fcda8/distributed-web-sockets-live-prices.png&quot;
        srcset=&quot;/static/366e7f1c6fca89dd38d7a2819cde6f83/12f09/distributed-web-sockets-live-prices.png 148w,
/static/366e7f1c6fca89dd38d7a2819cde6f83/e4a3f/distributed-web-sockets-live-prices.png 295w,
/static/366e7f1c6fca89dd38d7a2819cde6f83/fcda8/distributed-web-sockets-live-prices.png 590w,
/static/366e7f1c6fca89dd38d7a2819cde6f83/efc66/distributed-web-sockets-live-prices.png 885w,
/static/366e7f1c6fca89dd38d7a2819cde6f83/c83ae/distributed-web-sockets-live-prices.png 1180w,
/static/366e7f1c6fca89dd38d7a2819cde6f83/8963a/distributed-web-sockets-live-prices.png 1918w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Separate group of processes exposed over an API.&lt;/li&gt;
&lt;li&gt;Go Lang is used to fetch real time prices over web sockets.&lt;/li&gt;
&lt;li&gt;Number of workers can be specified. For example you can ask it to get real time prices of 100 scripts using 3 workers. It would evenly split the load across 3 workers.&lt;/li&gt;
&lt;li&gt;Can be controlled using a REST API. New subscriptions can be added, existing instruments can be stopped without restarting the application.&lt;/li&gt;
&lt;li&gt;No disruptions because a restart isn’t needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;run-everywhere-control-anywhere&quot;&gt;Run Everywhere, Control from Anywhere&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;One can register any number of computers (laptops, EC2 instances, Docker containers) by running a small custom processmanager on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAuUlEQVR42q2RvRKCMBCEQ4JgIDnygwpKsMQ3oGPG93+oNWQsbchY7Ow1983tLdu2Deu6Yg4TwnSPeiCEcFjzPCdn3nu0iiCkAZcWRa3BhQDnHEVRHBbzzsJYByYkyjOh7foIE2CM5alzFxBpVKcSpBWG2xVVVaULs4D0euMZRoTvD5ZlwTgMkLLJA9oY1zkHa23yvvcwxqCu6zxgv5fStjGuhlIKOjoRoWkyL9yXswv4HdmmIVX+B+AHbd3Cez5rLAIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;list-of-systems&quot;
        title=&quot;&quot;
        src=&quot;/static/8a8955b726add1a7e65c7ab5596d3280/fcda8/list-of-systems.png&quot;
        srcset=&quot;/static/8a8955b726add1a7e65c7ab5596d3280/12f09/list-of-systems.png 148w,
/static/8a8955b726add1a7e65c7ab5596d3280/e4a3f/list-of-systems.png 295w,
/static/8a8955b726add1a7e65c7ab5596d3280/fcda8/list-of-systems.png 590w,
/static/8a8955b726add1a7e65c7ab5596d3280/efc66/list-of-systems.png 885w,
/static/8a8955b726add1a7e65c7ab5596d3280/c83ae/list-of-systems.png 1180w,
/static/8a8955b726add1a7e65c7ab5596d3280/ec09f/list-of-systems.png 1916w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;
Quick Statistics of All Compute Running Algos
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can then be further expanded to get some more system statistics. You can also submit jobs/algos to execute on them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABX0lEQVR42p1S22qDQBTcGERTaeJ1vax3TYwaGkjaQAst5DUP/aN++3TPUkOhoZQ+DLPnrI5z5sj2+z3O5zOGYUAcx0jTVCHLsivyPL8JulPPxj64beH0dAQryxKcc4RhiCAIYFkWDMOAruvQNE1hNpuBMfYD87kG3TBxt36FMVxQ9FIwzwSqqsIw7lDVDTzPRRRFkj04jgPbttUHqXZdV9XL5RKr1QpcGvACDj6+ITpcsDu+gIlmQJrlatxECPi+j6IoIOSZxiHuug6bzQZt26o76pMJ6qmxIx8Jd/B4PIAl7x/I6i2qXGYhcyFX5IQcTaAegc6T28kxsS+d3kvXfd+DZXmBthtxOD2jqWuVI7kknkAixJSz+Jrie5+YIhjHUQqmAlGxRrl9UILkhJZimuafsVgs1PJq+T5LEoEkCtFUJZqmUVu+tdHfMP0FlC2jcElUyCKU2/2PILkjpoV9Am2m3iBHF2oQAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;detailed-view-submit-algos&quot;
        title=&quot;&quot;
        src=&quot;/static/4029b8066df9aa1fd40b080522d2297c/fcda8/system-details-submit-job.png&quot;
        srcset=&quot;/static/4029b8066df9aa1fd40b080522d2297c/12f09/system-details-submit-job.png 148w,
/static/4029b8066df9aa1fd40b080522d2297c/e4a3f/system-details-submit-job.png 295w,
/static/4029b8066df9aa1fd40b080522d2297c/fcda8/system-details-submit-job.png 590w,
/static/4029b8066df9aa1fd40b080522d2297c/efc66/system-details-submit-job.png 885w,
/static/4029b8066df9aa1fd40b080522d2297c/c83ae/system-details-submit-job.png 1180w,
/static/4029b8066df9aa1fd40b080522d2297c/8963a/system-details-submit-job.png 1918w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;Start and Stop Individual Tasks on Each Computer&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This makes it really convinient to start and stop algos without having to SSH into servers, logging into your laptop. One can login from anywhere and keep track of various on-going tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;centralised-risk-management&quot;&gt;Centralised Risk Management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Risk management should be centralised. The various algos running should communicate with each other and take informed decisions.&lt;/li&gt;
&lt;li&gt;One can observe max risk change everyday and spot trends.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABQElEQVR42pWQyW7CQBBEh0WywUbG9njfsCEcIiEsIiJOKLnlE/IT+f9jZaotFESIUA6lcY+rX1ePen5q8f52xm63Q5ZlKMvy36rrGkmS4HQ6QbXnT1iLELOZBc/zYFkWJpMJptMpxuMxlFIPRf9oNELbtgb48QVXl/AWDoIggOu6cBwH8/ncDJnBtm2pec871rcavDa22y1UnfioykLoeZajyIdvrsInKIoCm81GzOLJ81+it6oq9H1vgM1gYtNqtUKaplITFoYhtNZyMv2lvlUUxwiWS/T7PdQF0jSNgGLzkzA+8gUQUVEEHem7QPb4Bng8HqEYlaBuvZb1COJJqMCiGDqrBfiXZLjvD8ChOUXXdZIyTX+AktA0hFlzN9l1Qq78SiBBTMjVeSZmfU6kaKSiJJd3ulZ8JXoDk/DlcMA392/js8mBxmoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;centralised-risk-management&quot;
        title=&quot;&quot;
        src=&quot;/static/150aac32cc7504538f99815be7d7146c/fcda8/centralised-risk-management.png&quot;
        srcset=&quot;/static/150aac32cc7504538f99815be7d7146c/12f09/centralised-risk-management.png 148w,
/static/150aac32cc7504538f99815be7d7146c/e4a3f/centralised-risk-management.png 295w,
/static/150aac32cc7504538f99815be7d7146c/fcda8/centralised-risk-management.png 590w,
/static/150aac32cc7504538f99815be7d7146c/efc66/centralised-risk-management.png 885w,
/static/150aac32cc7504538f99815be7d7146c/c83ae/centralised-risk-management.png 1180w,
/static/150aac32cc7504538f99815be7d7146c/769f8/centralised-risk-management.png 1924w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;Money at Risk by Each Algo Segregated by Stock&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dashboard to tune risk and drawdown.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAXElEQVR42p2OOQ4AIQwDw6mEo4MmC/9/pheQ9gFLMbbcWEMhBDjnYIyBtfY0Ed3Te0drDSkl5JwRY4T3/ootRqqKMR7MObHP92kp5Te1VogIiFcI8xm8+tbuM3wBVjJV49Y5Rm8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;risk-drawdown-settings&quot;
        title=&quot;&quot;
        src=&quot;/static/79dfed0ad3224f8f432a6c0740941818/fcda8/risk-settings.png&quot;
        srcset=&quot;/static/79dfed0ad3224f8f432a6c0740941818/12f09/risk-settings.png 148w,
/static/79dfed0ad3224f8f432a6c0740941818/e4a3f/risk-settings.png 295w,
/static/79dfed0ad3224f8f432a6c0740941818/fcda8/risk-settings.png 590w,
/static/79dfed0ad3224f8f432a6c0740941818/efc66/risk-settings.png 885w,
/static/79dfed0ad3224f8f432a6c0740941818/c83ae/risk-settings.png 1180w,
/static/79dfed0ad3224f8f432a6c0740941818/575bd/risk-settings.png 1791w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABLklEQVR42pWRUWvCMBSFI4pSkbZmMYlJ09SKYyodjA0bZh11RRjs//+es6YKPto9fA95yHfuuZfsdjucz2cURQGtNYwx/8ZaC845mqYByfMcQRAgmE4xmUwwHA4xGo0wGAx64/8QQrDf7+/COGaI4gWiMOreXtqX8XjcCX1L4kcWgmP7LLDJKaRcgLEnUEp7wxjDtG14OBxA0jSFbIW1E/h8p92U8Zx3O+mLlBJhGMI5B2JtBrUUaI4GdfmEy3GOj1eKOWVYtMmsB146m81QluW1shf+NgY/tcF3laFyGWyqsVwqKPWYJEm66lVVgWidQLQJb4XCV9me3jFcHMXKCnAhuzqP8NIoilDX9fXKSmms1y9Y5Vtk6QaGp/BBPvmKQWJuJHfMDX8Hv57T6YQ/jcrmpSHDXk8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;zerodha-settings&quot;
        title=&quot;&quot;
        src=&quot;/static/932b4e6856d4615dc0878f6f512aa0b2/fcda8/zerodha-settings.png&quot;
        srcset=&quot;/static/932b4e6856d4615dc0878f6f512aa0b2/12f09/zerodha-settings.png 148w,
/static/932b4e6856d4615dc0878f6f512aa0b2/e4a3f/zerodha-settings.png 295w,
/static/932b4e6856d4615dc0878f6f512aa0b2/fcda8/zerodha-settings.png 590w,
/static/932b4e6856d4615dc0878f6f512aa0b2/efc66/zerodha-settings.png 885w,
/static/932b4e6856d4615dc0878f6f512aa0b2/c83ae/zerodha-settings.png 1180w,
/static/932b4e6856d4615dc0878f6f512aa0b2/7ebf9/zerodha-settings.png 1919w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAA9ElEQVR42p2Sy06FMBCGixgupdzO4VZpe+AQMEExGBfqxo3P4ML3f5BfBhLX1sWXSZO5/H9nWNd18H0f59MJsmkQhiEYY3Ac58+4rrvXDMMAZoxBnuc4FzU4F4iiCHEcW5GmKTzPwzzPYEppKNXi4/2K50XDXDpora0gUc3mbl3XQyE9prGHVhJVVVlT1zWyLMOyLEdDKSW0uaAoyo3CmrIskQiOx4fNctu2+xSKNInUUoINVJ/dXfH08kp/qPal/EfZr0Li7Rvr59fRkPzLRu5RCGG95SRJ4N06uJ9GsL7vIWKxq6QbDILAGs7D7R5vMI4TfgCZedxLEEeH2QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;profile-settings&quot;
        title=&quot;&quot;
        src=&quot;/static/407aead386bdda1cffb4a22b5b2fd49c/fcda8/profile-settings.png&quot;
        srcset=&quot;/static/407aead386bdda1cffb4a22b5b2fd49c/12f09/profile-settings.png 148w,
/static/407aead386bdda1cffb4a22b5b2fd49c/e4a3f/profile-settings.png 295w,
/static/407aead386bdda1cffb4a22b5b2fd49c/fcda8/profile-settings.png 590w,
/static/407aead386bdda1cffb4a22b5b2fd49c/efc66/profile-settings.png 885w,
/static/407aead386bdda1cffb4a22b5b2fd49c/c83ae/profile-settings.png 1180w,
/static/407aead386bdda1cffb4a22b5b2fd49c/ec09f/profile-settings.png 1916w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;unified-interface&quot;&gt;Unified Interface&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sensible intuitive APIs. One API for both real time and historical prices using real time workers. Makes writing programs a lot easier.&lt;/li&gt;
&lt;li&gt;Can easily be expanded to support multiple data providers using bridges and adapters.
&lt;ul&gt;
&lt;li&gt;Extendienble normalised data models for the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ease-of-access&quot;&gt;Ease of Access&lt;/h3&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA3UlEQVR42q3PzWqEMBQF4BgRLBglxsmPJhrERakMlDLr4gN03W3f/ylOrzpMu2ini7r4uOQuTs5l8zxjWRas01qL1nt03/g7uq7beKfhtYRvDViMEUopdG0Lt6pr2LKErSpImoKUPxBCQDUNrG5QjS84vX5AxOdrIIU453Za40Tv1bqv72goUKkacXjC5fKGEB7B+r6HlHIPo5ONMdvvBRF/KMlDUeBM17xbg1kUe8Msy8AYO8Y4jv8OTAhPkm2yYRiObRhCODZwmibkeY6EKnPOf5GCp1f8S3rDbz4BkG3MDXDQCM0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;token-details-ease-of-access&quot;
        title=&quot;&quot;
        src=&quot;/static/0320a34dbdf9682c20b3f95b5b44ce4f/fcda8/token-details.png&quot;
        srcset=&quot;/static/0320a34dbdf9682c20b3f95b5b44ce4f/12f09/token-details.png 148w,
/static/0320a34dbdf9682c20b3f95b5b44ce4f/e4a3f/token-details.png 295w,
/static/0320a34dbdf9682c20b3f95b5b44ce4f/fcda8/token-details.png 590w,
/static/0320a34dbdf9682c20b3f95b5b44ce4f/efc66/token-details.png 885w,
/static/0320a34dbdf9682c20b3f95b5b44ce4f/c83ae/token-details.png 1180w,
/static/0320a34dbdf9682c20b3f95b5b44ce4f/8963a/token-details.png 1918w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;Shortcuts on the Home Page to Perform Everyday Actions&lt;/p&gt;
&lt;h2 id=&quot;tech-stack&quot;&gt;Tech Stack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Languages Used&lt;/strong&gt;: Go, Python, Node.js&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Databases Used&lt;/strong&gt;: Cassandra, PostgreSQL, MongoDB, Redis&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Libraries and Frameworks&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt;: Flask, numpy, pandas, APScheduler, multiprocessing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node.js&lt;/strong&gt;: React, Ant UI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt;: Go Gin, KiteConnect, gabs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Quite a few places required intricate parallel or concurrent code with coordination using locks, semaphores and databases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Data cleaning, finding the optimal update periods to reduce intervals of stale data and network cost.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Complex functional and object oriented paradigms for client algo classes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Learning to Think in React by Building a Shopping Cart]]></title><description><![CDATA[I’ve noticed time and again that people don’t really understand the reason/history behind frameworks like React, Angular, Vue etc. It’s a…]]></description><link>https://abhirath.me/react-shopping-cart-learning-to-think-in-react-vanilla-javascript/</link><guid isPermaLink="false">068411ba-112e-4da6-ad60-d90205de8fda</guid><pubDate>Mon, 03 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve noticed time and again that people don’t really understand the reason/history behind frameworks like React, Angular, Vue etc. It’s a different paradigm altogether (compared to Vanilla JavaScript or jQuery).&lt;/p&gt;
&lt;p&gt;To really appreciate these tools, you’ll have to build complex user interactions and try keeping data and UI in sync using Vanilla JavaScript. You’ll quickly realise that apart from mutating data (shopping cart amount, product quantity), you’re forced to write boilerplate to change the HTML (store references to IDs and change &lt;code class=&quot;language-text&quot;&gt;.innerText&lt;/code&gt;). You are also forced to iterate and find documents within deep nested structures. Things are already complex and now we add API calls with error handling, loading spinners, notifications and modals to the mix.&lt;/p&gt;
&lt;p&gt;Let’s build a shopping cart. First using Vanilla JavaScript and then the same cart using React 😊 My objective is to help you appreciate these tools, the pain points they solve, how they help with re-usability and learning to think in their paradigms.&lt;/p&gt;
&lt;p&gt;Here’s the video of me coding and explaining the difference between both the approaches. Feel free to post any questions or comments.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/LDKnz5gwdz4&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/LDKnz5gwdz4&quot;&gt;YouTube Link&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[30 Days Road Map - Budding Front End Developer to your First Job]]></title><description><![CDATA[A handy guide to take you through the journey from a budding front end developer to get ready for your first job. You should read this guide…]]></description><link>https://abhirath.me/30-days-from-budding-front-end-developer-to-first-job/</link><guid isPermaLink="false">d4e3a0db-f069-4eb0-a98b-5f96f0b7da4b</guid><pubDate>Wed, 06 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A handy guide to take you through the journey from a budding front end developer to get ready for your first job. You should read this guide if you already know the basics of front end development and are keen on bridging the gap between you and your first job as a junior developer.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 576px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ff0bfffe1e065f71b821e63fdac84635/ac097/road-map.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.24324324324324%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABf3LooJCp/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAECAxEhIv/aAAgBAQABBQKIjnWJZ4Rm1JpoOu//xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAwEBPwGI/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAIRIf/aAAgBAgEBPwHVyf/EABsQAAICAwEAAAAAAAAAAAAAAAABESECEDEy/9oACAEBAAY/AvSLyOopERr/xAAaEAEAAwADAAAAAAAAAAAAAAABABFBIXGh/9oACAEBAAE/IRXFe5yoWYNTL3gEAbUNpn//2gAMAwEAAgADAAAAECgf/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAB/9oACAEDAQE/EMwET//EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAECAQE/EFsP/8QAHRABAQACAQUAAAAAAAAAAAAAAREAIVFBYXGBkf/aAAgBAQABPxC5M3InzCAbgLK0GeWJFKdXa+8QpEEeNDjGkO+8/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;road-map-front-end-developer-job-ready&quot;
        title=&quot;&quot;
        src=&quot;/static/ff0bfffe1e065f71b821e63fdac84635/ac097/road-map.jpg&quot;
        srcset=&quot;/static/ff0bfffe1e065f71b821e63fdac84635/a80bd/road-map.jpg 148w,
/static/ff0bfffe1e065f71b821e63fdac84635/1c91a/road-map.jpg 295w,
/static/ff0bfffe1e065f71b821e63fdac84635/ac097/road-map.jpg 576w&quot;
        sizes=&quot;(max-width: 576px) 100vw, 576px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#what-do-they-look-for&quot;&gt;What do they Look for?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#about-me&quot;&gt;About Me&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#bigger-picture&quot;&gt;Bigger Picture (Essential)&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#build-build-build&quot;&gt;Build, Build and Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#decent-portfolio&quot;&gt;Decent Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#plan&quot;&gt;Plan&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#day-1-7&quot;&gt;Day 1 - 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#day-8-14&quot;&gt;Day 8 - 14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#day-15-21&quot;&gt;Day 15 - 21&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#day-22-28&quot;&gt;Day 22 - 28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#day-29-30&quot;&gt;Day 29 &amp;#x26; 30&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#beyond-30&quot;&gt;Beyond Day 30&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;#credits&quot;&gt;Credits&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id=&quot;what-do-they-look-for&quot;&gt;What do they Look for?&lt;/h2&gt;
&lt;p&gt;While interviewing for a junior front end developer / internship, your interviewer &lt;strong&gt;won’t&lt;/strong&gt; expect you to know everything. They won’t be expecting depth of knowledge. The most important qualities that they would be looking for in an ideal employee are as follows.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ability and confidence in building simple things.&lt;/li&gt;
&lt;li&gt;Ability to break bigger problems into smaller problems.&lt;/li&gt;
&lt;li&gt;Google and find solutions to these smaller problems.&lt;/li&gt;
&lt;li&gt;Willingness to work hard and eagerness to learn.&lt;/li&gt;
&lt;li&gt;Know how to start projects and continue making progress in chunks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Many product based companies expect you to be familiar with Data Structures and Algorithms. I will not be touching upon them in this post.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;about-me&quot;&gt;About Me&lt;/h2&gt;
&lt;p&gt;I think I have reasonable experience to back the claims above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve interviewed at a few companies and by many potential freelancing clients.&lt;/li&gt;
&lt;li&gt;Have been involved in recruitment processes.&lt;/li&gt;
&lt;li&gt;Have interviewed candidates as well.&lt;/li&gt;
&lt;li&gt;Handled classes for nearly 100 students, collecting feedback and clarifying their doubts on a regular basis.&lt;/li&gt;
&lt;li&gt;Worked on a Resume Parser at my previous company. Was in constant touch with recruiting teams and I now think I have a fair idea of what they look for.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;bigger-picture&quot;&gt;Bigger Picture&lt;/h2&gt;
&lt;p&gt;Now that you know what interviewers look for, let’s get right to business. I’ll explain some strategies to tackle some of those pain points.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/406f9ef4d1e84c8e5b7188b887f67f57/b3058/bigger-picture.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.89189189189189%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHLVcRBAP8A/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECEhET/9oACAEBAAEFAvJjniNPNzmT/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAABABEUH/2gAIAQEABj8Cx0Qv/8QAGxAAAwACAwAAAAAAAAAAAAAAAAERITFBcZH/2gAIAQEAAT8hTG16TwOs+Sj2inRV20p//9oADAMBAAIAAwAAABBc7//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/ECf/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAgEBPxBn/8QAGxABAQEBAQADAAAAAAAAAAAAAREAITFRYZH/2gAIAQEAAT8QpRQeJSFlxYeKD86MQdSkCS+z83bMbE81fW//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;html-css-javascript-react-plan&quot;
        title=&quot;&quot;
        src=&quot;/static/406f9ef4d1e84c8e5b7188b887f67f57/1c72d/bigger-picture.jpg&quot;
        srcset=&quot;/static/406f9ef4d1e84c8e5b7188b887f67f57/a80bd/bigger-picture.jpg 148w,
/static/406f9ef4d1e84c8e5b7188b887f67f57/1c91a/bigger-picture.jpg 295w,
/static/406f9ef4d1e84c8e5b7188b887f67f57/1c72d/bigger-picture.jpg 590w,
/static/406f9ef4d1e84c8e5b7188b887f67f57/a8a14/bigger-picture.jpg 885w,
/static/406f9ef4d1e84c8e5b7188b887f67f57/fbd2c/bigger-picture.jpg 1180w,
/static/406f9ef4d1e84c8e5b7188b887f67f57/b3058/bigger-picture.jpg 1296w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;build-build-build&quot;&gt;Build, Build and Build&lt;/h3&gt;
&lt;p&gt;The main idea is to build numerous small to decent size projects. Reading about a concept (theory) and actually implementing it are two different things. You get those aha moments (when you really start understanding something) only when you actually code.&lt;/p&gt;
&lt;p&gt;Additionally in the process of building you’ll learn new concepts. Since these are videos you can hear the video maker explain why certain things are done the way they are. These reasonings can be used to explain concepts when you are questioned by interviewers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Every new concept you encounter read a little theory about it and then continue coding. You must strive to understand around 70% of the all code you write while following the videos/articles. If you don’t understand something, spend sometime on it. Don’t waste too much time on it. Make a note and move on.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Most of the things that you don’t understand will become clear after you are done with a few more items in the list. As you keep progressing your understanding also increases. I often continue even when I don’t understand something, I just make note of it and keep coding/copying from the video regardless. After a few videos or 1 mini project almost everything becomes clear.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the reason why I recommend that you keep coding rather than spending loads of time and energy everytime you don’t understand something.&lt;/p&gt;
&lt;p&gt;Each item in the plan more or less tends to build on the previous item. So please avoid skipping.&lt;/p&gt;
&lt;h3 id=&quot;decent-portfolio&quot;&gt;Decent Portfolio&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Save all the exercises and code you write. Organise them into neat folders. You will be uploading them to GitHub.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following images demonstrates what I normally do. You can dive into the details &lt;a href=&quot;https://github.com/abhirathmahipal/Practice&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/cad70f9289cc275b3509ef474a01a101/7b775/folders-organise.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.05405405405405%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABjElEQVR42o2Ta27dIBCF7/4XkH30d5eQ323UNk0iRWp0c7HBYB7Dw6czYDdXUSIV6Qg8zHw+g/Epl4pcG2IIUBcLZQiXmZByAV0ps0JMOF8mLG6FsSsszzEROmPXqW0bNgCRk/VsYCXROszawiwO2vDMzwKpXCASuAyqBZGo1wtHdMI+Sq3w0SNFi9YiWg1IySInh+Yd6mrhg0VsiQEN5HlODZ12NU5HpOQVSt3jVT3gMj2yfdVVSGFTLwjPT/j5dIdvf+4xKY2vv29x8+MLvofnXi/uBnB/Q/ABL2cN7XKXi3yu3NkSGlzmNeeFzCKOrRmvnP/LTJhj6PXbm8MxIhVOlDORNZ/rNmTMAq0N/BpQ+PyuO4xrBKX8vuV9MxVMC4E/OEtg6FpXz1DL0AVE42Mce55dJvoEmDj5PKcOvC4SoGaXhTeO2H8BxaG2cqe2vXi07Pi6OIbmUv7FDg0gfQzMueI8JVjfGPjmQu6kQAfkI4efAZmidOa/Yrhrbcg53y+9AI7YIQHSu5b/AlImXEtuhcVdAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;folders-organise-example-1&quot;
        title=&quot;&quot;
        src=&quot;/static/cad70f9289cc275b3509ef474a01a101/fcda8/folders-organise.png&quot;
        srcset=&quot;/static/cad70f9289cc275b3509ef474a01a101/12f09/folders-organise.png 148w,
/static/cad70f9289cc275b3509ef474a01a101/e4a3f/folders-organise.png 295w,
/static/cad70f9289cc275b3509ef474a01a101/fcda8/folders-organise.png 590w,
/static/cad70f9289cc275b3509ef474a01a101/efc66/folders-organise.png 885w,
/static/cad70f9289cc275b3509ef474a01a101/c83ae/folders-organise.png 1180w,
/static/cad70f9289cc275b3509ef474a01a101/7b775/folders-organise.png 1445w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;I have a folder called Practice and it is further sub divided into folders like JavaScript, Python, C and C++ etc&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/592ba500ea61170e990406952a07d103/e751c/subfolders-organise.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABd0lEQVR42l1Si3LDIAzL/3/l7rZuzYuEAIHw0mSS9Lpxp5piI0s4nQ8HhtGgnwPhW/QhIhwJkgtHbJD9ERPUovEcJhjroNaNcceiTcvFlNHFGGHVgN1ZJgOMcViWFd4HOLczkpRk++5btM5h2ww2Y69mR4OQpVzQyU8/zlS2YVozxtlgUitirmAK6Q2lAmY/WKvRTyt+xqXFJyEKZXWZCofHA71y0KLQJ+yxEoA76ol4RkswTVRoF19YiSTdhLBws9jEDgWyz6UgZ8qnBUvLYk3TouwFKSVay6wtDZH/5VzuNUK5+NnTpmYhfUmxPINgmhfMtC8Duc9uyJtF1u8y1Em1e6dlMn98W3wNCc4X1FM5V4VSJCRpyafqcql4X6JYcYgvhVI0rgGLyVhNQohCWhusPScqlmTKB6d65260p2Hd3azL7P4YHCXXpuoulAKtt6ZQyJrmf2SCmM5vU3hOhTzcXGxW6x8z9fUtigpcBP+XNPbeo1y5X5WLDRgIp1u3AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;subfolder-organisation&quot;
        title=&quot;&quot;
        src=&quot;/static/592ba500ea61170e990406952a07d103/fcda8/subfolders-organise.png&quot;
        srcset=&quot;/static/592ba500ea61170e990406952a07d103/12f09/subfolders-organise.png 148w,
/static/592ba500ea61170e990406952a07d103/e4a3f/subfolders-organise.png 295w,
/static/592ba500ea61170e990406952a07d103/fcda8/subfolders-organise.png 590w,
/static/592ba500ea61170e990406952a07d103/efc66/subfolders-organise.png 885w,
/static/592ba500ea61170e990406952a07d103/e751c/subfolders-organise.png 1123w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt;This is how an individual folder JavaScript would look like.&lt;/p&gt;
&lt;p&gt;Many employers want to have a look at your past work or projects that you’ve been involved in. GitHub is an amazing place for that.&lt;/p&gt;
&lt;p&gt;You probably haven’t worked before you won’t have prior work experience to talk about. You’ll be talking about the tutorials you’ve gone through, things you’ve built and show them all the hard work you’ve put by showing them your GitHub profile. It also signals that you are serious and excited when it comes to learning new things. You will have a lot more things to talk about and demonstrate.&lt;/p&gt;
&lt;p&gt;I’ve noticed that longer interviews generally indicate higher chances of you getting the job. By having more things to show and talk about you increase your odds of getting the job 🙂&lt;/p&gt;
&lt;p&gt;For instance I’ve been coding everyday at my job and this is how my GitHub profile looks. It clearly indicates that I’ve written a lot of code. When I tell the interviewer that I’ve written a lot of code and show them this, most of them are impressed.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/81a16f450115fca0d41cf8943d714a4c/71c8e/portfolio-github.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.351351351351354%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABF0lEQVR42m2Qy0oDMRSG+96+g+5diouqCK0oxYVYu2lLsYpYaLHIjKWXKdaM00kyl2Q+M2N1o4eQwLn8+c5fk1IihGAbxcRbSVEU4M7/8bdgjEGrBKU0xlpqZSLLckIlXFIRJhErvUInmiiRxIlC6Mi9mm0aIpOYNE1YyACpFUprV4sq4RKmZguLSS3jjymN4IKT2Sl7gwOOvXMaixb73iGXyyuOpnXO5k1aQYv+pkd91mQUPjL6HDKP/W/+UrC8sszgRx7dzT3D4IHm5IbOesBd0OV62Wb0/sztW4f2uss4fOVJTOiJPr4T8uMXArmo3KgEjS3cGsah56QKrNm55RpyR//z86+Fu8HMNVrnWZ7njnBdrV/GF0h2eLUb1F1rAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;github-profile-portfolio&quot;
        title=&quot;&quot;
        src=&quot;/static/81a16f450115fca0d41cf8943d714a4c/fcda8/portfolio-github.png&quot;
        srcset=&quot;/static/81a16f450115fca0d41cf8943d714a4c/12f09/portfolio-github.png 148w,
/static/81a16f450115fca0d41cf8943d714a4c/e4a3f/portfolio-github.png 295w,
/static/81a16f450115fca0d41cf8943d714a4c/fcda8/portfolio-github.png 590w,
/static/81a16f450115fca0d41cf8943d714a4c/71c8e/portfolio-github.png 875w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;plan&quot;&gt;Plan&lt;/h2&gt;
&lt;h2 id=&quot;day-1-7&quot;&gt;Day 1 - 7&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Important Note :-&lt;/strong&gt; Keep all your code well organised. Don’t delete any of it. You’ll be pushing it online to show a decent portfolio.&lt;/p&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;If you aren’t aware of the following topics, will take you a little longer. Please bear that in mind 😅&lt;/p&gt;
&lt;p&gt;To follow along Days 1 - 7 you should have basic knowledge of HTML, CSS, linking stylesheets etc.&lt;/p&gt;
&lt;h4&gt;Goals&lt;/h4&gt;
&lt;p&gt;Get you more comfortable with HTML and CSS. Get to a state where you can build real stuff more easily. Also get familiar with mobile responsiveness without any framework. This should also give you a better about how CSS frameworks work in the future weeks.&lt;/p&gt;
&lt;h4&gt;Plan&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Semantic HTML5&lt;br&gt;
A lot of tutorials use Semantic HTML5 so it’ll be much easier if you know what semantic HTML is. Also it’s the recommended way of doing things.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=kGW8Al_cga4&quot;&gt;HTML5 Semantics&lt;/a&gt; (14 Minute Video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://guide.freecodecamp.org/html/html5-semantic-elements/&quot;&gt;FreeCodeCamp Explanation with Images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=K_s2MUPTGvQ&quot;&gt;Minimalistic UI - Responsive Profile Card with CSS&lt;/a&gt; (10 Minute Video)&lt;br&gt;
Check video description for project files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CSS Selectors&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Many beginners are not aware of common CSS Selectors. If you want to really understand other people’s code and get things done faster you should at least cover the selectors listed below. You may not use these selectors but will come across them in other people’s code.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.technetexperts.com/web/10-most-popular-css-selectors/&quot;&gt;CSS Selectors 1 - 5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.technetexperts.com/web/10-most-popular-css-selectors/2/&quot;&gt;CSS Selectors 6 - 10&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XKhQb8GKhoQ&quot;&gt;UI Profile Card Using only HTML and CSS&lt;/a&gt; (10 Minute Video)&lt;br&gt;
Starter files and code for the above can be downloaded &lt;a href=&quot;https://darkcode1.blogspot.com/2019/01/amazing-ui-profile-card-using-only-html.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=2KL-z9A56SQ&quot;&gt;Media Queries in 5 Minutes&lt;/a&gt; (4 Minute Video)&lt;br&gt;
Media queries are needed for mobile responsive websites. Quick explanation of what they are.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ooc6f1w6Mzg&quot;&gt;Amazing Transparent Login Form Just by Using HTML &amp;#x26; CSS&lt;/a&gt; (6 Minute Video)&lt;br&gt;
Please check video description if you want to download the code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=v1PeTDrw6OY&quot;&gt;Awesome CSS Search Box&lt;/a&gt; (5 Minute Video)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Y5SHm53WFEk&quot;&gt;Full Screen Landing Page - Responsive HTML5/CSS3 Tutorial&lt;/a&gt; (25 Minute Video)&lt;br&gt;
Photo in the video is no longer available, use another picture of your choice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JJSoEo8JSnc&quot;&gt;CSS Flexbox in 20 Minutes&lt;/a&gt; (20 Minute)&lt;br&gt;
Flexbox is a CSS Display Property that’s being used everywhere these days. It makes it really easy to write responsive websites. I feel it’s important that you start using Flexbox if you aren’t already. Many modern CSS frameworks now use Flexbox by default. &lt;strong&gt;I’ve noticed that many beginners aren’t aware of Flexbox. Please don’t skip this.&lt;/strong&gt;&lt;br&gt;
Code and live preview &lt;a href=&quot;https://jsfiddle.net/bradtraversy/bu0ecodm/1/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XsEnj-1hG2o&quot;&gt;Build a Responsive, Mobile First Website - HTML5 &amp;#x26; CSS3&lt;/a&gt; (45 Minute Video)&lt;br&gt;
Code and live preview &lt;a href=&quot;https://codepen.io/bradtraversy/pen/mKdGzd&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Wm6CUkswsNw&quot;&gt;Responsive Landing Page for a Website&lt;/a&gt; (60 Minute Video)&lt;br&gt;
Check video description for downloading the code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;day-8-14&quot;&gt;Day 8 - 14&lt;/h2&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;If you aren’t aware of the following topics, will take you a little longer. Please bear that in mind 😅&lt;/p&gt;
&lt;p&gt;To follow along from Days 8 - 14 you should know Bootstrap fundamentals like the grid system, some basic Bootstrap classes.&lt;/p&gt;
&lt;h4&gt;Goals&lt;/h4&gt;
&lt;p&gt;Build more complex things using HTML and CSS. You will also learn the benefits of using CSS frameworks. We’ll be focusing explicitly on Bootstrap. The concepts are similar across many frameworks though.&lt;/p&gt;
&lt;h4&gt;Plan&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wIx1O5Y5EB4&quot;&gt;Pluralsight Login Page Clone - HTML &amp;#x26; CSS&lt;/a&gt; (40 Minute Video)&lt;br&gt;
Code and live preview &lt;a href=&quot;https://codepen.io/bradtraversy/pen/MzyJqw&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=_NOLyIjMIBg&quot;&gt;Bootstrap Responsive Price Table&lt;/a&gt; (12 Minute Video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=9cKsq14Kfsw&quot;&gt;Responsive Bootstrap Website Start To Finish with Bootstrap 4, HTML5 &amp;#x26; CSS3&lt;/a&gt; (1 Hour 25 Minute Video)&lt;br&gt;
Download code from video description&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zhllkjYYUVE&quot;&gt;Complete Responsive Website using HTML/CSS/JavaScript&lt;/a&gt; (2 hours)&lt;br&gt;
This is quite long. You can always watch it at 1.25x speed to move faster 😉&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=93QK-byrx9k&quot;&gt;Transparent Login Form with HTML5, CSS3 &amp;#x26; Bootstrap 4&lt;/a&gt; (25 Minute Video)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;day-15-21&quot;&gt;Day 15 - 21&lt;/h2&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;JavaScript basics like variables, loops, event listeners, functions, data structures and basic operations on them, linking scripts to a HTML page etc. You should also be aware of the DOM and perform basic manipulations like change CSS of an element, change text and so on.&lt;/p&gt;
&lt;h4&gt;Goals&lt;/h4&gt;
&lt;p&gt;Be in a position to make your web pages interactive (animations, manipulate DOM on events like clicks) and add basic logic.&lt;/p&gt;
&lt;h4&gt;Plan&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JoDx8YyBdBA&quot;&gt;Bulb On and Off using JavaScript&lt;/a&gt; (7 Minute Video)&lt;br&gt;
Very simple. Just to get you warmed up.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=WCppvHhcEz4&quot;&gt;Simple Calculator Using JavaScript&lt;/a&gt; (7 Minute Video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=CQXMjTdCyZw&quot;&gt;Random Number Guessing Game&lt;/a&gt; (15 Minute Video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=G1eW3Oi6uoc&quot;&gt;A Simple Filterable List&lt;/a&gt; (17 Minute Video)&lt;br&gt;
Something similar to a simple search form.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jaVNP3nIAv0&quot;&gt;Stone, Paper, Scissors using HTML, CSS and JavaScript&lt;/a&gt; (1 Hour 25 Minute Video)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZniVgo8U7ek&amp;#x26;t=1s&quot;&gt;Memory Card Game&lt;/a&gt; (34 Minute Video)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;day-22-28&quot;&gt;Day 22 - 28&lt;/h2&gt;
&lt;h4&gt;Prerequisites&lt;/h4&gt;
&lt;p&gt;Should have a feel for React’s philosophy, should know about Node.js, npm, know how to create a React.js project, basics like State and Props. If you don’t please watch &lt;a href=&quot;https://www.youtube.com/watch?v=DLX62G4lc44&quot;&gt;React.js Full Course by FreeCodeCamp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You will also need to know a little about external APIs. Most common meaning of an API - It’s a mechanism by which you can get data from an external source such as a server.&lt;/p&gt;
&lt;h4&gt;Goals&lt;/h4&gt;
&lt;p&gt;Become comfortable using React. Learn to write logic and also get a head start in structuring React applications. Be warned that this week will be more strenuous compared to the previous weeks.&lt;/p&gt;
&lt;h4&gt;Plan&lt;/h4&gt;
&lt;p&gt;Plan is to build a few simple projects, understand Higher Order Components, learn about React Router and understand Global Data patterns using Context and also a bit of Hooks.&lt;/p&gt;
&lt;p&gt;I would suggest beginners not to spend time on Redux. It takes considerable time to learn. Hooks and Context come by default and are gaining traction. You get more return for the time spent by learning them instead.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=m_mtV4YaI8c&quot;&gt;React Component Lifecycle&lt;/a&gt; (25 Minutes)&lt;br&gt;
An important topic. Time and again you’ll find yourself writing these methods. You’ll definitely encounter them in every medium size project at work. These same concepts can be applied while building Android apps, iOS apps, games etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.golangprograms.com/react-js-projects-for-beginners.html&quot;&gt;Really Small Projects for Beginners&lt;/a&gt;&lt;br&gt;
This will help you become more familiar. Choose 3-4 from the list and type them out. Don’t do everything as we are short on time :)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=tvfeBLMA_Q4&quot;&gt;Recipe App using React Router&lt;/a&gt; (1 Hour 30 Minutes)&lt;br&gt;
Get familiar with using External APIs and build an app using React and React Router. React Router is used when your application has more than one page. Most apps have multiple pages which makes it imperative to understand Router.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Y0-qdp-XBJg&quot;&gt;Protected Routes using React Router&lt;/a&gt; (15 Minutes)&lt;br&gt;
A very common pattern. By writing a Higher Order Component you can ensure certain pages are only visible to loggedin users. The same Higher Order Component can be reused for multiple pages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wesbos.com/react-context/&quot;&gt;Why use Context?&lt;/a&gt; (16 Minutes)&lt;br&gt;
A brief video explaining you the problem React Context tries solving. Once you know the problem it solves, things become more fun and meaningful. &lt;strong&gt;You DON’T have to install alpha version of React like he does in the video. The video is a year old. Context will directly work in your setup.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6RhOzQciVwI&amp;#x26;list=PL4cUxeGkcC9hNokByJilPg5g9m2APUePI&quot;&gt;React Context &amp;#x26; Hook by Net Ninja&lt;/a&gt; (2 Hours 40 Minutes)&lt;br&gt;
A YouTube playlist to learn about React Context and Hooks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/results?search_query=react+clone&quot;&gt;Build a Clone of Your Choice&lt;/a&gt;&lt;br&gt;
This is important. Do something that connects with you. Even better if you build more. This search term happens to point to some great videos. While learning from a tutorial you should try understand most of the code. You may not understand bits and pieces. Don’t worry about that. Don’t waste too much time trying to understand EVERYTHING. Keep moving forward and build new things.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://daveceddia.com/react-practice-projects/&quot;&gt;6 Fun React Projects&lt;/a&gt; &amp;#x26; &lt;a href=&quot;https://daveceddia.com/your-own-react-project-ideas/&quot;&gt;Your Own React Project Ideas&lt;/a&gt;&lt;br&gt;
For React Project ideas in case you’re still thinking about what to build.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;day-29-30&quot;&gt;Day 29 &amp; 30&lt;/h2&gt;
&lt;h4&gt;Plan&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;If you haven’t already pushed your practice code to GitHub start doing it now.&lt;/li&gt;
&lt;li&gt;You’ve learnt a lot in the last 4 weeks. Revision is important. Trust me. I’ve been teaching for a while now and students forget a lot.&lt;/li&gt;
&lt;li&gt;Quickly go through all these projects. You might be questioned on them. For instance
&lt;ul&gt;
&lt;li&gt;Tell me about a recent project or tutorial that you worked on.&lt;/li&gt;
&lt;li&gt;The challenge you faced while solving a JavaScript bug and how did you finally solve it.&lt;/li&gt;
&lt;li&gt;What features of React have you explored?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;beyond-30&quot;&gt;Beyond Day 30&lt;/h2&gt;
&lt;p&gt;I have made a separate section for these because they are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A little time consuming &lt;strong&gt;or&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;There’s a chance that you might not appreciate the insights they offer as you wouldn’t have faced the problems the authors highlight &lt;strong&gt;or&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Going deep into a particular topic might really not be necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Advanced List&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://every-layout.dev/&quot;&gt;Every Layout - Really Good for CSS&lt;/a&gt; (Advanced. Free version is more than enough 🙂)&lt;br&gt;
How to structure things the right way when using CSS. Really good. Must warn you though. It’s advanced and to really understand you should have written a lot of CSS. If you’re new to CSS please avoid this for now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://javascript30.com/&quot;&gt;Build 30 Mini Applications Using Pure JavaScript&lt;/a&gt;&lt;br&gt;
Fun, fast and informative.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://flexbox.io/&quot;&gt;Flexbox with Real World Applications&lt;/a&gt;&lt;br&gt;
Again by Wes Bos. Introduces Flexbox but doesn’t stop there. You also build a couple of stuff using Flexbox.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://daveceddia.com/archives/&quot;&gt;Dave Ceddia’s Blog&lt;/a&gt;&lt;br&gt;
Wonderful place for all things React.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pexels.com/photo/road-landscape-nature-sky-56832/&quot;&gt;Opening Road Map Picture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pexels.com/photo/person-holding-magnifying-glass-712786/&quot;&gt;Bigger Plan Picture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Managing Processes with Supervisor - In Depth Tutorial]]></title><description><![CDATA[In this post I’ll show you how to setup Supervisor on Linux and become familiar with a few handy options and settings. If you haven’t used…]]></description><link>https://abhirath.me/managing-processes-with-supervisor-in-depth-tutorial/</link><guid isPermaLink="false">f37d9f15-3e5f-4ee9-9fd7-3e9046e5e775</guid><pubDate>Tue, 05 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this post I’ll show you how to setup Supervisor on Linux and become familiar with a few handy options and settings. If you haven’t used Supervisor in the past this post should give you a decent start.&lt;/p&gt;
&lt;p&gt;Supervisor is a Python program that makes managing other programs (processes) a breeze. It can ease the process of starting, killing and restarting applications that you develop. I’ll be explaining various aspects that you need to keep in mind while using Supervisor.&lt;/p&gt;
&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#basics&quot;&gt;Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#installing-supervisor&quot;&gt;Installing Supervisor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#writing-conf-files&quot;&gt;Writing conf Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#a-few-options-explained&quot;&gt;A Few Options Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#some-common-errors&quot;&gt;Some Common Errors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Supervisor can help you administrate and automate the process of starting applications on your web server. It can run the steps specified by you and start multiple applications. Maybe you want somebody to automatically start the application after you’ve restarted your server. Supervisor can do all that and more.&lt;/li&gt;
&lt;li&gt;Supervisor starts your application or script as it’s own child process. This way it can kill them when you want to. It daemonizes something that runs infinitely say a web server. You should not use it to control a process which has a definite end (say a task which takes 3 minutes and exits after that).&lt;/li&gt;
&lt;li&gt;The command to start a particular process and various options are given via a &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Supervisor looks for files ending with &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt; in certain directories. It then follows the instructions that you’ve given in those files.&lt;/li&gt;
&lt;li&gt;Once a proper &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt; file is written, starting any program is as simple as&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;supervisorctl start appname&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It daemonizes the process that you want to run. You can save logs that your application spits out in files.&lt;/li&gt;
&lt;li&gt;Say your server runs 50 processes. It would be a pain to start every one of them whenever you restart the server. Supervisor has an autostart option which will start the process when Supervisor is initialised.&lt;/li&gt;
&lt;li&gt;You could make Supervisor run a program as a particular user. There are loads of such options that can help make your day to day life easier.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;installing-supervisor&quot;&gt;Installing Supervisor&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;On Ubuntu or debian you can&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; supervisor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can also install it using pip. &lt;a href=&quot;https://pypi.python.org/pypi/supervisor&quot;&gt;Supervisor on Pypi&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;writing-conf-files&quot;&gt;Writing conf Files&lt;/h2&gt;
&lt;p&gt;Supervisor can be informed of any program that you wish to run via a &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;I found this example from &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps&quot;&gt;Digital Ocean&lt;/a&gt; to be very helpful. So I’m adapting a similar approach but with a different script. For the sake of this example and brevity we’ll write a small script that displays the amount of RAM that the machine sports.&lt;/p&gt;
&lt;p&gt;Go to your home directory (~/) and save the following as &lt;code class=&quot;language-text&quot;&gt;displayram.sh&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;((&lt;/span&gt;counter&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Count is now &lt;span class=&quot;token variable&quot;&gt;$counter&lt;/span&gt;.&quot;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; /proc/meminfo &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; MemTotal
    &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Do note this is a never ending process. It runs forever because of the while loop. I repeat Supervisor can only manage and monitor never ending processes.&lt;/p&gt;
&lt;p&gt;Make the file you just created executable.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;chmod +x displayram.sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Save the following as &lt;code class=&quot;language-text&quot;&gt;displayram.conf&lt;/code&gt;. Supervisor will use this file to control the process. Substitute abhirath with your username.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[program:displayram]
command=/home/abhirath/displayram.sh
autostart=false
autorestart=false
stderr_logfile=NONE
stdout_logfile=/home/abhirath/displayram.out.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Move the file that you just created to &lt;code class=&quot;language-text&quot;&gt;/etc/supervisor/conf.d/displayram.conf&lt;/code&gt;. This is the default directory that Supervisor looks for programs.&lt;/p&gt;
&lt;p&gt;Then on the terminal&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;supervisorctl reread&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;followed by&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;supervisorctl update&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;supervisorctl start displayram&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our script starts instantly. You can verify that it works by opening &lt;code class=&quot;language-text&quot;&gt;/home/yourusername/displayram.out.log&lt;/code&gt;. It should be filled with lines displaying the RAM installed on the machine.&lt;/p&gt;
&lt;p&gt;A better way would be to run the following on the terminal.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; /home/yourusername/displayram.out.log
&lt;span class=&quot;token comment&quot;&gt;# or&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; ~/displayram.out.log&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It will keep printing out new entries on the terminal.&lt;/p&gt;
&lt;p&gt;You will also need to familiarise yourself to spawn more than one process - &lt;a href=&quot;http://stackoverflow.com/questions/12923320/how-to-setup-a-group-in-supervisord&quot;&gt;An example which requires running multiple processes to start an app.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To stop the script we just started run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;supervisorctl stop displayram
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;a-few-options-explained&quot;&gt;A Few Options Explained&lt;/h2&gt;
&lt;h3&gt;Directory&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The directory which Supervisor switches to before executing the command.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Researching about this setting to get my app to work with Supervisor was when I learnt that &lt;em&gt;when you activate an environment in Python you basically are just instructing your machine to use a copy of Python situated in a particular directory instead of using the default Python installation.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Command&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The way via which Supervisor starts a particular program. Give the command / path that you normally use to start your program.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Commands are not equivalent to bash or your typical terminal commands by default. They are fairly similar but a command that you use on your terminal may not yield the same effect here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Commands can contain absolute paths or relative paths. The &lt;code class=&quot;language-text&quot;&gt;displayram&lt;/code&gt; example uses absolute paths. If you want to use relative paths you need to set the path. You can read more about it &lt;a href=&quot;http://supervisord.org/configuration.html#program-x-section-values&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can ensure that your command is treated as a bash command by using &lt;code class=&quot;language-text&quot;&gt;bash -c &quot;command here&quot;&lt;/code&gt;. Our earlier example can be rewritten as&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[program=displayram]
directory=/home/abhirath
command=bash -c &quot;./displayram&quot;
autostart=false
autorestart=false
stderr_logfile=NONE
stdout_logfile=/home/abhirath/displayram.out.log&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Stop and Kill as Group&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sometimes your program doesn’t really get killed. They might have children that they don’t kill. So to actually stop them Supervisor has to be mean and kill every process that might have spawned. One possible reason is that they expect a different kill signal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You don’t have to use them unless you notice that your program is still running even after you explicitly ran
&lt;code class=&quot;language-text&quot;&gt;supervisorctl stop programname&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This helped me a lot - &lt;a href=&quot;https://coderwall.com/p/4tcw7w/setting-supervisor-to-really-stop-django-runserver&quot;&gt;Really killing a program.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Logs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stderr_logfile&lt;/code&gt; - the file to which it shall redirect stderr to. If set to NONE it will not log output from stderr.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stdout_logfile&lt;/code&gt; - the file to which it redirect stdout to. This can also be set to NONE.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stderr_logfile_maxbytes&lt;/code&gt; - maximum space that the log file will take before Supervisor uses a new file to store logs. You can input a numerical followed by GB, KB etc. &lt;strong&gt;By default it’s set to 50MB.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stdout_logfile_maxbytes&lt;/code&gt; - same as above but for stdout.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stdout_logfile_backups&lt;/code&gt; - the number of backup files it stores. Say you’ve set it to 3. After the first files exceeds the value of &lt;code class=&quot;language-text&quot;&gt;stdout_logfile_maxbytes&lt;/code&gt; it creates a second file then a third. If the third file exceeds the size it proceeds to delete the first file and continue logging. In all it would use a maximum of 3 * 50MB in our case. &lt;strong&gt;By default it has a value of 10.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stderr_logfile_backups&lt;/code&gt; - same as above but for stderr.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/23343874/supervisord-log-file-rotation-settings&quot;&gt;An example which uses a variety of log settings.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Supervisor saves it’s own logs as well. They are different from the logs you set for your program. These logs contain information about Supervisor. They are stored in &lt;code class=&quot;language-text&quot;&gt;/var/log/supervisor/supervisord.log&lt;/code&gt;
To see the last few logs you can
&lt;code class=&quot;language-text&quot;&gt;tail /var/log/supervisor/supervisord.log&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A useful read - &lt;a href=&quot;http://supervisord.org/configuration.html#program-x-section-settings&quot;&gt;Options available under program.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;some-common-errors&quot;&gt;Some Common Errors&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. You get a message similar to &lt;code class=&quot;language-text&quot;&gt;unix:///var/run...sock no such file&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It means Supervisor isn’t running. You will have to start Supervisor.
&lt;code class=&quot;language-text&quot;&gt;sudo service supervisor restart&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;2. Spawn errors. Supervisord is unable to start your program?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check the error log and output logs. Supervisor keeps appending stuff to your program’s log file. So it’s a good idea to use &lt;code class=&quot;language-text&quot;&gt;tail -f /path/to/program/log/file&lt;/code&gt; to keep track of changes happening.&lt;/li&gt;
&lt;li&gt;Check the &lt;code class=&quot;language-text&quot;&gt;environment&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;directory&lt;/code&gt; options under your program. Give absolute paths like &lt;code class=&quot;language-text&quot;&gt;/home/abhirath/so/and/so&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;3. Supervisor doesn’t start automatically after bootup?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;On Ubuntu 16 you can enable it by
&lt;code class=&quot;language-text&quot;&gt;sudo systemctl enable supervisor&lt;/code&gt;.
Also read &lt;a href=&quot;http://unix.stackexchange.com/questions/281774/ubuntu-server-16-04-cannot-get-supervisor-to-start-automatically&quot;&gt;this stackexchange question.&lt;/a&gt; - &lt;a href=&quot;https://github.com/Supervisor/initscripts&quot;&gt;init scripts for various operating systems.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Frequently new &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt; files that you write are not recognised. If that is the case do the following:-
Check the syntax of everything in the file. If there’s an error Supervisor doesn’t even show the file. Also the files must have an extension of &lt;code class=&quot;language-text&quot;&gt;.conf&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;4. Any signs of the process / app that you want to start is already running?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They might already be running. Check the status using &lt;code class=&quot;language-text&quot;&gt;supervisorctl appname status&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I’ve seen .NET apps that don’t kill their child processes by themselves. So even after you stop a program their child process might be running. For instance you might get errors like &lt;em&gt;port is already in use&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Read about &lt;code class=&quot;language-text&quot;&gt;stopasgroup&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;killasgroup&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;stopsignal&lt;/code&gt; over &lt;a href=&quot;http://supervisord.org/configuration.html&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;stopasgroup&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;killasgroup&lt;/code&gt; work on individual programs. They are not to be confused with group applications&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://coderwall.com/p/4tcw7w/setting-supervisor-to-really-stop-django-runserver&quot;&gt;Really killing a program.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Vuvuzela - A Private Messaging System]]></title><description><![CDATA[I gave a talk about Vuvuzela at Papers We Love, Chennai. You can find the slides here. This blog post tries to cover the points we discussed…]]></description><link>https://abhirath.me/vuvuzela-scalable-private-messaging-traffic-analysis-paper/</link><guid isPermaLink="false">a8e91053-8243-471e-9ad3-e04ba59b2aef</guid><pubDate>Fri, 22 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I gave a talk about Vuvuzela at &lt;a href=&quot;https://twitter.com/PWLChennai&quot;&gt;Papers We Love, Chennai&lt;/a&gt;. You can find the slides &lt;a href=&quot;/0708bf8648b08b41bd289baa6a78cc34/Vuvuzela_PWL_Jan_2019.pdf&quot;&gt;here&lt;/a&gt;. This blog post tries to cover the points we discussed orally and therefore aren’t a part of the slides.&lt;/p&gt;
&lt;p&gt;Paper:- &lt;a href=&quot;https://vuvuzela.io/static/vuvuzela.pdf&quot;&gt;Vuvuzela&lt;/a&gt;&lt;br&gt;
Recommended By:- &lt;a href=&quot;https://ganesh-srinivas.github.io/&quot;&gt;Ganesh Srinivas&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Recommended Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/onion-routers-mix-networks-differences-explained/&quot;&gt;Onion Routers and Mix Networks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A few differential privacy concepts and terms are used in the paper. I would recommend reading &lt;a href=&quot;https://blog.cryptographyengineering.com/2016/06/15/what-is-differential-privacy/&quot;&gt;this&lt;/a&gt; and &lt;a href=&quot;https://cryptocurrencyheart.com/technology/differential-privacy.html&quot;&gt;this&lt;/a&gt;. The latter link has a video which describes how de-anonymisation techniques were used to uncover health records of the Governor of Massachusetts. She also claims that 87% of the US population can be de-anonymised using just the gender, ZIP Code and date the birth.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Metadata&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In the context of a call things like who did you call, location, duration of the call, the number of times you called up the person etc. Anything that describes additional parameters about the content (recording of the phone call in this case) can be termed as metadata.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eff.org/deeplinks/2014/11/verizon-x-uidh&quot;&gt;Verizon Injects Custom Headers to Un-Encrypted Traffic&lt;/a&gt; is an interesting read. It doesn’t directly address metadata but custom headers definitely fall under metadata. The article will give you some insight as how to such info can be used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;State of the art privacy mechanisms even go to the extent of hiding your screen size and resolution as it can be used to identify a whistleblower, journalist etc amongst a pool of their suspects. Ganesh mentioned about an interesting flaw in browsers which goes by the name &lt;a href=&quot;https://en.wikipedia.org/wiki/Canvas_fingerprinting&quot;&gt;Canvas Fingerprinting&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Existing Work&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some systems offer strong privacy guarantees but do not scale. Some systems broadcast every message to every user. Other systems use Private Information Retrieval (PIR) to hide metadata. Simplest PIR technique is to send the entire database to every user who requests for information. This way observing parties (using Man in the Middle Attacks for instance) will not get to know which particular information (or message from a recipient) they were trying to access.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Systems that scale do not hide metadata and a persistent adversary can easily correlate activities with a particular individual. Tor and Mixnets are such systems. A powerful adversary can manipulate traffic and several nodes. Say amongst thousand users he stops Charlie from accessing a website and the same very same instance the adversary notices that the particular website stops receiving traffic. My manipulating and making the right moves over a period of time the identity of the user can come to light.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;I like to think of it this way. Tor plays with space alone (the bytes that you send across the network go through various other servers thus they aren’t where they are supposed to be) and mixnets play with both space and time (adds delays and shuffles the request through various servers as well).&lt;/strong&gt; Thinking in terms of space and time helps clarify a lot of concepts as they comprise the state which we exist or can manipulate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vuvuzela uses two protocols to operate. One protocol to initiate conversations and another one to exchange messages between parties who’ve already established connection (by sharing keys i.e).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The authors expresses it’s privacy guarantees in terms on differential privacy. I don’t really understand them in depth but basically the adversary can never be sure. His suspicions on a person can increase with time but he can never be sure if he was involved in the communication or not as to the external observing party everything looks the same.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vuvuzela uses a lot of network bandwidth to operate. Also it stores all the incoming and outgoing messages in volatile memory. Additionally you would also need multiple servers following the Vuvuzela to add enough noise or cover traffic. So hardware costs definitely lean on the higher side.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Todo&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Explain both the protocols&lt;/li&gt;
&lt;li&gt;The small additional things (like client, uniform padding, participate in every round, rate of messaging etc)&lt;/li&gt;
&lt;li&gt;Algorithmic complexity&lt;/li&gt;
&lt;li&gt;How different variables or state of the server is hidden&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Interesting Stuff Mentioned in the Meetup&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Differential Privacy using Coin Tosses (Differential Privacy by Sampling)&lt;/li&gt;
&lt;li&gt;How Mozilla Anonymises the Information it Collects (Prio). You can read a little about it &lt;a href=&quot;https://hacks.mozilla.org/2018/10/testing-privacy-preserving-telemetry-with-prio/&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Learning to Think in React by Building a Stopwatch]]></title><description><![CDATA[Here’s the video of me coding it. Feel free to post any questions or comments :) Links YouTube Link GitHub Repository Slides (They hardly…]]></description><link>https://abhirath.me/learning-to-think-in-react-building-a-stopwatch/</link><guid isPermaLink="false">72009ca0-20d3-4c48-810d-a0743981e681</guid><pubDate>Thu, 14 Feb 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here’s the video of me coding it. Feel free to post any questions or comments :)&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/mPj0v38QJNE&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=mPj0v38QJNET&quot;&gt;YouTube Link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/abhirathmahipal/stopwatch-vanilla-js-just-react&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/d70765c0a58305bfe6684df43b6d25d9/Thinking_in_React.pdf&quot;&gt;Slides (They hardly contain anything though!)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Onion Router and Mix Networks]]></title><description><![CDATA[Introduction Prerequisites Onion Router Mix Networks Security and Meta Data Abuse Scaling I wrote this article as supplementary reading for…]]></description><link>https://abhirath.me/onion-routers-mix-networks-differences-explained/</link><guid isPermaLink="false">12ec4914-35aa-4353-989b-0cc8123d954a</guid><pubDate>Thu, 17 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#onion-router&quot;&gt;Onion Router&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mix-networks&quot;&gt;Mix Networks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#security-and-meta-data-abuse&quot;&gt;Security and Meta Data Abuse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#scaling&quot;&gt;Scaling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I wrote this article as supplementary reading for a talk on Vuvuzela. I hope it can be read as a stand-alone post as well but that isn’t the goal.&lt;/p&gt;
&lt;p&gt;In order to understand &lt;a href=&quot;/vuvuzela-scalable-private-messaging-traffic-analysis-paper/&quot;&gt;Vuvuzela&lt;/a&gt; I feel it’s important to understand the limitations that the earlier mechanisms suffer from. This is a short post contrasting Onion Routers and Mix Networks. It is important to note that both these protocols fail to hide metadata. I’ll reiterate and give some more context to drive this point home, just knowing that they don’t hide metadata is enough for now. I’ve also linked to articles I’ve read in the past and also the ones I’ve stumbled upon whilst reading the said paper.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;You need to have a decent idea about the following concepts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Public / Private Keys and Digital Signatures. &lt;a href=&quot;http://blakesmith.me/2010/02/08/understanding-public-key-private-key-concepts.html&quot;&gt;This&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@vrypan/explaining-public-key-cryptography-to-non-geeks-f0994b3c2d5&quot;&gt;this&lt;/a&gt; provide a decent explanation as to how keys work in general.&lt;/li&gt;
&lt;li&gt;Proxy Servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;onion-router&quot;&gt;Onion Router&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A detailed explanation of the protocol and workings can be found &lt;a href=&quot;https://www.geeksforgeeks.org/onion-routing/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use it under the assumption that the adversary cannot monitor all nodes. If you can protect just one server in the chain, you can be assured that the content of your request and response stay private. Under normal circumstances either source or destination or both remain hidden. If the first server is compromised, the source of the request (the client trying to visit say YouTube.com) is given away but the end destination YouTube.com stays hidden as everything in encrypted using multiple keys. Similarly if the last server is compromised the attacker will get to know the end destination (i.e YouTube.com) but will not know where it originated from.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The chain of servers chosen normally spans across diverse geographical boundaries. This makes it harder for perpetrators to manipulate network traffic as rules, regulations and privileges vary across political divisions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unlike mix networks, onion routers can be used for time sensitive data as well. Requests are forwarded immediately. Mix networks normally wait for quite sometime before they start forwardings requests. They are safer but the message takes longer to reach the final destination.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The client (i.e the user who’s using the Onion Router protocol to protect his privacy) needs public keys of all the servers in the chain. However each server can only decrypt it’s layer and the content stays hidden. Each server just takes it a step forward towards decryption but cannot actually see the content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the website visited by the user uses HTTPS, even the last server in the Onion chain cannot see the content even after decrypting all the layers. The last server will know the end destination of the request but it will not know the content of the request nor will it know the source of the request. It just knows that the second last server in the chain has sent it some encrypted data. The last server on decrypting the data, will find details of the destination server (say YouTube.com) and whom it has to forward the response to (the second last server, Onion Routers follow the same chain of servers).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;mix-networks&quot;&gt;Mix Networks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Please read &lt;a href=&quot;https://crypto.is/blog/mix_and_onion_networks&quot;&gt;this&lt;/a&gt;. It explains it pretty well. It also draws real life parallels to an observer in a crowd. It really clears things up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You could watch &lt;a href=&quot;https://www.youtube.com/watch?v=IqgW24FMcc0&quot;&gt;this&lt;/a&gt; video if you have 12 minutes to spare. Not required though.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It provides an additional layer of protection. The content of the requests are protected even if the adversary monitors all the nodes in the network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Does not depend on route reproducibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It cannot be used for time sensitive data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It too is prone to meta data analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;I like to think of it this way. Tor plays with space alone (the bytes that you send across the network go through various other servers thus they aren’t where they are supposed to be) and mixnets play with both space and time (adds delays and shuffles the request through various servers as well).&lt;/strong&gt; Thinking in terms of space and time helps clarify a lot of concepts as they comprise the state which we exist or can manipulate.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;security-and-meta-data-abuse&quot;&gt;Security and Meta Data Abuse&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Adversaries are very powerful and have great reach. They can control ISPs, cloud providers, assign people to monitor suspects/victims over very long durations of time etc. They therefore can block certain users, observe traffic flow patterns from a user to the server, between servers and so on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;It is fairly easy to know that the victim / suspect is connected to such a server (Tor, Mix Net etc) as they are generally publicly known, basic traffic observation will reveal that. It is not trivial to track his activity and prove that he did something particular. That’s key.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A patient adversary can easily follow patterns in case of Onion Routing. Say Alice visits abcxyz.com everyday at 8 PM, an adversary can block all other users other than Alice. He can then look for activity, he will notice that Alice’s network is active and the request flows through a particular chain. Since she’ll be the only person using the network it’s quite evident that she’s the one visiting the particular website.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;An adversary can monitor the network and identify individuals by looking at request sizes. Say Alice, Bob and Charlie send a request to abcxyz.com or are engaged in a chat. Network traffic can be monitored at the entry and the last server. Alice sends abnormally large data compared to Bob and Charlie, so the adversary can find out the recipient of the request (abcxyz.com or chat server) from the last server in mix and correlate it with the sizes of the request sent by Alice, Bob and Charlie.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mix nets make it harder to pin requests to a particular user but a patient adversary over many rounds can statistically correlate information to a user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adversaries can disconnect everyone except two parties and try figuring out if they are chatting or not by intercepting their traffic. If request request by Alice corresponds to a request to Bob, it isn’t far fetched to assume that they are chatting.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;scaling&quot;&gt;Scaling&lt;/h2&gt;
&lt;p&gt;Both these approaches are very scalable. A simple strategy would be to add more servers following the respective protocols and the clients are given an option to choose the chain of servers instead of using all of them (based on the load of each server). The client would then make appropriate requests with the given data. Say you are very paranoid in general and therefore choose a longer chain not limited by the boundaries of a single country. Since requests of a client does not have to go through all the servers, both these approaches are easily scalable. To the best of my knowledge and understanding both scale linearly.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GD50 Lecture 05 - Super Mario Bros]]></title><description><![CDATA[This is a part of a series of notes. You can find notes to other lectures here
Please feel free to bring to my attention mistakes, other…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources-05-super-mario-bros/</link><guid isPermaLink="false">81b20dc7-79ef-4704-a7c6-e0222a6eb64e</guid><pubDate>Sun, 13 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a part of a series of notes. You can find notes to other lectures &lt;a href=&quot;/introduction-game-development-gd50-notes-resources/&quot;&gt;here&lt;/a&gt;
Please feel free to bring to my attention mistakes, other interesting resources and feedback via the comments section. I’m all ears and will do my best to incorporate them into the blog post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/12929685/5698202&quot;&gt;Continue Statements in Lua&lt;/a&gt; - Read this answer. Other options are decent as well.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sourcemaking.com/design_patterns/factory_method&quot;&gt;Factory Patterns&lt;/a&gt; - This site explains widely used programming patterns really well. Also has code samples.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gameprogrammingpatterns.com/component.html&quot;&gt;Entity Component Systems Explained&lt;/a&gt; - A pretty comprehensive explanation with examples. It’s a part of an amazing book.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Intro&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Not using the original sprite sheet due to copyright issues.&lt;/li&gt;
&lt;li&gt;Released in 1985, it kind of revived the gaming industry after the crash in the 70’s. Probably the most famous game of all time.&lt;/li&gt;
&lt;li&gt;2D Platformer. Quite complex for it’s time, move around, effected by gravity, spawn enemies etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What Goes Into Mario?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tilemaps&lt;/strong&gt; - Each level is designed using individual &lt;code class=&quot;language-text&quot;&gt;16 x 16&lt;/code&gt; tiles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2D Animations&lt;/strong&gt; - Kind of like a flip book.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collision Detection&lt;/strong&gt; - We’ll be deviating from AABB that we normally use. We don’t need to iterate through every tile in the world checking for collisions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera&lt;/strong&gt; - We track the player and move the world along with him. The notion of a camera is introduced.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some columns in the level there are no tiles (chasms the player can fall into), some columns are a bit higher (player has to jump), some have power ups and so on. All these variations in pattern put together create a level.&lt;/p&gt;
&lt;h2&gt;Tilemaps&lt;/h2&gt;
&lt;p&gt;2D array of numbers. Each number normally depicts the kind of tile that should appear on the corresponding spot of the level. They can have a host of other properties like allow to pass things, trigger an animation and so on. You could do this by associating properties (using Tables in Lua) against each tile. The sky is the limit.&lt;/p&gt;
&lt;h2&gt;tiles0 “Static Tiles”&lt;/h2&gt;
&lt;p&gt;Colour in the background and just render a few tiles. That’s all.&lt;/p&gt;
&lt;p&gt;Question by Colton:- &lt;strong&gt;What would be the first step to implement this?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Student Answer:-&lt;/strong&gt; Loop over tiles and render them.&lt;/p&gt;
&lt;p&gt;Colton goes on to explain that we’ll create a table to store tiles. We just won’t store numbers. We will store each tile as a mini table that will have an id as well as some properties (sort of like metadata).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a sprite sheet using generateQuads.&lt;/li&gt;
&lt;li&gt;A small sprite is used. We index into a the table of quads just generated to get the relevant sprite.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 39 - 42 =&gt;&lt;/em&gt;&lt;/strong&gt; Generate a random colour. It’ll denote the sky.&lt;/li&gt;
&lt;li&gt;Variables &lt;code class=&quot;language-text&quot;&gt;mapWidth&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;mapHeight&lt;/code&gt; are used to to fill a table with appropriate number of entries for this demo.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;TILE_SIZE&lt;/code&gt; is a constant set to 16. It’ll be 16 throughout the lecture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 47 - 50 =&gt;&lt;/em&gt;&lt;/strong&gt; Populate the table with data denoting the structure of the map. If height is less than 5 (top portion that is) make it a sky tile else a ground tile. It’s just a table with integers denoting sky or ground. We do not store the actual quad.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 74 - 85 =&gt;&lt;/em&gt;&lt;/strong&gt; Iterate over and use the above generated table to render. Sky tiles have no quad. If it’s a ground tile render the appropriate quad.&lt;/p&gt;
&lt;p&gt;Final outcome:- Screen with tiles and a random sky colour.&lt;/p&gt;
&lt;h2&gt;tiles1 “Scrolling Tiles”&lt;/h2&gt;
&lt;p&gt;Types of scrolling in games.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In some games you cannot scrolling. For example in Temple Run you cannot go back and forth. The game keeps moving forward all the time.&lt;/li&gt;
&lt;li&gt;Then there are games like Mario where you make the entire world move respective to the player.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;love.graphics.translate()&lt;/code&gt; Moves the coordinate system. Everything drawn to the screen after that gets rendered respective to the new coordinate system. So we shift everything and move the world. This gives the effect of the world moving as the player moves. We pass in X &amp;#x26; Y based on the player position.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Demo =&gt;&lt;/em&gt;&lt;/strong&gt; Key presses now move the tiles. If you move too much you will reach a point where there are no tiles. Normally such information is hidden from the user (recall that &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-02-flappy-bird/#games-are-illusions&quot;&gt;games are illusions&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 95 =&gt;&lt;/em&gt;&lt;/strong&gt; Translate by negative camera speed. If the player moves to the left, we want everything to move to the right to give the illusion of the player moving. Y coordinate is set to 0 because we don’t want the map to move vertically. Math.floor is used as decimal values might cause blurring (called Blur Artifacting). Any time you condense (texture rendered on a small virtual window) or magnifying values while using a virtual screen there are chances of weird blurs appearing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 80 - 87 =&gt;&lt;/em&gt;&lt;/strong&gt; Take care of updating camera scroll based on right and left key inputs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We translate before we draw. Everything drawn after the translate gets effected by it.&lt;/p&gt;
&lt;p&gt;Love 2D is a low level game engine which gives more control and is good for learning. It has no camera objects and the likes. Higher level game engines like Phaser etc have camera objects which encapsulate this translate behvaiour.&lt;/p&gt;
&lt;h2&gt;character0 “The Stationary Hero”&lt;/h2&gt;
&lt;p&gt;We again generate quads from the sprite sheet and just draw the first quad. It’s just static and does nothing. The other quads you notice in the image files are going to be used for animating the character.&lt;/p&gt;
&lt;h2&gt;character1 “The Moving Hero”&lt;/h2&gt;
&lt;p&gt;Now instead of camera scroll, have a variable called &lt;code class=&quot;language-text&quot;&gt;characterSpeed&lt;/code&gt;. In this demo the character moves but the world (i.e tiles) are stationary.&lt;/p&gt;
&lt;p&gt;3 things yet to be done.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;World moves as character moves.&lt;/li&gt;
&lt;li&gt;Animate character as he moves.&lt;/li&gt;
&lt;li&gt;Clamp (or limit beyond a certain point) if the character reaches the edge of the world. In such a scenario, the character moves but the world doesn’t.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;character2 “The Tracked Hero”&lt;/h2&gt;
&lt;p&gt;The camera is fixed on the player. World moves relative to the player.&lt;/p&gt;
&lt;p&gt;This demo is just to show how the world changes with respect to the player so does not account the case where the player reaches the edge. See the actual code in &lt;code class=&quot;language-text&quot;&gt;mario/src&lt;/code&gt; for that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;character2/main.lua Lines 93 - 103 =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- update camera scroll based on user input&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;left&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        characterX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; characterX &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; CHARACTER_MOVE_SPEED &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dt
    &lt;span class=&quot;token keyword&quot;&gt;elseif&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;right&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        characterX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; characterX &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; CHARACTER_MOVE_SPEED &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dt
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- set the camera&apos;s left edge to half the screen to the left of the player&apos;s center&lt;/span&gt;
    cameraScroll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; characterX &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;VIRTUAL_WIDTH &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CHARACTER_WIDTH &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the line &lt;code class=&quot;language-text&quot;&gt;cameraScroll = characterX - (VIRTUAL_WIDTH / 2) + (CHARACTER_WIDTH / 2)&lt;/code&gt; character width is added so that the world’s coordinates line up perfectly in the center. Also notice that we check for keypresses and keep updating &lt;code class=&quot;language-text&quot;&gt;characterX&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this example we just translate the world by the X axis and leave Y unchanged. Say mario could jump extremely high or we were to implement some sort of vertical scrolling game, we would have to translate on the Y axis as well (using the same approach as given above).&lt;/p&gt;
&lt;h2&gt;character3 “The Animated Hero”&lt;/h2&gt;
&lt;p&gt;If the player moves loop through some image to create the illusion of animation. Animations are nothing but a series of images shown in succession.&lt;/p&gt;
&lt;p&gt;Created a class called &lt;code class=&quot;language-text&quot;&gt;Animation&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pass in the frames you want animated.&lt;/li&gt;
&lt;li&gt;Time interval between each frame (quad) switch.&lt;/li&gt;
&lt;li&gt;If all frames have been looped through, repeat from start again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The class also includes logic for animating single and multiple frames. Idle animation for instance has a single frame. So by writing it this way the same class can be used for all animations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;What about moving left animation?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We just flip the drawing when calling &lt;code class=&quot;language-text&quot;&gt;love.graphics.draw()&lt;/code&gt;. If you recall it takes in optional arguments to flip it (rather scale, rotate i.e translate it). So we have to keep track whether he’s walking left or right and flip it on the X axis if he’s walking towards the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Animation.lua =&gt;&lt;/em&gt;&lt;/strong&gt; Notice that while initialising the class the current frame it set to 1 (line 17). Also on line 22 we check if there are more than one frames. If there’s only one frame it’s kept constant throughout otherwise on the completion of the specified timer we keep changing the frame.&lt;/p&gt;
&lt;p&gt;Notice that we have a function &lt;code class=&quot;language-text&quot;&gt;function Animation:getCurrentFrame()&lt;/code&gt; that returns the frame. The main render function basically calls this function every frame to get which quad to render. So every few hundred milliseconds it changes internally and therefore returns the next quad and the main render function shows that quad.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The animation class does not actually render the quad on screen. It just keeps track of the ongoing frame in the animation. Any render function can use this object to query the current frame and render it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua Lines 51 - 58 =&gt;&lt;/em&gt;&lt;/strong&gt; The idle animation object is defined here. An interval is passed into it for the sake of consistency even though it doesn’t make a difference. He’s also defined &lt;code class=&quot;language-text&quot;&gt;movingAnimation&lt;/code&gt; after that. Notice that the sprites 10 and 11 are the sprites which show the character moving (the walking away frames).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 60 and 67 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;currentAnimation&lt;/code&gt; keeps track of the animation currently activated. &lt;code class=&quot;language-text&quot;&gt;direction&lt;/code&gt; keeps track which direction the player is walking in so that we can flip conditionally flip the sprite while rendering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 150 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;love.graphics.draw()&lt;/code&gt; gets the current frame from the animation object by calling &lt;code class=&quot;language-text&quot;&gt;getCurrentFrame()&lt;/code&gt;. The animation object keeps updating the frame as time progresses and the render function gets the current frame to show from the animation object.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 150 - 160 =&gt;&lt;/em&gt;&lt;/strong&gt; All these lines are just one function call. When a sprite is flipped, it is done so with respect to it’s origin. Default origin is the top left corner. So by flipping the character it will drift a bit from the center. So while calling &lt;code class=&quot;language-text&quot;&gt;love.graphics.draw()&lt;/code&gt; the last argument we pass, we set the origin to be the center of the sprite. Normally the sprite is recentered when we flip sprites and want consistency.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you’re wondering how does the current animation switch?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 115 - 125 =&gt;&lt;/em&gt;&lt;/strong&gt; Continuously checks for keypresses. If right or left key is pressed, change &lt;code class=&quot;language-text&quot;&gt;currentAnimation&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;movingAnimation&lt;/code&gt; else let it remain &lt;code class=&quot;language-text&quot;&gt;idleAnimation&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;character4 “The Jumping Hero”&lt;/h2&gt;
&lt;p&gt;Question:- &lt;strong&gt;How to jump?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check for space, we need gravity, delta y. (Recall Flappy Bird and how we tracked gravity and delta y).&lt;/li&gt;
&lt;li&gt;Take care of jump animation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On closer observation it becomes apparent that we need two states. One while going up and the other to indicate that we are coming down.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why do we need two states?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While jumping we destroy blocks, when falling down we kill enemies. The inverse doesn’t hold true. We need a way to differentiate.&lt;/p&gt;
&lt;p&gt;The two states share the same animation but have different behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Main.lua 120 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;if key == &apos;space&apos; and characterDY == 0 then&lt;/code&gt; we ensure that DY is zero so that the player only jumps when he’s on ground. If he’s mid air, DY isn’t going to be zero and allowing him to jump in such a state will allow a player to jump infinitely in mid air.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Main.lua 132 - 135 =&gt;&lt;/em&gt;&lt;/strong&gt; We haven’t reached collision detection yet so we quickly hack it up. If the character reaches below the ground set his dy to zero so that he stops moving.&lt;/p&gt;
&lt;h2&gt;Procedural Level Generation&lt;/h2&gt;
&lt;p&gt;Colton found the easiest way to think and reason about generating tiles for this game was to go column by column. First you start with no tiles (just the sky denoted by a background colour). Then you go column by column and ask do I want ground here, if yes fill it will tiles from the bottom edge till ground level. Do you want a raised pillar here, if yes add a few more tiles post ground level. If you don’t want ground in that column (i.e a chasm or a ditch) don’t fill any tiles at all in that column. All this can be done with boolean flags and &lt;code class=&quot;language-text&quot;&gt;math.random()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Try thinking of ways to generate it row by row (horizontal strips across the screen) and it will dawn upon you that it’s much harder. Column by column helps to think of it in individual units (this column has a chasm, this has normal ground and so on) but row by row you are forced to deal with tiles that aren’t a part of the same structure.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;info-box&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b1a6b6bf80d26f99962f51c1fdb27a68/4b190/metaphors-models-programming.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.432432432432435%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMC/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAZsoJj//xAAWEAADAAAAAAAAAAAAAAAAAAABECD/2gAIAQEAAQUCRj//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAXEAEBAQEAAAAAAAAAAAAAAAAAAREh/9oACAEBAAE/Id1KrqKr/9oADAMBAAIAAwAAABBfP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EIj/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAYEAEBAQEBAAAAAAAAAAAAAAABEQAxIf/aAAgBAQABPxBEc5puBcd7i4kuTe7/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;how-metaphors-models-help&quot;
        title=&quot;&quot;
        src=&quot;/static/b1a6b6bf80d26f99962f51c1fdb27a68/1c72d/metaphors-models-programming.jpg&quot;
        srcset=&quot;/static/b1a6b6bf80d26f99962f51c1fdb27a68/a80bd/metaphors-models-programming.jpg 148w,
/static/b1a6b6bf80d26f99962f51c1fdb27a68/1c91a/metaphors-models-programming.jpg 295w,
/static/b1a6b6bf80d26f99962f51c1fdb27a68/1c72d/metaphors-models-programming.jpg 590w,
/static/b1a6b6bf80d26f99962f51c1fdb27a68/4b190/metaphors-models-programming.jpg 800w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;image-caption&quot;&gt; Taken from the book:- &lt;strong&gt;Code Complete 2nd Edition Chapter 2.1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The essence being how we see or model things (abstracting into classes or functions, think of a map as a 2D grid and those sort of stuff) makes a lot of difference while working on them. It opens up new possibilities, greatly simplifies and can even break stuff.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You could easily extend this idea. Say you want a pillar of varying width you could introduce a width variable and fill up the next few columns with a pillar and decrement the width variable by one on every iteration.&lt;/p&gt;
&lt;p&gt;Placing objects (grass, enemies, powerups etc) can be dealt with after you are done with the iteration that places all tiles. You can conditionally place objects on certain types of tiles (should not place grass on ditches and those sort of things). You can also keep track of where you’ve placed obstructions and place the next obstruction at a reasonable distance from the last.&lt;/p&gt;
&lt;p&gt;He then goes ahead to show how a varying sprite sheet with a simple algorithm like the one described above can be used to generate rich levels. Assortment of sprites for the ground tiles, topper (thin layer near the top most tile added for visual appeal) tiles, backgrounds, obstacles make it look vivid.&lt;/p&gt;
&lt;p&gt;The sprite sheet is well organised into similar chunks. This organisation provides easy programmatic access (splitting the sprite sheet into quads and accessing different variations of the same element. Most importantly the same can be done for all of them).&lt;/p&gt;
&lt;h2&gt;level0 “Flat Levels”&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 521px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f153114d50f2f836f952faf6d5ed11c7/bb9c5/topper-ground-identification.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.10810810810811%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACqElEQVR42nWRyU+TURTFX/thYiNRJPEPgMSFUBVlMIq4YMWCKBsHEEEjDgmWkACigKWmA6M4FChaaJEhFNqyqAxKRMtQMEYQcAAkxRKwpRVREuP2ePlaLXFY/HLvObn3vvveYwkOIxI/mJE49w/W/Q8mJLw3IHHW9Fv/xUwHji4+Qry5Aox91YO5H4B5tBuoJ4/iSgPYF50fXjf44y/vM/GjGaInUjDhahO4ZT04d6Mflw6b3OTN1YIbqwQ3dQfc5G1wb+568/U4fgvcW5+mGsFsNQK7aCAbrwR7XQU24WOM1l6kDR106kgJ2Mc6QgNmrwWb13i1XePPHcSMGsxVD1F3MQ1cprWnyRhSQkAnsn4pgl/U4Uj1PQQsNNKV9BC6qcZDuUe/AZ92+/jeCtFjGQ1cfQh+qNvXuKBFnCUbfYUHEGSv4RsFrmZvzf/4RLdZa4GolwYKVnQQurQQLmsR4KTP+daMOFsRLMWx2D6vBufRIX7pJgJd96m5nh8goCjk0fJR4CR/rQlbetffcKUTzGmkNzBC6OygK1pweFCBLmksttmbqLkDx6aTsHWJmlydpGkjVxth4nuYk6KTvDUjRD3lYOmlZUhVKHBGqUKaUomTqnJI5RJ0XzuES/JCpKjKkCyX8TXpJSpsdjQiqrMCGTfkSClV4bxMgaBpHXY9VyP5sgTs5VUxhnPEsOXthi1XjBFiKG8PnuVHkvZ6o6RHc8L5mmC7GtltaXiXGQprfgQmJTsRMlWO1D4JzKdCwYaLYmC9Ho2BAooF0UQM5dEYLIjivQGfN0g11sIYBC9qIDFfwES2GE+lB/EqZy9CZqpw2poLQ2oYmCkrEm2ZEWi/st/HPhj+1EQ7eQZJJHbYSnC2+gR6MsLQmhUFy0UxQvtlSGo5h5rj4fgJOE1SMgq8vxgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;topper-ground-identification&quot;
        title=&quot;&quot;
        src=&quot;/static/f153114d50f2f836f952faf6d5ed11c7/bb9c5/topper-ground-identification.png&quot;
        srcset=&quot;/static/f153114d50f2f836f952faf6d5ed11c7/12f09/topper-ground-identification.png 148w,
/static/f153114d50f2f836f952faf6d5ed11c7/e4a3f/topper-ground-identification.png 295w,
/static/f153114d50f2f836f952faf6d5ed11c7/bb9c5/topper-ground-identification.png 521w&quot;
        sizes=&quot;(max-width: 521px) 100vw, 521px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topper with ground. How it’s done?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;He’s just taking the topper and the tile set (ground tiles) from different parts of the sprite sheet. We don’t fix a place for toppers so as to keep it general enough to work with pillars and chasms. There’s a flag which indicates whether a tile has a topper or not. If it’s set to true if it’s the topmost tile of that column.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Splitting tile set and toppers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Have a look at &lt;code class=&quot;language-text&quot;&gt;tiles.png&lt;/code&gt; for a better idea of what we’re about to do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;level0/utils.lua =&gt;&lt;/em&gt;&lt;/strong&gt; We need to write a four way nested loop to get the tiles and toppers. The first two levels of nesting is to actually get one of the 30 (3 X 10) different segments of tile sets. After that’s done, we’ll have to iterate again and get tiles across the X and Y dimensions again. So we’ll need a two level nested loop for that. Have a look at &lt;code class=&quot;language-text&quot;&gt;GenerateTileSet()&lt;/code&gt;. It takes in the actual quads, the X and Y of the large segment (3 columns by 10 rows) and the size of each segment as well. Basically taking a segment of the sprite sheet and extracting the desired group of related tiles from it.&lt;/p&gt;
&lt;p&gt;This is only possible as the sprite sheet is structured and laid out in an organised fashion. Programmatic access would not have been possible if they were randomly spread out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;level0/main.lua =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constants for width, height etc.&lt;/li&gt;
&lt;li&gt;Gets quads from the respective sprite sheet and then split them into relevant sets using &lt;code class=&quot;language-text&quot;&gt;GenerateTileSets()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 223 - 249 =&gt;&lt;/em&gt;&lt;/strong&gt; Use a table to represent the entire world. Fill in blank tiles to represent the sky, if height is equal to 7 give it a topper (thin layer that the player actually walks on).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 139 &amp;#x26; 140 =&gt;&lt;/em&gt;&lt;/strong&gt; The tile and topper set is a result to something random when r is pressed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;level1 “Pillared Levels”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;How to put pillars?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just put up tiles above ground level in that column.&lt;/p&gt;
&lt;p&gt;You could have a flag spawn pillar which controls whether to have a pillar or not. You could also pass in the width or something and draw the same height multiple times and set the flag back to false.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua Line 227 - 236 =&gt;&lt;/em&gt;&lt;/strong&gt; Fill the entire map with the sky tile. So the level is basically empty at this point.&lt;/p&gt;
&lt;p&gt;Once done we don’t have to worry about inserting or managing the table. We can just replace the stuff we want.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua Line 239 - 259 =&gt;&lt;/em&gt;&lt;/strong&gt; Go column by column to generate the level map. Randomly set a flag to generate a pillar or not. If the flag is true fill in positions 4, 5 &amp;#x26; 6 with tiles (these are 3 positions above ground.) Also place a topper on the top most tile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua line 253 to 259 =&gt;&lt;/em&gt;&lt;/strong&gt; Fills tiles to create the ground in that column. If a pillar exists don’t put a topper else place a topper as usual.&lt;/p&gt;
&lt;p&gt;You can also create mario like steps instead of straight pillars in a similar manner. Keep reference to the previous height and thn iterate (each iteration reduce height). You could also keep track of width and keep increasing height till half way up and reduce height from there on.&lt;/p&gt;
&lt;p&gt;Because of the code’s random nature it’s possible that two pillars spawn next to each other. Pseudo random generators can also surprise the person who wrote the code.&lt;/p&gt;
&lt;h2&gt;level2 “Chasmed Levels”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;How to generate chasms?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You just skip a column. So at the start itself you randomly decide if you want a chasm in the block or not (in the code there’s an arbitrary set to &lt;code class=&quot;language-text&quot;&gt;math.random(7)&lt;/code&gt; for 1 in a 7 chance, which in general is a bad practice).&lt;/p&gt;
&lt;p&gt;I think (I’m not sure myself) the reason being you have no control over where the chasm ends up (like the very first step where the player stands) and it probably is a very raw approach, we could do better by having a few hand spun rules like at so many intervals, only after a certain point in the level.&lt;/p&gt;
&lt;p&gt;Lua has no continue statements, so we use a goto statement and avoid rendering ground in the column. Using &lt;code class=&quot;language-text&quot;&gt;::continue::&lt;/code&gt; is a community accepted standard work around for the same.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audience Question =&gt; Level generation do we do it all at once?&lt;/strong&gt;&lt;br&gt;
In mario we do it all at once. It’s pretty small and can easily fit in memory. Also it’s much easier to teach like that.&lt;/p&gt;
&lt;p&gt;Incremental approach can be taken for infinite runners. You split the game into parts. As the user approaches the right end, generate the new level, obstacle etc and append it to the level. You can discard the level or obstacle that the user has already crossed (in infinite runners you normally can only move in one direction).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audience Question =&gt; Do we render the entire level at once?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes . Since it’s a small game rendering the entire map 60 times a second isn’t a problem. Large game render only a certain section. You would write your code to ensure it renders only areas near the camera or the user.&lt;/p&gt;
&lt;p&gt;Related resource from a previous lecture &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-02-flappy-bird/#games-are-illusions&quot;&gt;Games are Illusions&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Tile Collision&lt;/h2&gt;
&lt;p&gt;We have a fixed 2D tile system. We can get to the tile from the x &amp;#x26; y coordinates. We can use that to your advantage. We just have to check that particular tile. If you recall with AABB collision detection you have to iterate over all the tiles to check if it’s colliding with the player. In this case we know where the player is and we just can check that tile.&lt;/p&gt;
&lt;p&gt;You can find the relevant function in &lt;strong&gt;mario/TileMap.lua&lt;/strong&gt;. Also I’d recommend seeing slide#25 for more details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tile collisions while jumping up =&gt;&lt;/strong&gt; Just check both the top edges of our character (which tile the head hits). Checking only one side will miss a collision if half his body is under a tile and the other half is not blocked by anything (and we happen to check the side which is not under anything). We just need the tile our player will hit. We get the index of the tile and check if it’s solid (property set via a flag in the table).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 415px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9a7a3f926053f177406339b77c11fa2b/73926/exact-gaps-jumping-up.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.5945945945946%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAADYUlEQVR42gFWA6n8ADQ0KpWLMpWJKZeUTpSIJ5iQOY2JRTEvJCMkJicnJiYmJiYmJiUlJnlzNZmMJZaSSJaNNpOHKKCbTkxIKQBBQCn++mv/6zP+9U3+92X/7Szs51g9OywiISQpKSgoKCgnJiYkIyPHxFf/+k/86zT//XL75jL//1BvbjsAPjkc8N499u5q7tcj8+da+Oxa28UdOTgmICQkHyEdICAfJSckIiUmuKgg//dv79078d888upp/eUpaWAeAEA9J/DYJPbmSvfsYPHYIfryZevTQlYsFEkkM39laHxoYlEtNUIaHdCpI/nnNfjvbvLbKfLiSP/6YWpgHgBAPy3272ny3C3261726lr04TLv2V9OPTSLtYmv/XjL/ayXxJA6LzTYtFT67ETz4EL48nDu2Cv/+WBtaj4APzob9OVH+e5g8dga+O1j+exM4r0Qiop9k/ZbhvAonO9Tmv1ZdoV8zp8b//1x8tsp9eZG9etf/+cga2IiAD47I+zTGvToV/LlUe7WIvn0cOG/JpCKeYHWUFSbFlCcEIPYSH6KhcmVDfjrQfTsa+7VHvDkVv/zVGhdFwBAPi7z51nw2in17Gjx4Uby4znq015cejuR7GuF3zZ/1jSY9GlKcz/UsEr25jbx41D062Hr1if/+WlraDkAPzsf9upZ9+hN8dok+PBp9eI379YsWaAnU6pTgd9lgt9lXbNWQ5wm3cg0/fNm8Nkh9+xZ8+RM/+gobGUtAD86IPDZJvnxbPPiQ/PfOvv2dOvMJkA4Hi6gJD7ZI0fdJj+xJScwJtOmFPzzW/brYvHaJ/Xtav/wR2leGABBPy304kTz3Cr48W3y3DD250Tx215WKBxNUjZSWy5QVyxUXTg/Ex/asUL35Cj26l715kvv2Cj//m1sZjAAPzwj9Otl8uA879ou9e5r890o4dA9SjgqMiAhNiAiNR4jNyUiNCEfw7RI/fFb7dQe9u1o7tw6/ukybGc1AEA7HfrmMf/9dfvqO/zuSv//dOfTJjc4IR0jKCMpJyIpJyInJx8kJ8GvG///avzyW/voMfz5c//5QW1iGQAxMCZ+cx+BeS6CfT5/ch2Efjx5cjEvLCIlJScoJyYnJyYnJyYmJSdoXyOEeSOCfkKAdCJ/dy2Igz1EPyGXrK+2kw+RkQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;jumping-through-exact-gaps&quot;
        title=&quot;&quot;
        src=&quot;/static/9a7a3f926053f177406339b77c11fa2b/73926/exact-gaps-jumping-up.png&quot;
        srcset=&quot;/static/9a7a3f926053f177406339b77c11fa2b/12f09/exact-gaps-jumping-up.png 148w,
/static/9a7a3f926053f177406339b77c11fa2b/e4a3f/exact-gaps-jumping-up.png 295w,
/static/9a7a3f926053f177406339b77c11fa2b/73926/exact-gaps-jumping-up.png 415w&quot;
        sizes=&quot;(max-width: 415px) 100vw, 415px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Notice how the top portions of the bounding box of the player touches the tiles (it therefore will trigger a collision even though the player’s head is not touching the box). Reduce one pixel from each side which checking for collisions so that it can go through gaps that are exactly of the same size without triggering a collision.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To get the tile index =&gt;&lt;/strong&gt; 6th from top, 5th from top and so on , we just have to divide the player’s Y coordinate by a tile height and add one to it. The same things can be done for the X coordinate as well. We can then index into the tilemap table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bottom Collisions =&gt;&lt;/strong&gt; We do something very similar for the bottom. This time we check for collisions with the character’s bottom edges. The coordinates of the bottom edges are (x, y + height) and (x + width, y + height). The same is done for checking right and left collisions.&lt;/p&gt;
&lt;p&gt;Remember that top, right, bottom and left collisions are checked in different states. We need to check top collision while jumping for instance. We needn’t check for top collisions while walking towards the right for instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;mario/src/TileMap.lua =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 27 - 33 =&gt;&lt;/em&gt;&lt;/strong&gt; We can easily get the current position of the player and from that we can easily get the tile the player is on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 28 - 29 =&gt;&lt;/em&gt;&lt;/strong&gt; If the player happens to be beyond the map boundaries then return nil rather than a tile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 32 =&gt;&lt;/em&gt;&lt;/strong&gt; Lua tables are one indexed but geometric coordinates are zero indexed. So we add 1 to the indices we get.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Advantages over AABB&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Just find out which tile the player is on.&lt;/li&gt;
&lt;li&gt;We don’t have to iterate over all the tiles and perform AABB collision on them (recall Breakout).&lt;/li&gt;
&lt;li&gt;Kind of like a linked list vs array. Array you know exactly where to look and can get what you want immediately. Linked list you have to iterate one by one until you find it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is good to repeat again. You check for collisions at different points on the character based on the different actions he performs. Say he is jumping you check for collisions on the top left and right edges. Since the gaps are wide enough to let our player pass between them we only check the top edges while jumping. Assume that our player is 8 tiles tall, in that case we’d have to check for collisions across his entire body even while walking.&lt;/p&gt;
&lt;p&gt;Game objects need a different treatment and are a little more complex. Have a table of some objects like snails and we have to iterate over them one by one to check for collisions. It’s because they have their own X &amp;#x26; Y coordinates and unlike the tiles they aren’t fixed at a place.&lt;/p&gt;
&lt;h2&gt;Entities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Almost anything that you want can be an entity.&lt;/li&gt;
&lt;li&gt;In this particular game Colton has modelled everything that moves or is sentient as an entity (snails for instance).&lt;/li&gt;
&lt;li&gt;They can have their own state.&lt;/li&gt;
&lt;li&gt;He explained a little about Entity Component Systems. In such systems everything is an entity, each entity has components (we’ll discuss it below). Unity for instance is an entity component system.&lt;/li&gt;
&lt;li&gt;I like to think of them like CSS classes. Every new class added to the HTML element gives it additional properties.&lt;/li&gt;
&lt;li&gt;Everything has properties and these properties ultimately define the behaviour of the object.&lt;/li&gt;
&lt;li&gt;Instead of a deep tree with inheritance (Say you have a base class Monster, Goblin a subclass inherits from it, the subclass GoblinWarlord inherits from Goblin and so on), you have a container which you compose (or fill) with components or properties. All the pieces together create what you want rather than having to inherit from parent classes.&lt;/li&gt;
&lt;li&gt;Entities are often objects that do things or perform some action. In this game the tile map are just statically rendered and are not entities. Stationary objects are not considered to be entities as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Interacting with Entities&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;mario/scr =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;GameLevel.lua Line 14 - 16 =&gt;&lt;/em&gt;&lt;/strong&gt; References to entities (enemies), objects (the non living stuff like obstacles, coins etc) and tilemap.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;GameLevel.lua Line 36 - 46 =&gt;&lt;/em&gt;&lt;/strong&gt; Update (position, health, consumed or not etc) the tilemap, the objects and entities. The main update function calls this. Notice how the individual update function of each object and entity is called.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;GameLevel.lua Line 51 - 58 =&gt;&lt;/em&gt;&lt;/strong&gt; This piece of code in responsible for rendering them. It calls the individual render function of each object and entity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Player Falling State&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;mario/src/states/entity/PlayerFallingState.lua Lines 62 - 78 =&gt;&lt;/em&gt;&lt;/strong&gt; Iterate over every game object. If the game object is solid change dy (rate of change of height) to zero and move the player just above the object. If the object is consumable (gem for instance) remove the consumable object without doing anything to the player.&lt;/p&gt;
&lt;p&gt;Depending on the object do different stuff. If it’s an enemy it dies or kills you, if power up show the relevant effect and so on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for the link on Entity Component Systems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Game Objects&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/090c0352ffecf67edf8d7e28d71666e6/715a3/game-objects.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 24.324324324324326%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAABMElEQVR42g3PzUoCQRwA8H2CTkEHI3Gdmf/Mfs3qzqy7reCu31mZRpuiEoYXCwXtg4IMg04SRHQKunboBSLo1pvV7w1+ipRZbhkZl5uWLrllcVu3swihduS0C2bZ01rbhshyAoAQTqcJRkQlhCCVYKzMx/lqKROe+RXXngmT12JePQY1+TgMJ6G2KjmXkTjpx34hsvS08JjpUA+A2i6hTLmdRXE3V5kWO0V547lBcygORlhNXewb1ztwv2f0OvXe4FA3ndMjvHjiu3PrVcdud5EKGsrPZ/PuoRh/tJdx+J3369PnYPKS2tocReiqgcY10iiLesVPqmx5nnj7SrRW6u/GmtF/X48GCsB/A4BRjIEBQQQoUE1jkrO8o+dsAwhFiFDKnAyTOWoK5lPQuGQm/wNhGElymbiEUAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;game-objects&quot;
        title=&quot;&quot;
        src=&quot;/static/090c0352ffecf67edf8d7e28d71666e6/fcda8/game-objects.png&quot;
        srcset=&quot;/static/090c0352ffecf67edf8d7e28d71666e6/12f09/game-objects.png 148w,
/static/090c0352ffecf67edf8d7e28d71666e6/e4a3f/game-objects.png 295w,
/static/090c0352ffecf67edf8d7e28d71666e6/fcda8/game-objects.png 590w,
/static/090c0352ffecf67edf8d7e28d71666e6/715a3/game-objects.png 830w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Things that don’t go well with the tile dimensions, maybe they are of different sizes, appear at weird places etc. Examples are powerups, ladders, coins, ropes etc.&lt;/li&gt;
&lt;li&gt;Test them using AABB collision.&lt;/li&gt;
&lt;li&gt;We could have modelled them as entities but in this project it’s not the case.&lt;/li&gt;
&lt;li&gt;In this game, entities are living sentient beings, game objects are non living. Colton adds that for small projects as this everything could be entities.&lt;/li&gt;
&lt;li&gt;Definitely have a look at Slide #30.&lt;/li&gt;
&lt;li&gt;In bigger games, different varieties of the same object exist (different types of bricks, gems etc). In such a case we could have a class for object and have sub classes which inherit from the base. This way we’d easily model a lot more objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How would you implement ladders?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Check for a collision with a ladder. If it’s true and the up arrow key is pressed then enter climb state. If reached the end enter walking state again.&lt;/p&gt;
&lt;p&gt;You can generate a lot of objects based on functionality. For instance:-&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ropes and ladders all trigger a climbing state.&lt;/li&gt;
&lt;li&gt;Bushes, mushrooms are cosmetic. Nothing happens when you jump on them.&lt;/li&gt;
&lt;li&gt;Spikes and a few other objects are lethal. You can have a flag &lt;code class=&quot;language-text&quot;&gt;isLethal&lt;/code&gt; against the object and on collision it should kill the player.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;LevelMaker.lua =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It generates game objects randomly.&lt;/li&gt;
&lt;li&gt;Every object has flags like collidable, consumable, solid etc. when a player collides with an object the respective callback function is activated. When a gem is consumed for instance, score increases, a sound is played and the gem disappears.&lt;/li&gt;
&lt;li&gt;Each game object also has an associated texture, height, width, x and y coordinates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;mario/src/LevelMaker.lua =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 56 - 74 =&gt;&lt;/em&gt;&lt;/strong&gt; There’s a one in 8 chance to spawn a pillar. There’s a one-eight chance of having a bush on a pillar. So in all there’s a one in 64 chance of having a pillar with a bush.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 85 - 91 =&gt;&lt;/em&gt;&lt;/strong&gt; Look at how the properties are set. Especially note line 91 which sets &lt;code class=&quot;language-text&quot;&gt;collidable = false&lt;/code&gt;. Bushes therefore don’t trigger anything when collided against.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 97 - 112 =&gt;&lt;/em&gt;&lt;/strong&gt; Randomly deciding to generate a block or not. On line 112 &lt;code class=&quot;language-text&quot;&gt;solid = true&lt;/code&gt;. The user cannot pass or move through them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above set properties are tested for and certain actions can then be triggered depending on these properties. Open &lt;code class=&quot;language-text&quot;&gt;mario/src/Player.lua&lt;/code&gt; and have a look at the methods &lt;code class=&quot;language-text&quot;&gt;Player:checkRightCollisions(dt)&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Player:checkObjectCollisions()&lt;/code&gt; to see how they are used.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Audience Question =&gt; Wouldn’t it be better to have a helper class that takes care of creating objects?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Such a pattern is called a Factory Pattern (or at least is very similar in spirit).&lt;/p&gt;
&lt;p&gt;At this scale it isn’t necessary. So he just created one class called &lt;code class=&quot;language-text&quot;&gt;GameObject&lt;/code&gt; that abstracts away creation of all objects. He also felt the need to reduce the number of files to simplify the code and increase comprehension. If Colton were to design a large game he would probably create a class for each kind of object like a bush class, a gem class and so on. In a large game there’d be many kinds of gems, bushes and so on. The class would take optional parameters to create different variations of bushes and so on.&lt;/p&gt;
&lt;p&gt;The current &lt;code class=&quot;language-text&quot;&gt;GameObject&lt;/code&gt; class is abstracted enough to allow for custom event handlers that can be tested for conditions. We can thus define custom behaviour for them. For instance a gem is consumable but a bush isn’t. So on collision we check if the flag &lt;code class=&quot;language-text&quot;&gt;consumable&lt;/code&gt; is true and then we call a custom function.&lt;/p&gt;
&lt;p&gt;He again briefly hints at Entity Component Systems. It’s a pretty neat way of modelling stuff. You just add components like consumable to an object such as a gem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; and check out the link on Factory Patterns.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[GD50 Lecture 04 - Match 3]]></title><description><![CDATA[This is a part of a series of notes. You can find notes to other lectures here
Please feel free to bring to my attention mistakes, other…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources-04-match-3/</link><guid isPermaLink="false">4e00c649-ca93-4e2e-b8f0-4c45262a66bd</guid><pubDate>Fri, 09 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a part of a series of notes. You can find notes to other lectures &lt;a href=&quot;/introduction-game-development-gd50-notes-resources/&quot;&gt;here&lt;/a&gt;
Please feel free to bring to my attention mistakes, other interesting resources and feedback via the comments section. I’m all ears and will do my best to incorporate them into the blog post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/245192/what-are-first-class-objects&quot;&gt;What are First Class Object?&lt;/a&gt; - This is the link I referred to when I wanted to know more about Python function.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/10273185/what-are-the-benefits-to-using-anonymous-functions-instead-of-named-functions-fo&quot;&gt;When to use Anonymous Functions?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=lUqFelc84XE&quot;&gt;Bubble Sort Visualised.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/761825/5698202&quot;&gt;String Strip in Python.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Game Description&lt;/h2&gt;
&lt;p&gt;Grid of small objects that you should group into collections of 3 or more. The score is directly proportional to the number of objects you get together. Whenever you match similar object together they disappear and are replaced by more objects. Bejeweled and Candy Crush are some Match style games that you probably are aware of.&lt;/p&gt;
&lt;h2&gt;timer0 “The Simple Way”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;How would you implement a simple timer (1 2 3 and so on)?&lt;/strong&gt;&lt;br&gt;
Some variable that you keep modifying by adding DT (time between each frame). You could also simply display it on the screen as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua =&gt;&lt;/em&gt;&lt;/strong&gt; Variables &lt;code class=&quot;language-text&quot;&gt;currentSecond&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;secondTimer&lt;/code&gt; are declared. secondTimer stores the time progression since the last tick and is reset once it crosses 1. Every time secondTimer is reset, currentSecond is incremented.&lt;/p&gt;
&lt;p&gt;Note that we don’t set secondTimer to 0. We instead do &lt;code class=&quot;language-text&quot;&gt;secondTimer = secondTimer % 1&lt;/code&gt; so that if secondTimer is a little above a second, it keeps that value. The excess value reduces the span of the next tick (Check &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-02-flappy-bird/#bird10&quot;&gt;this&lt;/a&gt; out for more details). &lt;strong&gt;&lt;em&gt;Lines 40 - 47&lt;/em&gt;&lt;/strong&gt; implement the described functionality.&lt;/p&gt;
&lt;p&gt;You can expect every DT to be approximately equal to 1/60&lt;sup&gt;th&lt;/sup&gt; of a second as the screen gets updated 60 times a second.&lt;/p&gt;
&lt;p&gt;This is a bad way of doing it. It doesn’t scale.&lt;/p&gt;
&lt;p&gt;Also keep in mind that Lua doesn’t differentiate between a float and an int. Lua only has one numerical type. So you can use modulo 1 on a float as well.&lt;/p&gt;
&lt;h2&gt;timer1 “Also The Ugly Way”&lt;/h2&gt;
&lt;p&gt;5 timers on the screen this time. 5 times the code as the previous example. He mentioned in the last section that it isn’t scalable. He shows it here. Since there are 5 timers he’s used a loop.&lt;/p&gt;
&lt;h2&gt;timer2 “The Clean Way”&lt;/h2&gt;
&lt;p&gt;Global time object which manages everything with the power of anonymous functions. Please note that we could use normal functions as well. The task at hand is very trivial and we don’t use it in more than one place. Hence Colton has resorted to anonymous functions.&lt;/p&gt;
&lt;p&gt;We use a library called Timer (it’s a part of the knife ecosystem).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- interval is in seconds&lt;/span&gt;
Timer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Timer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Timer.every(interval, callback)&lt;/code&gt; is similar to JavaScript’s setInterval. You can specify a function to be executed every x seconds forever. An anonymous function is passed (you can pass in any function, it doesn’t have to be anonymous). The function gets called everytime the interval runs out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 21 - 32 =&gt;&lt;/em&gt;&lt;/strong&gt; Declared the intervals and second counters in a table. Iterate over those values and just set a Timer. Notice the nameless function on line number 29.&lt;/p&gt;
&lt;p&gt;Notice how the code falls from 98 lines in the earlier example to 70 lines. We can even specify more timers without increasing the lines of code (just add more timers to the table). This is very scalable. It’s declarative as well (just specify how long you want a timer. No additional logic).&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Timer.after(interval, callback)&lt;/code&gt; does something once after the given interval.&lt;/p&gt;
&lt;p&gt;You should checkout this library called &lt;a href=&quot;https://github.com/airstruck/knife&quot;&gt;Knife&lt;/a&gt;. We only use Tween and Timers but this library has a lot more functionality to offer. Checkout slide #15 for a gist of the modules that Knife provides.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The title changes colours. A timer is used to change the colour of the letters every 0.75 seconds.&lt;/li&gt;
&lt;li&gt;Inside the game there is a countdown timer that goes from 60 to 0. User gains more time by making matches and the game ends when the timer touches 0.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Also remember that you have to remove or unset a timer. Timers are global objects, so if they are not needed in the new state or not needed after a certain point, unset them.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for the links on anonymous functions and first class objects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;tween0 “The Simple Way”&lt;/h2&gt;
&lt;p&gt;Tweens are used to change values over time. Say opacity from 100 to 0 in x seconds of time or say move an object from this position to that position in 5 seconds.&lt;/p&gt;
&lt;p&gt;Colton then shows a screen where he moves a bird from one end to another in 2 seconds. He also points that it doesn’t do the task in exactly 2 seconds (took 2.01, 2.0089 etc). It depends on the specs of the computer. If it can maintain a high frame rate it’ll be more accurate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 19 =&gt;&lt;/em&gt;&lt;/strong&gt; The time the bird should take to move to the final position.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Line 31 =&gt;&lt;/em&gt;&lt;/strong&gt; The final x position of the tween is set.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Lines 52 - 61 =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
On every frame just increment the position by the proportion of movement to the time elapsed. Just scaling to the ratio of elapsed time to move duration. &lt;code class=&quot;language-text&quot;&gt;math.min&lt;/code&gt; is used so that it doesn’t cross the end position.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; timer &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; MOVE_DURATION &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; timer &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; dt

        &lt;span class=&quot;token comment&quot;&gt;-- math.min ensures we don&apos;t go past the end&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;-- timer / MOVE_DURATION is a ratio that we effectively just multiply our&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;-- X by each turn to make it seem as if we&apos;re moving right&lt;/span&gt;
        flappyX &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;endX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; endX &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; MOVE_DURATION&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can assign multiple variables in a single line in Lua (similar to Python), just separate the values with a comma. &lt;code class=&quot;language-text&quot;&gt;A, B = 1, 2&lt;/code&gt; for instance sets A to 1 and B to 2.&lt;/p&gt;
&lt;h2&gt;tween1 “A Better Way”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 29 - 43 =&gt;&lt;/em&gt;&lt;/strong&gt; Insert into a table the positions of 1000 bird with x as 0 and a random value for y (so that they scatter across the screen and cover the left hand side in it’s entirety). Also the rate at which it reaches the end is set. Notice that &lt;code class=&quot;language-text&quot;&gt;math.random&lt;/code&gt; is used twice. It’s used without any argument so that it returns a float. &lt;code class=&quot;language-text&quot;&gt;math.random(8)&lt;/code&gt; will return an int between 0 and 8, so by adding the additional float we are sure that rate is a float.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 70 - 85 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;love.update()&lt;/code&gt; same like before. Keeps updating time as long as it is below &lt;code class=&quot;language-text&quot;&gt;TIMER_MAX&lt;/code&gt;. Scale each bird’s x coordinate by time passed and the duration it should take to reach the end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stress Testing:-&lt;/strong&gt; Enable FPS and go berserk. He tries rendering 10,000 birds and it works pretty fine. He increases the count and tries moving a million birds across the screen. The frame rate drops below 10.&lt;/p&gt;
&lt;p&gt;You get a good idea of the limits of your game and the system as well.&lt;/p&gt;
&lt;h2&gt;tween2 “The Timer.tween Way”&lt;/h2&gt;
&lt;p&gt;Changing movement and opacity of the birds over time now. Doable using the previous approach but it gets dirty pretty quick.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 89 =&gt;&lt;/em&gt;&lt;/strong&gt; You can set an opacity for fonts, graphics and images. Recall that you can specify an opacity when you define a colour to be used. Love uses the last colour set. So to modify the opacity of a drawable independent of it’s colour set colour to white i.e &lt;code class=&quot;language-text&quot;&gt;(255, 255, 255, desiredOpacity)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Code is very similar to the earlier example. In addition to the rate and x, we also store the starting opacity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 54 - 59 =&gt;&lt;/em&gt;&lt;/strong&gt; We tween each bird in the birds table. &lt;code class=&quot;language-text&quot;&gt;Timer.tween()&lt;/code&gt; takes bird.rate and the values to tween. We pass in the bird currently being iterated upon and specify the final values as &lt;code class=&quot;language-text&quot;&gt;{ x = endX, opacity = 255 }&lt;/code&gt;, so over the duration of bird.rate it consistently approaches the specified final values. We can pass in classes, tables and even variables to be changed inside &lt;code class=&quot;language-text&quot;&gt;Timer.tween()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With just 2-3 more lines of code, we can now tween two variables. This can be extended to tween even more variables with trivial changes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Level text comes from the top to the center of the screen. It’s opacity and positions are tweened.&lt;/li&gt;
&lt;li&gt;There’s a rectangle with stats. It’s opacity is tweened from 0 till it appears.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Code Run Through&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;StartState.lua Lines 24 - 31 =&gt;&lt;/em&gt;&lt;/strong&gt; The colour table of the title text. Every 0.75 seconds the colours are cycled through. If a letter had colour1 it is now rendered with colour2, letters which were rendered with colour6 are now rendered with colour1 and so on. Check lines 44 - 52 for the implementation of the timer. The timer is removed on line 92 as the timer is no longer needed in the BeginGame state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;StartState.lua Lines 81 - 94 =&gt;&lt;/em&gt;&lt;/strong&gt; If the user chooses to start the game, we tween our transition rectangle (just a rectangle with some text) from 0 to 255 (it means the rectangle was always present, it just wasn’t invisible until we increased it’s opacity). Also notice that we can pass in an anonymous function that is to be executed once Love’s done tweening the transition rectangle.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;chain0 “The Simple (and Hard… and Ugly) Way”&lt;/h2&gt;
&lt;p&gt;Exploring ways to do stuff in succession. Say you want a non playing character to go walk 5 steps in 3 seconds, start a dialog with you, then do xyz. We want a way to reduce code complexity as well. If void of any special constructs, we’d model it using if statements. If the NPC has reached destination, open dialog box, if the dialog has been read, close it and so on. These conditions would be checked on every frame update. You can probably imagine the code getting complex pretty quickly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question:- Colton then shows a bird move around the perimeter of a screen. How would you do that?&lt;/strong&gt;&lt;br&gt;
You would have a bunch of if statements and variables to keep track of goals (top portion traveled along, right portion traveled along and so on).&lt;/p&gt;
&lt;p&gt;Additionaly we need to account for time as well. The bird has to move across the screen in some predetermined time.&lt;/p&gt;
&lt;p&gt;The code base becomes ugly pretty quickly. Also we now have to carry state (goals, positions etc).&lt;/p&gt;
&lt;p&gt;In chain0 a very similar approach is used. Instead of an if else ladder, we use tables. Basically we store information that will help us do the above task in a table. We store the X and Y values that the bird should travel to in order.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note that we could use a table because the 4 goals were very similar. Had they been different, we would have resorted to an if else ladder.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;destinations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_WIDTH &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; flappySprite&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWidth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_WIDTH &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; flappySprite&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWidth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_HEIGHT &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; flappySprite&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHeight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_HEIGHT &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; flappySprite&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHeight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;br/&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Chain.lua Lines 66 - 89&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;timer variable to measure time elapsed since the last destination (i.e reaching a point in the table). It is reset to 0 everytime a goal is achieved.&lt;/li&gt;
&lt;li&gt;Iterate over the table and move the bird to the destination X and Y over time from the base (current X and Y).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 82 =&gt;&lt;/strong&gt; Every destination coordinate becomes the base for the next goal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 75 &amp;#x26; 76 =&gt;&lt;/strong&gt; Update current X and Y coordinates of the bird in parts. Say the bird has to move 100 units in 2 seconds so at the 1st second it should be 50 units from the initial position. This scaling is handled by &lt;code class=&quot;language-text&quot;&gt;(destination.x - base.x) * (timer / MOVEMENT_TIME)&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;(destination.x - base.x)&lt;/code&gt; gives the distance it has to cover and &lt;code class=&quot;language-text&quot;&gt;(timer / MOVEMENT_TIME)&lt;/code&gt; gives the ratio considering the time elapsed and the total time it should take.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;chain1 “The Better Way”&lt;/h2&gt;
&lt;p&gt;We can use this approach for any operation including tweens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 30 - 47 =&gt;&lt;/em&gt;&lt;/strong&gt; Use &lt;code class=&quot;language-text&quot;&gt;:finish&lt;/code&gt; on every tween to define what’s to be executed next. We further pass in tweens as anonymous functions on the completion of a tween.&lt;/p&gt;
&lt;p&gt;Passing in a function to another function to be executed on the completion of the calling function (nested callbacks) can at times lead to callback hell (was a very common phenomenon in the JavaScript community).&lt;/p&gt;
&lt;p&gt;There are ways to counter callback hell. The &lt;code class=&quot;language-text&quot;&gt;Chain&lt;/code&gt; construct can take in functions to be executed and will ensure they are executed in order. It’s very declarative and elegant.&lt;/p&gt;
&lt;p&gt;The number of lines drop from 96 to 70. It’s also cleaner, promotes a declarative style to define async behaviour and is much more managable.&lt;/p&gt;
&lt;h2&gt;swap0 “Just a Board”&lt;/h2&gt;
&lt;p&gt;This update just renders a board and doesn’t actually deal with swapping tiles.&lt;/p&gt;
&lt;p&gt;Generate sprite quads for the tiles from an image by evenly dividing the image into pieces like how we did in Breakout. Each block is 32 x 32 units.&lt;/p&gt;
&lt;p&gt;3 or more of the same colour is a match. The lecture code doesn’t care about the inscriptions on the tile (cross, ovals etc).&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;generateBoard()&lt;/code&gt; returns a 8 * 8 2D array. It’s similar in spirit to the basic levelmaker of Breakout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why &lt;code class=&quot;language-text&quot;&gt;table[y][x]&lt;/code&gt; and not &lt;code class=&quot;language-text&quot;&gt;table[x][y]&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
Look closely how the table we construct maps to the actual grid, you will notice that each row of the grid (therefore height) maps to the first index and so on of the our 2D table (table with tables).&lt;/p&gt;
&lt;p&gt;It’s important to keep the fact that we index the table for the grid. So for the sake of convinience we do the bookkeeping in this way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 66 - 84 =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a blank table for filling in the rows.&lt;/li&gt;
&lt;li&gt;Insert into the this blank table an X coordinate, a Y coordinate and a random number that will be used to index into the quads to generate a random tile.&lt;/li&gt;
&lt;li&gt;Table indices are 1 based but the coordinate system starts from 0. So we subtract one from the table index and then multiply by 32 (the width of a tile is 32). This gives the X and Y coordinate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 89 - 102 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;drawBoard()&lt;/code&gt; takes in an X and Y offset and renders the above grid of tiles starting from that offset. It adds this offset to all the X and Y coordinates of the tiles and also uses the associated tile number in the quad table to render the appropriate sprite.&lt;/p&gt;
&lt;h2&gt;swap1 “The Static Swap”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;How to swap two tiles?&lt;/strong&gt;&lt;br&gt;
Just swap two tiles (like how you interchange the values of two ordinary variables). In the tiles table we just need to swap places. We use a third variable (that acts as a holder) to swap the values. If we don’t use this temporary variable or holder we’ll lose information pertaining to one of the tiles.&lt;/p&gt;
&lt;p&gt;In Lua you don’t have to use a temporary variable to swap (recall that you can assign multiple variables values. Eg &lt;code class=&quot;language-text&quot;&gt;x, y, z = y, z, x&lt;/code&gt; would swap x’s value with y, y’s value with z and z’s value with x).&lt;/p&gt;
&lt;p&gt;A rectangle indicates which the tile the user is on. Arrow keys are used to move the marker across tiles. Currently there are no constraints, any tile can be swapped with any other tile.&lt;/p&gt;
&lt;p&gt;If you were to implement constraints (only adjacent tiles can be swapped) you’d probably use the code below. If a tile is adjacent (top, down, left or right) it moves by a single step. So the sum of absolute differences between their X’s and Y’s would be 1. If we were to sum the difference of diagonal tiles we would get 2. &lt;strong&gt;Think about it and enumerate a few cases on a piece of paper.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- To check if two tiles are adjacent (top, down, left or right) or not&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tile1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; tile2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tile1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; tile2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;-- swap tiles&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now have to check if a tile is highlighted or not (user presses enter on a tile), we store this boolean flag in a variable. If a tile is highlighted we render a semi transparent rectangle over a tile. The rectangle is rounded for aesthetics.&lt;/p&gt;
&lt;p&gt;The first time the user presses enter, it highlights a tile with a semi transparent rectangle and he gets another red marker which he can move around to choose another tile. After he places the second marker on another tile and presses enter again, our game swaps the tiles.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 189 - 200 =&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We set an opaque red as the colour. We also set a lineWidth of 4. So when shapes are drawn they are thicker than usual.&lt;/li&gt;
&lt;li&gt;On &lt;strong&gt;line 197&lt;/strong&gt; we draw a rectangle like usual but we pass in &lt;code class=&quot;language-text&quot;&gt;line&lt;/code&gt; so that the rectangle is hollow i.e the rectangle just has a border. By using &lt;code class=&quot;language-text&quot;&gt;line&lt;/code&gt; it uses the lineWidth we set earlier. Additionally we also pass in &lt;code class=&quot;language-text&quot;&gt;4&lt;/code&gt; as the last paramter so that the rectangle is rounded.&lt;/li&gt;
&lt;li&gt;Always reset the colour after your change it. If you don’t you will have to be extra careful to ensure that it doesn’t render everything in the last set colour. You could also set the colour everytime just before you use it. That works well too.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 58 - 75 =&gt;&lt;/em&gt;&lt;/strong&gt; Takes care of input handling. It changes the appropriate tiles on user inputs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 85 - 101 =&gt;&lt;/em&gt;&lt;/strong&gt; This block is entered when the user has highlighted a tile and then presses enter with the marking box on another tile. It just swaps the tiles.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swap the tiles using temporary holders. We also need additional data like gridX and gridY. We’re using temporary holders for them as well. He also mentioned that we swap stuff in the board &lt;strong&gt;(lines 94 &amp;#x26; 95)&lt;/strong&gt; before swapping the coordinates and the positions &lt;strong&gt;(lines 98 - 101)&lt;/strong&gt; as it’d give birth to some weird bugs.&lt;/li&gt;
&lt;li&gt;We also set highlighted to false. The red rectangle (marker) now is set to tile2 (the tile selected by the second marker).&lt;/li&gt;
&lt;li&gt;It is worth knowing that we &lt;strong&gt;could have&lt;/strong&gt; used simple multiplications (by 32) and additions (the offset) as well to derive stuff from the table indices instead of swapping internal data like coordinates.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;swap2 “The Tween Swap”&lt;/h2&gt;
&lt;p&gt;This update enables tweening the tiles to their new positions instead of instantly swapping them.&lt;/p&gt;
&lt;p&gt;It’s a relatively easy to achieve effect. Just tween &lt;code class=&quot;language-text&quot;&gt;tile.x&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;tile2.x&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;tile.y&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;tile2.y&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;tile2.x&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;tile.x&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;tile2.y&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;tile.y&lt;/code&gt;. Tween the positions of the tiles to be swapped to the position of the other.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 99 - 102 =&gt;&lt;/em&gt;&lt;/strong&gt; Implements the logic described above spread across a duration of &lt;code class=&quot;language-text&quot;&gt;0.2&lt;/code&gt; seconds.&lt;/p&gt;
&lt;h2&gt;Calculating Matches&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Question:- Any ideas on calculating matches?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A student suggested that we could look at adjacent tiles and if they are of the same colour, find the direction and then go recursively deeper in that direction. Colton pointed out that it’s trickier to implement and it’s probably inefficient as well.&lt;/p&gt;
&lt;p&gt;Go over each row horizontally first. If consecutive tiles are of the same colour keep incrementing &lt;code class=&quot;language-text&quot;&gt;matchNum&lt;/code&gt; until the pattern is broken. If &lt;code class=&quot;language-text&quot;&gt;matchNum&lt;/code&gt; is 3 or more it’s a match. Also if you’re reached the end of the row stop and skip to the next row. You also have to reset &lt;code class=&quot;language-text&quot;&gt;matchNum&lt;/code&gt; as you’ll be starting across a fresh row.&lt;/p&gt;
&lt;p&gt;Do the same thing vertically across the columns of the table.&lt;/p&gt;
&lt;p&gt;If a match if found (3 or more) append them to the table containing the list of matches.&lt;/p&gt;
&lt;p&gt;There’s also a possible optimisition. If you’re at the 7th tile and the match count is 0 or 1, you don’t have to check the 8th tile as it wouldn’t form a match anyways.&lt;/p&gt;
&lt;p&gt;See slide #25 to slide #66 for a visual explanation. There’s hardly any text you can quickly view it as an animation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Student Question =&gt; If we delete the tiles as and when see matches and there was an intersection of matches (forming a T shape or a cross)?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Colton’ Reply =&gt;&lt;/strong&gt; If we cleared matches as and when we encountered them, we wouldn’t see the second match as one or more of the common tiles of the matches would be cleared and it would no longer be a match.&lt;/p&gt;
&lt;p&gt;The current algorithm we implement goes over the entire grid before deleting matches so it would not miss it. It would see the first match of the intersection while going horizontally and then the second one while iterating vertically over the grid.&lt;/p&gt;
&lt;p&gt;Colton also suggested that we could reward the user with more points in case of an intersection, clear the entire row and do those sorts of things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Board.lua Board:calculateMatches()&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Variables for current colour, matchNum (how many consecutive of the same colour seen), matches etc.&lt;/li&gt;
&lt;li&gt;A branch for shortcircuiting at 7th or greater tile.&lt;/li&gt;
&lt;li&gt;Loop to keep counting the same colour if found.&lt;/li&gt;
&lt;li&gt;If a match is found, insert it into the matches table. Insert into the table all the tiles that are part of the match. We insert all the tiles because it’s easier to find if a tile is in the match table or not. If we inserted match ranges (index positions), we would have to write logic to check if a given tile is a part of the range or not. This takes a little more memory but simplifies stuff quite a bit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;We iterate from 2 to 8, so if the last tile of the horizontal row is a part of a match, we will not reach the else block that takes care of calculating the matches since we would have exhausted the for loop. So there’s an if block on line 95 that handles this corner case and adds the match to the matches table.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Exact same logic for the vertical matches. Just x &amp;#x26; y are inverted.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;self.matches = matches&lt;/code&gt; so that we have a reference to all the matches. They’ll come in handy later on when we want to remove tiles.&lt;/li&gt;
&lt;li&gt;In the end this function either returns false (if there are no matches) or the matches table. This is a neat API design as we can directly use &lt;code class=&quot;language-text&quot;&gt;if Board:calculateMatches()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Removing Matches&lt;/h2&gt;
&lt;p&gt;You should have realised by now that all the matches are part of a 2D table (a table of matches and each match has a list of tiles). We first have to set all tiles in the matches table to nil. It has the effect of removing the tile from the grid.&lt;/p&gt;
&lt;p&gt;Once the matches are removed, we have to bring the impact of gravity. Higher level tiles that still exist should fill lower level spaces.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Jist of the algorithm =&gt;&lt;/em&gt;&lt;/strong&gt; Start from the bottom of each column and find an empty tile (i.e look vertically and start from the bottom). If an empty tile is found go upward and look for the nearest tile and swap the tile with the empty space. Then start with the position just above the space you encountered and not the location of the tile you swapped it with because we could still see spaces between them. We don’t have a fixed number of items to check (we just have to ensure that the tiles are at the bottom and if spaces exist, all of them should be above them). So we resort to using a while loop rather than a for loop. It now has a similar look and behaviour of the bubble sort algorithm. If no more tiles are found since the highest tile in the column, the column needs no more swapping.&lt;/p&gt;
&lt;p&gt;A student made a nice suggestion that we could just shift all tiled cells to the bottom without having to go through all this. It’s a neat idea. It’s similar to getting rid of spaces in strings and as a result everything moves to the left anyways.&lt;/p&gt;
&lt;p&gt;I think Colton took us through the approach described above so that we could get a clearer picture of what’s happening.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Board.lua Lines 182 - 209&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 183&lt;/em&gt;&lt;/strong&gt; A flag for space (empty tile) or not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Lines 191 - 207&lt;/em&gt;&lt;/strong&gt; If a space was encountered the flag is set to true. If a tile’s encountered it means that there’s one or more spaces followed by a tile. We then enter the if branch under &lt;strong&gt;&lt;em&gt;line 193&lt;/em&gt;&lt;/strong&gt;, tween the tile to fall and then reset &lt;code class=&quot;language-text&quot;&gt;space = false&lt;/code&gt;. So we’ve accounted for the lowest space and the tile vertically just after it.&lt;/li&gt;
&lt;li&gt;Notice that we use an outer for loop from 1, 8 (for the columns) since the number of columns in known in advance. The inner loop is a while loop (for going over each column vertically) as the number of tiles we have to fix is not known in advance. Each columns might need different number of swaps, some might not even need any.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See slide #67 to slide #93 for a visual explanation. There’s hardly any text, you can quickly view it as an animation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; to see bubble sort in action. Also check out string strips in Python to better understand the idea suggested by the student.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Replacing Tiles&lt;/h2&gt;
&lt;p&gt;Check from the top if there are empty spots. Remember that gridX and gridY are coordinate values, x and y are just indices in the grid table. Set the empty spot to a tile using x and y so that the internal data structure is correct. This is essential as the tile has to be stored in the correct place in memory.&lt;/p&gt;
&lt;p&gt;Once that’s done we can manipulate it’s gridX and gridY values to give the right effect, render it in the right place, create visual effects like spins etc. We currently tween it’s gridY value to make it look like it’s falling into place from the top.&lt;/p&gt;
&lt;p&gt;Also the inputs are disabled while replacing tiles to avoid bugs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua Lines 189 - 192 =&gt;&lt;/em&gt;&lt;/strong&gt; 50 points for each tile in a match.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua Lines 198 - 211 =&gt;&lt;/em&gt;&lt;/strong&gt; We first get the tiles with their respective positions and target positions using &lt;code class=&quot;language-text&quot;&gt;getFallingTiles()&lt;/code&gt; and tween them to their new positions over &lt;code class=&quot;language-text&quot;&gt;0.25&lt;/code&gt; seconds. After that’s done we also need to get new tiles and tween them to their respective positions (tween gridY to make it look like it’s falling). After that’s done we recalculate matches just in case the new tiles create new matches. &lt;code class=&quot;language-text&quot;&gt;calculateMatches()&lt;/code&gt; recursively keeps calling itself everytime it finds a match on the new tiles. Say with the new tiles spawned it found a match, it destroys them and generates a new set of tiles again upon which it has to check for matches again.&lt;/p&gt;
&lt;h2&gt;Palette&lt;/h2&gt;
&lt;p&gt;Taking some sort of image and using some arbitrary number of colours from it. You basically use a limited number of colours that are quite likely to go well with each other.&lt;/p&gt;
&lt;p&gt;He briefly mentions about a famous colour palette - &lt;a href=&quot;http://pixeljoint.com/forum/forum_posts.asp?TID=16247&quot;&gt;DawnBringer’s 32 Colour Palette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dithering =&gt;&lt;/em&gt;&lt;/strong&gt; Draw two coloured pixel by pixel interleaved (alternation colours colour1, colour2, colour1 and so on). The end result looks like a new colour.&lt;/p&gt;
&lt;p&gt;Check slide #109 for the resultant colour by dithering each of the 32 colours with each other. The first row and column are the individual colours. The intersections are the result of the row and column.&lt;/p&gt;
&lt;p&gt;You can create loads of cool stuff by using a limited colour set and dithering. Check out slide #110, all of those scenes were created by dithering a small palette of 16 colours.&lt;/p&gt;
&lt;p&gt;There’s a famous 32 colour palette by Dawn Bringer which can be put to good use. You can convert images to a particular palette as well. Colton then shows how an image of a cat (with 1000’s or millions) would look if converted to this colour palette. It looks very similar to a cat but had a very inconsistent and blotchy look (anything with blurs develop patches). He then showed an example where he converted a comic with many flat colours into this colour palette. It had a nice feel to it. The gist being that a particular colour palette will not work with all images.&lt;/p&gt;
&lt;p&gt;This game and the previous game (Breakout) use this very same 32 colour palette.&lt;/p&gt;
&lt;p&gt;By imposing the constraint of a limited colour palette you give the game a consistent look. Can also be used to give a nice retro feel. Old games were limited by hardware. They could only display a limited set of colours and hence resorted to colour palette and dithering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Palette Swap&lt;/strong&gt;&lt;br&gt;
Create a gray scale version of a sprite. Have distinct parts which you can identify. Use different colours for each of those distinct parts. The same sprite could just be used as a different game object. Mario actually did this. They had the same sprite but used a different colour palette to colour them.&lt;/p&gt;
&lt;p&gt;I’ll just quote Wikipedia here.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A palette swap is a practice used in video games, whereby a graphic that is already used for one element is given a different palette, so it can be reused as other elements. The different palette gives the new graphic another set of colors, which makes it recognizably distinct from the original. Palette swaps are commonly used to distinguish between first and second players, for creating visual hierarchies, and for making visually distinct areas for levels in games.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Assignment&lt;/h2&gt;
&lt;p&gt;He briefly explains about the assignment.&lt;/p&gt;
&lt;p&gt;If you want to implement mouse functionality, remember that you will have to use the Push library to convert the actual coordinates on the screen to a set of coordinates that are scaled to the &lt;code class=&quot;language-text&quot;&gt;VIRTUAL_WIDTH&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;VIRTUAL_HEIGHT&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;End&lt;/h2&gt;</content:encoded></item><item><title><![CDATA[GD50 Lecture 03 - Breakout]]></title><description><![CDATA[This is a part of a series of notes. You can find notes to other lectures here
Please feel free to bring to my attention mistakes, other…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources-03-breakout/</link><guid isPermaLink="false">c6469008-6a3f-44c6-a228-d85682319b45</guid><pubDate>Thu, 22 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a part of a series of notes. You can find notes to other lectures &lt;a href=&quot;/introduction-game-development-gd50-notes-resources/&quot;&gt;here&lt;/a&gt;
Please feel free to bring to my attention mistakes, other interesting resources and feedback via the comments section. I’m all ears and will do my best to incorporate them into the blog post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.programiz.com/python-programming/methods/built-in/slice&quot;&gt;Slices in Python.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Use Sprite Sheets? - &lt;a href=&quot;https://gamedev.stackexchange.com/questions/7069/2d-graphics-why-use-spritesheets&quot;&gt;Link 1&lt;/a&gt;, &lt;a href=&quot;https://www.reddit.com/r/gamedev/comments/1wls8o/spritesheet_vs_multiple_images/&quot;&gt;Link 2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.khanacademy.org/computing/computer-programming/programming-natural-simulations/programming-particle-systems/a/intro-to-particle-systems&quot;&gt;Intro and Exercises in Particle Systems&lt;/a&gt; - This is awesome.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tntbasic.com/learn/help/guides/asciicodesexplained.htm&quot;&gt;ASCII Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.thewindowsclub.com/local-localnow-roaming-folders-windows-10&quot;&gt;Folders Under AppData in Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://askubuntu.com/questions/14535/whats-the-local-folder-for-in-my-home-directory&quot;&gt;./local/share/ in Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gamedev.stackexchange.com/questions/87794/how-to-implement-2d-collision-detection-that-is-immune-to-low-framerate-and-fast&quot;&gt;Collision Detection for Fast Objects.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Breakout State Flow&lt;/h2&gt;
&lt;p&gt;Quick overview of possible movements between states. It’s quite clear from slide#7 that it is possible to go to the HighScoreState from the StartState and vice versa but it’s not possible to directly enter the PaddleSelectState from the HighScoreState. He also briefly explains what happens in every state. For instance if the ball goes below the paddle and the player loses a life, the game transitions from the PlayState to the ServeState. I don’t want to go into these details for the sake of brevity. Essentially you draw a detailed state diagram to get a better picture of the flow. It’ll also help you refactor your code better. To know more use cases of a state diagram see &lt;code class=&quot;language-text&quot;&gt;Section Pong-9&lt;/code&gt; of &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-01-pong/&quot;&gt;Lecture Pong&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;breakout0 “The Day-0 Update”&lt;/h2&gt;
&lt;p&gt;Organise your project into folders. See slide#9 and you’ll get a clear idea.&lt;br&gt;
Global tables are initialised for fonts, textures and music. Within the music table, you notice that the background music is separated from the other audio files by an extra line break (line 85 of Main.lua). He mentions that using a &lt;code class=&quot;language-text&quot;&gt;ResourceManager&lt;/code&gt; class is a better way ahead.&lt;/p&gt;
&lt;p&gt;A screen is setup like the usual lectures. Instead of having the constants in the same file (&lt;code class=&quot;language-text&quot;&gt;VIRTUAL_WIDTH&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;VIRTUAL_HEIGHT&lt;/code&gt;) all the constants are moved to &lt;code class=&quot;language-text&quot;&gt;src/constants.lua&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A state machine is setup and &lt;code class=&quot;language-text&quot;&gt;StartState&lt;/code&gt; is entered into. Like last lecture a global input table is setup (for keypresses). A function &lt;code class=&quot;language-text&quot;&gt;displayFPS()&lt;/code&gt; is written so that the frame rate is visible on the screen instead of having to see the terminal. It’s a common practice to display FPS on the screen during development. You can read more about it in my &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-01-pong/&quot;&gt;notes on Pong&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead of having to require multiple files repeatedly a &lt;code class=&quot;language-text&quot;&gt;src/Dependency.lua&lt;/code&gt; is used. It imports all dependencies internally and by importing it, you implicitly import other dependencies. All states are moved to &lt;code class=&quot;language-text&quot;&gt;src/states&lt;/code&gt; to make it modular. It might seem like a lot of folders at first but it simplifies and keeps things organised especially in larger games.&lt;/p&gt;
&lt;p&gt;On line 181, you will notice the background image being rendered. The virtual heights and widths are being divided by the height and width of the background image to get the scaling factor. Also notice that 1 is subtracted from the background image’s height and width. This creates a larger than necessary scaling factor. Ensures that the image is stretched and always fills the screen.&lt;/p&gt;
&lt;h2&gt;breakout1 “The Quad Update”&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;local highlighted&lt;/code&gt; in &lt;code class=&quot;language-text&quot;&gt;state/StartState.lua&lt;/code&gt; is used to keep track of the highlighted menu option (start or highscore). It is set to 1 to highlight Start by default.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 23 - 28 =&gt;&lt;/em&gt;&lt;/strong&gt; the highlight variable is toggled between 1 and 2 every time the user presses the up or the down key. In this case we only have two menu options and can simply toggle. In other cases we’d have to increment and decrement highlight by 1 on up and down press respectively.&lt;/p&gt;
&lt;p&gt;Escape key presses aren’t global anymore. Pressing the escape button in some states switches to the previous state (acts like the back button).&lt;/p&gt;
&lt;p&gt;The highlighted option is given a different colour. Remember that Love2D is kind of like a state machine and uses the last set colour for rendering text, so we explicitly set the colour every time we want to render something. Also see line 53, the last of the four 255 sets the alpha of the colour. Setting it to 255 makes it as opaque as possible. The value can be tweaked to give your text tints.&lt;/p&gt;
&lt;h2&gt;Sprite Sheets&lt;/h2&gt;
&lt;p&gt;Instead of having multiple image files for each of your asset, put them all in one giant image. We can then load the single file into memory and get parts of the drawable (image) and render them. Basically select a sub portion of the image and ask Love to render it at your desired location. See slide#11 and 12. Sprite atlas is a synonym for sprite sheet.&lt;/p&gt;
&lt;p&gt;Check slide#13 for the function definitions.&lt;/p&gt;
&lt;p&gt;There are tools to generate quads (parts of sprites which contain images). They prove to be useful when you have image files with many sprites especially when the dimensions of the sprites are uneven. They can help you generate dimensions to get the respective sprites.&lt;/p&gt;
&lt;p&gt;Every file from this point onwards will be required by &lt;code class=&quot;language-text&quot;&gt;src/Dependencies.lua&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Util.lua =&gt;&lt;/em&gt;&lt;/strong&gt; has a function to generate quads. Basically iterate over the atlas and divide them into tiles of equal width and height. The code is pretty straightforward. It stores the quads in a table and returns the table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;On line 42 =&gt;&lt;/em&gt;&lt;/strong&gt; Colton has defined a helper function that is similar to slicing in Python. Lua doesn’t provide such an option by default. On line 45 is the meat of the function, if starting point isn’t mentioned, it starts from the beginning, if the end isn’t mentioned it goes on till the end (represented by &lt;code class=&quot;language-text&quot;&gt;#tbl&lt;/code&gt;. # gives the size of the table). The third argument of a for loop in Lua increments the variable by that much (if you’ve used loop in other languages, you probably have used i++ or i = i + 2). It’s just that. So in short it’s a typical for loop in a language like C, JavaScript or C++.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 57 =&gt;&lt;/em&gt;&lt;/strong&gt; defines a &lt;code class=&quot;language-text&quot;&gt;generateQuadPaddles&lt;/code&gt; to get the paddles. Notice the image file and see how they are spread across. Each block is 16 px tall so we start y at 64 and x at 0 so that we get the first paddle on the 4th row. Adjustments are made to get the paddles on the left as well. There are 4 such rows, instead of having to repeat the logic, a loop is used, y is incremented by 32 to index new rows and x is set to 0 to get the first paddle. They are stored in a table as usual and returned.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 65 =&gt;&lt;/em&gt;&lt;/strong&gt; of Main.lua you can see the function (also pass in the main sprite sheet to the function) in use. A global table &lt;code class=&quot;language-text&quot;&gt;gFrames&lt;/code&gt; is defined. We store all the quads that pertain to paddles in this global table.&lt;/p&gt;
&lt;p&gt;The Paddle class has variables &lt;code class=&quot;language-text&quot;&gt;skin&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;size&lt;/code&gt; that keep track of the colour and size. If you notice, we load the paddle quads in the order in which they appear in the sprite sheet. There are 4 sprites of each colour and there are 4 colours. The second paddle of the 3rd colour can be accessed from the table by indexing #10 from the table (2 colours skipped and 1 skip from the 3rd colour so &lt;code class=&quot;language-text&quot;&gt;((2 x 4) + 2)&lt;/code&gt;). The other bits should make you feel right at home. Very similar to the previous lectures (getting input, updating x coordinate, containing movement within the boundaries and render (this time using quads instead of the entire texture)).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua line 20 =&gt;&lt;/em&gt;&lt;/strong&gt; A new paddle is initialised. It also has logic to play and pause the game.&lt;/p&gt;
&lt;p&gt;Also by generating quads there’s one less headache now. No need to name, sort and organise images. We can simply load then in one table and them random access them from the table using indices.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; to know about Python slices and the advantages of using sprite sheets.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;breakout2 “The Bounce Update”&lt;/h2&gt;
&lt;p&gt;In Util.lua a new function &lt;code class=&quot;language-text&quot;&gt;GenerateQuadBalls&lt;/code&gt; is defined. It generates the quads pertaining to the balls from the atlas. It’s very similar in fashion to how quads are generated for the paddles. Notice in the sprite sheet (slide#12) that each ball is around 8px in height.&lt;/p&gt;
&lt;p&gt;A global table is used for all quads. Colton says it’s more organised and neater.&lt;/p&gt;
&lt;p&gt;Ball objects are initialised with a skin. It also implements a generic AABB collision. It can take a target (any drawable) and check if the ball collides with it or not. An instance the Ball class can get easily get the required quad by &lt;code class=&quot;language-text&quot;&gt;gFrames[&apos;Balls&apos;][self.skin]&lt;/code&gt;. A random number is passed while initialising the ball so that it gets a random colour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ball.lua line 68 =&gt;&lt;/em&gt;&lt;/strong&gt; Walls start deflecting the ball now. If the ball hits the top, we let the X velocity be and just reverse Y velocity. If we hit the left or right edge, the Y velocity remains, just reverse X velocity. Recall in Pong we actually had to reset the position during a collision else we’d risk getting stuck in an infinite loop. The case where the ball hits the paddle at a weird angle is yet to be fixed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua =&gt;&lt;/em&gt;&lt;/strong&gt; Initialises a ball, checks for collisions with the paddle.&lt;/p&gt;
&lt;h2&gt;breakout3 “The Brick Update”&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;generateQuadBricks()&lt;/code&gt; of Util.lua is used in the &lt;code class=&quot;language-text&quot;&gt;gFrames&lt;/code&gt; table. It internally uses the &lt;code class=&quot;language-text&quot;&gt;GenerateQuads&lt;/code&gt; function to split the atlas into dimensions of given width and height. We pass in the width and height of the brick. You probably figured out that the function would return many more quads than required (that too wrong ones) as we use a crude approach to split the sprite sheet using the dimensions of the brick. The quads it returns are no doubt uneven and pertain to the entire sprite sheet but we don’t care. We’ll slice it to get the first 21 (the bricks) and the rest will be discarded. This is a one time thing that happens during the start of the game and it really doesn’t matter even if it’s a little inefficient.&lt;/p&gt;
&lt;p&gt;Bricks have a member variable called &lt;code class=&quot;language-text&quot;&gt;inPlay&lt;/code&gt;. It’s a flag that identifies if it’s alive or not. Using this flag is a simple workaround for having to deallocate the brick (if it’s hit, it probably needs to be removed from the table that holds all bricks during gameplay). This flag is used with an if condition before updating and rendering (we selectively render and update bricks that are still inPlay). For a small game this approach works. For large games we’d have to deallocate memory. On brick hits, we just have to set inPlay to false.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 49 =&gt;&lt;/em&gt;&lt;/strong&gt; We index the appropriate colour and tier (&lt;strong&gt;&lt;em&gt;bricks of varying health or strength levels, differentiated by colours&lt;/em&gt;&lt;/strong&gt;) like how we did for paddles to get the right quad from the quad table (offsetting by multiplication and addition).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua line 34 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;LevelMaker.createMap()&lt;/code&gt; a function to create a table of bricks to be used anywhere. Additionally we also iterate over all the bricks and check if the individual brick collides with the ball. We also render bricks selectively using the flag described above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;LevelMaker.lua line 26 - 47 =&gt;&lt;/em&gt;&lt;/strong&gt; All it does now is randomly choose the number of rows and columns and places the bricks along the correct coordinates to center align all the bricks. It’s pretty simply as all the bricks are of the same colour and it fills the entire grid with bricks. Lines 34 to 43 are the most interesting lines in this file as of now, it initialises Bricks after taking top and left padding into consideration. The lines are well commented and are easy to understand. Fancy patterns and colours will be covered in eventual updates.&lt;/p&gt;
&lt;h2&gt;breakout4 “The Collision Update”&lt;/h2&gt;
&lt;p&gt;Currently the ball just passes through a brick. It should deflect after hitting a brick. In addition we also need to know where the ball is coming from, so that we can get it to bounce in the right direction. (If the ball hits a brick from the left, we just deflect it towards the right etc). &lt;strong&gt;We need to find out which portion of the ball isn’t inside the brick and we’ll also be using dx to know the direction it was travelling in before hitting the brick.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When the ball comes in contact with the corner of a paddle, it should take a sharp turn or cut. However if it hits an area near the center, it shouldn’t deflect by much of an angle. See slide #17. A good measure for this intensity is the distance from the center of the paddle.&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua line 64 - 71 =&gt;&lt;/em&gt;&lt;/strong&gt; There are two if else branches which we’ll go over one by one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;self.paddle.dx &amp;lt; 0&lt;/code&gt; dx not being zero indicates that the paddle is in motion. It being less than 0 indicates that it is moving towards the left. &lt;code class=&quot;language-text&quot;&gt;self.ball.x &amp;lt; self.paddle.x + (self.paddle.width/2)&lt;/code&gt; is used to check if the ball’s x coordinate is less than the x coordinate of the center of the paddle. The second line sets a dx of 50 in the left along with 8 times the distance of the ball from the center. Distance from the center is given by &lt;code class=&quot;language-text&quot;&gt;(self.paddle.x + self.paddle.width /2 - self.ball.x)&lt;/code&gt;. The 8 times creates the amplification (sharper angle and faster speed) effect.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The next else if branch is very similar. He’s just made changes to directions (dx should be positive for instance) and used &lt;code class=&quot;language-text&quot;&gt;math.abs&lt;/code&gt; to convert the negative difference between the center and the ball to a positive dx.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;For deflecting the ball off the brick in the right direction we use a simple rule based system. It’s simple but works most of the times (only fails if it hits the brick at weird angles). For the sake of time and brevity Colton decided to use this approach. See slide #18 for a picture and some more details. He pointed to another tutorial that is quite complex but solves this problem accurately. Relevant links to those tutorials - &lt;a href=&quot;https://github.com/noooway/love2d_arkanoid_tutorial&quot;&gt;this&lt;/a&gt; and &lt;a href=&quot;https://github.com/noooway/love2d_arkanoid_tutorial/wiki/Resolving-Collisions&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua Line 80 =&gt;&lt;/em&gt;&lt;/strong&gt; checks if a Brick collides with a Ball. Lines 95 - 121 take care of deflecting the ball in the right direction. There are 4 branches in the if else ladder. Let’s go over them one by one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 95 =&gt;&lt;/em&gt;&lt;/strong&gt; checks if the ball’s x coordinate it less than the brick (meaning the ball is approaching the brick from the left). Notice &lt;code class=&quot;language-text&quot;&gt;self.ball.x + 2 &amp;lt; brick.x&lt;/code&gt;, 2 is added to the ball’s x coordinate to account for edge collisions (top left or bottom left corner of the brick). If the ball hits say the bottom left corner it gives more priority to the coming from right. The jist lies in &lt;code class=&quot;language-text&quot;&gt;self.ball.x &amp;lt; brick.x&lt;/code&gt;, the + 2 is a small fix.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;98 &amp;#x26; 99 =&gt;&lt;/em&gt;&lt;/strong&gt; If the above condition is true, just reverse the velocity of the ball and shift it outside to avoid pesky infinite loops (recall these infinite loops were covered in &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-01-pong/&quot;&gt;Lecture 01 - Pong&lt;/a&gt;. We subtract 8 because that’s the width of the ball and moves it away from the brick. We could even use &lt;code class=&quot;language-text&quot;&gt;self.ball.width&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 102 =&gt;&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;self.ball.x + 6&lt;/code&gt; (same offset of 2 but on the right, should have been &lt;code class=&quot;language-text&quot;&gt;self.ball.x + 8&lt;/code&gt; but we reduce 2 being the fix for edges and it becomes + 6). We shift by 32 as the brick is 32 units broad.&lt;/li&gt;
&lt;li&gt;Similar treatment for top and bottom collisions. Reverse dy instead of dx and move by 8 and 16 units (the brick is 16 units tall).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 124 =&gt;&lt;/em&gt;&lt;/strong&gt; Increase the speed of the ball with each hit.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;These collision detection rules will fail once dx or dy becomes too high (the ball moves a lot each frame, one frame it might be outside a brick and in the next frame it could have traversed multiple bricks and get past them. Recall that we test for detection every frame, since the ball isn’t in contact with a brick, we won’t be able to detect the collision). It just skips over them.&lt;/p&gt;
&lt;p&gt;Colton explains a better way to detect collisions at the cost of more resources. Jist of the better idea is as follows.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Detect collisions along the entire path travelled by the ball between the last frame and current frame. You have dx and dy so go backward to the last frame.&lt;/li&gt;
&lt;li&gt;From there on make small additions to the ball’s x and y values until you touch dx and dy (i.e reach the position in the latest frame after dx and dy are added). Keep checking for collisions after these small additions that is.&lt;/li&gt;
&lt;li&gt;This way you’ll ensure that you don’t skip through objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for the link on detecting collisions when an object is too fast.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;breakout5 “The Hearts Update”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;StartState.lua 35 - 40 =&gt;&lt;/em&gt;&lt;/strong&gt; Switch to the serve state if option 1 is selected from the start state. Pass in health, the paddle, the score and bricks.&lt;/p&gt;
&lt;p&gt;Only the assets are global in this game. Every state is passed variables that it needs. Recall our state machine can take in a table. Even web frameworks like React work in a similar fashion. It passes the required data to the state instead of maintaining globals. &lt;strong&gt;Keep in mind that if a certain state requires some data, the present state which transitions into that certain state will also need to have access to that data. So you might have to pass data via various states so that data can trickle down to that certain state.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The serve and play state probably need bricks, a paddle, hearts for indicating life etc but the high score state needs only the highscore. By passing in what’s required rather than using globals you keep stuff clean and encapsulated. You also get a bird eye view of what each state needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;ServeState.lua 39 =&gt;&lt;/em&gt;&lt;/strong&gt; On state transition we additionally pass in the health as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Main.lua&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Has quads for hearts. It was generated by splitting an image evenly (recall how we split the bricks).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;208 =&gt;&lt;/em&gt;&lt;/strong&gt; Function to render the hearts. It first renders the hearts the user has left and then renders the hearts he’s lost. To render the hollow hearts (missing health) the difference between total lives and lives held is taken, so if the user hasn’t lost any life the for loop fails in it’s very first iteration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;PlayState.lua&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;81 =&gt;&lt;/em&gt;&lt;/strong&gt; Every brick hit simply add 10 to the score. Will be improved in the future updates.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;132 =&gt;&lt;/em&gt;&lt;/strong&gt; Check if the ball goes below the screen, reduce health then switch to serve state. If lost all lives switch to the game over state. Pass in the variables that the respective states require.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;164 =&gt;&lt;/em&gt;&lt;/strong&gt; renderScore is used to display the score (very simple and the definition can be found on line 239 in Main.lua).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any variable defined without using the keyword local becomes a global and is accessible from anywhere in the program. So it’s a good practice to use &lt;code class=&quot;language-text&quot;&gt;local&lt;/code&gt; to avoid bugs that arise from unintentionally changing global variables.&lt;/p&gt;
&lt;h2&gt;breakout6 “The Pretty Colours Update”&lt;/h2&gt;
&lt;p&gt;Flags for overall map shape and individual row properties. These flags are used to create random levels that look handcrafted (The code doesn’t play with the overall map shape at all, you can safely ignore NONE and the 2 PYRAMID flags).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LevelMaker.lua&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 40 =&gt;&lt;/em&gt;&lt;/strong&gt; Ensure that the number of columns are odd as even columns can lead to asymmetry.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 45 =&gt;&lt;/em&gt;&lt;/strong&gt; Decide the tier based on the level currently in subject to a maximum tier of 3 (we just have 3 tiers).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Line 48 =&gt;&lt;/em&gt;&lt;/strong&gt; Colour cycles are set and restricted to 5 and decided based on level as well. Lines 45 and 48 have the effect of increasing a tier and resetting the highestColor to blue every 6 levels.&lt;/li&gt;
&lt;li&gt;The flags skip and alternate are used to create fancy patterns. If skipFlag is true (set randomly on line 65), every other slot of the row is empty. If alternate is true (set on line 68), the colours of the brick alternate and if solid is true, the entire row is of the same colour. Additionally the number or rows are also random.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just simple concepts like skipping and alternating colours are used for our procedurally generated game maps.&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Student Question:- What happens if the ball is between a brick in a particular frame?&lt;/strong&gt;&lt;br&gt;
Like mentioned earlier our code fails when delta is too high. So if it’s between a brick, it’ll trigger AABB collision. Recall that we try finding out the portion of the ball that’s outside the brick. No portion of the ball falls outside the brick hence the last default branch (bottom collision) is triggered. It behaves as if the ball has been hit from the below.&lt;/p&gt;
&lt;h2&gt;breakout7 “The Tier Update”&lt;/h2&gt;
&lt;p&gt;Now the Brick class makes use of colour and tier while updating and rendering a brick. Checkout the new updated Brick class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Brick.lua line 44 - 58 =&gt;&lt;/em&gt;&lt;/strong&gt; Get a brick of a higher tier (strength level) to a weaker state represented by a different colour. If it’s in the weakest state and gets hit again, set inPlay to false so that the brick doesn’t get rendered.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua line 81 =&gt;&lt;/em&gt;&lt;/strong&gt; Simple arithmetic based on colour to update the score once a brick is destroyed. So different colours and different tiers get different scores. The base tier is zero so you don’t get the additional 200 points bonus on hitting it. You can play around and try out different rules to reach an optimum scoring system.&lt;/p&gt;
&lt;h2&gt;breakout8 “The Particle Update”&lt;/h2&gt;
&lt;p&gt;Particle systems make a variety of effect achievable. These effects are normally difficult to achieve using sprite animations. Things like an organic fire, flowy or smooth effects are normally achieved using the particle system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How would you create a fire?&lt;/strong&gt; Lots of fire particles in an area (representing the center) and gradually reduce the number as you move further away. They probably float upwards and then disappear. In other words write some logic to spawn fewer and fewer particles from a given point, set some -ve dy so that they float upwards and then fade away. You could additionally use a timer to transition the colour from glowing red to yellow. As some particles move up they could turn brown or black (smoke) and disappear from the screen.&lt;/p&gt;
&lt;p&gt;We use Love’s integrated particle system. It takes in a texture as a foundation and the number of particles to emit. The number of particles the particle system can emit, their speed etc ultimately decide the possible effects you can create. Particle systems have loads of functions and you can check the ones provided by Love &lt;a href=&quot;https://love2d.org/wiki/ParticleSystem&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Every brick when hit, needs a particle system of it’s own of their own colour (red brick hits should give out red particles).&lt;/p&gt;
&lt;p&gt;Logic for the particle system used in our game:- Randomly generate particles close to our brick, fade away after a certain amount of time. They are of the same colour as the brick in the start and become transparent before they ultimately fade away.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Brick.lua line 20 - 51 =&gt;&lt;/em&gt;&lt;/strong&gt; Defines a colour palette in the form of RGB triplets for each brick.&lt;/p&gt;
&lt;p&gt;Colton mentions the importance of having a limited colour palette. It gives a cohesive look and even gives a retro like touch. Makes it easier to choose colours as it limits the choices you have. Can be a huge time saver.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;
  &lt;span class=&quot;token comment&quot;&gt;-- particle system belonging to the brick, emitted on hit&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;psystem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newParticleSystem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gTextures&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;particle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- various behavior-determining functions for the particle system&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- https://love2d.org/wiki/ParticleSystem&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- lasts between 0.5-1 seconds seconds&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;psystem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setParticleLifetime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- give it an acceleration of anywhere between X1,Y1 and X2,Y2 (0, 0) and (80, 80) here&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- gives generally downward&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;psystem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLinearAcceleration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- spread of particles; normal looks more natural than uniform, which is clumpy; numbers&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- are amount of standard deviation away in X and Y axis&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;psystem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAreaSpread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;normal&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code snippet given above are lines 66 - 81 of Brick.lua. The life time, area spread and texture of the particle system is set. It’s a part of the init function because each brick has it’s own particle system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lines 92 - 102 =&gt;&lt;/em&gt;&lt;/strong&gt; set the colours for the particle system. 2 colours are set. The transparency (alpha) varies between them. &lt;code class=&quot;language-text&quot;&gt;55 * (self.tier + 1)&lt;/code&gt; makes a higher tier more opaque hence brighter. All this code does is specify two colours (using the colour table defined in lines # 20 - 51) with different levels of transparency. The particle system creates particles of the first colour and transitions them to the second colour (transparent in our case) during the lifespan of the particle. 64 particles are emitted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Line 152 =&gt;&lt;/em&gt;&lt;/strong&gt; clearly shows that the particle system is initialised with the center of the brick as it’s base (recall that the dimensions of the Brick are 32 and 16).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for a detailed introduction and a few exercises on Particle Systems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;breakout 9 “The Progression Update”&lt;/h2&gt;
&lt;p&gt;This update starts showing levels to the user. All we have to do is store a number. The number is incremented when all the bricks are destroyed (hence all the bricks have inPlay set to false). A new state &lt;code class=&quot;language-text&quot;&gt;victory&lt;/code&gt; is created. The game transitions into the victory state when the condition above is fulfilled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;StartState.lua 40 =&gt;&lt;/em&gt;&lt;/strong&gt; When changing to a new state just pass in the level in the table. Any time we change state, we just pass in an additional level variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua 204 =&gt;&lt;/em&gt;&lt;/strong&gt; A function to check victory. If a brick is in play return false else return true.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PlayState.lua 88 =&gt;&lt;/em&gt;&lt;/strong&gt; If victory is true, play a sound and transition to victory state. All the victory state does is display a message. Pretty straight forward. Also gives an option to resume game by proceeding to the next level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;VictoryState.lua 35 =&gt;&lt;/em&gt;&lt;/strong&gt; Notice when we transition from the victory state to the new state again, the victory state increments the level and also makes use of the level maker to create a new set of bricks.&lt;/p&gt;
&lt;h2&gt;breakout10 “The High Score Update”&lt;/h2&gt;
&lt;p&gt;Check out the file system related functions in slide #27.&lt;/p&gt;
&lt;p&gt;Most operating systems have specified directories to store application data. Love only allows writing files to the directory assigned by the operating system for such purposes. You can create subdirectories and files within this directory.&lt;/p&gt;
&lt;p&gt;For instance on Windows the directory is &lt;code class=&quot;language-text&quot;&gt;C:\Users\user\AppData\Roaming\LOVE&lt;/code&gt;. The directories for other operating systems can be examined &lt;a href=&quot;https://love2d.org/wiki/love.filesystem&quot;&gt;here&lt;/a&gt;. This directory is already hard coded by Lua. So you will only need to use &lt;code class=&quot;language-text&quot;&gt;love.filesystem.setIdentity&lt;/code&gt; only when you want to write to a subdirectory within this directory (you mostly won’t need to).&lt;/p&gt;
&lt;p&gt;We’ll just have a table (table of tables holding name and score) and sort them by score. While writing to a file we’ll need to convert it to a string. Colton decided to take a simple approach while storing this info in the file. So 10 high scores would result in 20 lines in the file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;name
score
name
score
.
.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;main.lua line 213 =&gt;&lt;/em&gt;&lt;/strong&gt; Create a folder named &lt;code class=&quot;language-text&quot;&gt;breakout&lt;/code&gt; in the local storage directory. If a file named &lt;code class=&quot;language-text&quot;&gt;breakout.lst&lt;/code&gt; &lt;strong&gt;doesn’t&lt;/strong&gt; exist, create some dummy high scores and save it to that file (also called seeding). If the file already exists iterate over every line using abstractions provided by Love. If it’s a name just take the first three characters (we only accept 3 characters and this serves as a safety check against long names). If it’s a number read the line (you will get a string type) and convert it to an integer. If this sounds too simple, you could write some code for error checking as well. You could check if the file has been tampered with or if a score is a garbage value, handle it elegantly and prevent it from being rendered and so on to make it more robust.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; and read about these special folders and their purposes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;breakout11 “The Entry Update”&lt;/h2&gt;
&lt;p&gt;Allows the user to enter his name when he gets a high score. An arcade game like style is used (only 3 characters for storing a name, use up arrows to traverse from A to Z and left and right arrows to change position).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How should we move from A to B, back to A and so on in response to up and down key presses?&lt;/strong&gt;&lt;br&gt;
A student suggested that we could have a table with A-Z and index the next or previous element. This is bulky and Colton proceeded to describe a better way which I’ll summarise below.&lt;/p&gt;
&lt;p&gt;A new state &lt;code class=&quot;language-text&quot;&gt;EnterHighScoreState&lt;/code&gt; is created. Check out slide #28 to see how it looks. It’ll also make following along easier.&lt;/p&gt;
&lt;p&gt;A table &lt;code class=&quot;language-text&quot;&gt;local chars&lt;/code&gt; is used to store the ASCII values of the three characters. &lt;code class=&quot;language-text&quot;&gt;local highlightedChar&lt;/code&gt; is an integer that keeps track of the desired character (highlighted on the screen) amongst the three characters. We index the &lt;code class=&quot;language-text&quot;&gt;chars&lt;/code&gt; table using &lt;code class=&quot;language-text&quot;&gt;highlightedChar&lt;/code&gt; and change the value accordingly. If the left or right arrow key is pressed, it decrements and increments highlightedChar and if the up or down arrow keys are pressed it changes the value of &lt;code class=&quot;language-text&quot;&gt;chars[highlightedChar]&lt;/code&gt; by +1 or -1 effectively going to the next or previous alphabet.&lt;/p&gt;
&lt;p&gt;If we exceed 90 (z in ASCII) we must wrap around to 65 (a) and if we try going below 65, we should display z. These edge cases are taken care of using if conditions (on line 74 and 79 of EnterHighScoreState.lua).&lt;/p&gt;
&lt;p&gt;To reach this state the user should make it to the high score list. So it needs to have the current high score list and also the current score. We have to pass these along the possible states.&lt;/p&gt;
&lt;p&gt;We start by comparing the current high score from the bottom of the list and place it below the score higher than it and shift everything below it one spot down.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; to know a little about ASCII.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;breakout12 “The Paddle Select Update”&lt;/h2&gt;
&lt;p&gt;Just displays two arrows for directions and renders a paddle. Every time the right or the left key is pressed it increments or decrements a counter and indexes into the quad table to choose the appropriate paddle. Also the direction hint arrows change (between transparent and opaque) to indicate if the user has reached an extreme and cannot scroll further for more possible paddles in that direction. Check slide#29 to get a better picture of what I’m saying.&lt;/p&gt;
&lt;p&gt;Once a colour is chosen by the user, initialise the paddle with the respective colour (recall the choice is stored in the counter) and the paddle can be passed to the various states you might transition into.&lt;/p&gt;
&lt;h2&gt;breakout13 “The Music Update”&lt;/h2&gt;
&lt;p&gt;Sound effects for the game.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;He also mentioned to have a look at the code that recovers the life of a user by a heart once a certain threshold is reached. This rewards the user for his efforts.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;End&lt;/h2&gt;</content:encoded></item><item><title><![CDATA[GD50 Lecture 02 - Flappy Bird]]></title><description><![CDATA[This is a part of a series of notes. You can find notes to other lectures here
Please feel free to bring to my attention mistakes, other…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources-02-flappy-bird/</link><guid isPermaLink="false">1618fefa-5ba2-42d3-a293-565c8a665719</guid><pubDate>Mon, 05 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a part of a series of notes. You can find notes to other lectures &lt;a href=&quot;/introduction-game-development-gd50-notes-resources/&quot;&gt;here&lt;/a&gt;
Please feel free to bring to my attention mistakes, other interesting resources and feedback via the comments section. I’m all ears and will do my best to incorporate them into the blog post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.creativebloq.com/web-design/parallax-scrolling-1131762&quot;&gt;Examples of a Few Parallax Sites&lt;/a&gt; - Have a look if you want to get a feel of Parallax. Skip if you already know what Parallax is.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/17436947/how-to-iterate-through-table-in-lua&quot;&gt;Iterating a Table in Lua&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ears2.dmu.ac.uk/learning-object/basic_soundwaves/&quot;&gt;Basic Sound Wave Types&lt;/a&gt; - With animations and sound demos.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Optional Reading&lt;/h2&gt;
&lt;p&gt;These links were suggested by Colton during the lecture. They are purely optional.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://howtomakeanrpg.com/&quot;&gt;How to Make an RPG&lt;/a&gt;&lt;br&gt;
He uses Lua with his own custom engine (similar to Love) to make a Role Playing Game. Colton mentioned that he got his hands dirty with Lua using it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://gameprogrammingpatterns.com/&quot;&gt;Game Programming Patterns&lt;/a&gt;&lt;br&gt;
Great general guide to learn game development concepts for large scale game development. &lt;code class=&quot;language-text&quot;&gt;Personal Note&lt;/code&gt;:- I’ve read a few of his blog posts and I can vouch that (Bob/Robert) Nystrom is awesome.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that this lecture builds on a lot of foundation that was set in the previous lecture.&lt;/p&gt;
&lt;h2&gt;bird0 “The Day-0 Update”&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;love.graphics.newImage(path)&lt;/code&gt; - Loads an image from a file that we can later use to draw to screen.&lt;/p&gt;
&lt;p&gt;He sets &lt;code class=&quot;language-text&quot;&gt;512px&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;288px&lt;/code&gt; as the virtual dimensions. He chose them as it worked well with the assets and they also have a &lt;code class=&quot;language-text&quot;&gt;16:9&lt;/code&gt; resolution. You are free to choose whatever you want after a few trials.&lt;/p&gt;
&lt;p&gt;A filter was set (The filter decides what’s to be done when you upscale or downscale a texture). You can read more about them in my &lt;a href=&quot;/introduction-game-development-gd50-notes-resources-01-pong/#filters-extra-info&quot;&gt;previous&lt;/a&gt; blog post.&lt;/p&gt;
&lt;p&gt;Covers quite a few things that are very similar to the first lecture.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- images we load into memory from files to later draw onto the screen&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; background &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;background.png&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; ground &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ground.png&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The keyword &lt;code class=&quot;language-text&quot;&gt;local&lt;/code&gt; binds the scope of the variable to the current file. &lt;code class=&quot;language-text&quot;&gt;background&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ground&lt;/code&gt; cannot be accessed outside the file and it also avoid variable collisions. If another file happens to use the same name, we won’t run into the risk of changing the global variable with the same name.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;love.graphics.draw()&lt;/code&gt; can be used to draw anything that is of type drawable. Images come under the type drawable. So keep in mind that &lt;code class=&quot;language-text&quot;&gt;background&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ground&lt;/code&gt; can now be drawn to screen.&lt;/p&gt;
&lt;p&gt;He recommended using &lt;strong&gt;aseprite&lt;/strong&gt; to create sprites. Other popular options are Photoshop and Gimp.&lt;/p&gt;
&lt;h2&gt;bird1 “The Parallax Update”&lt;/h2&gt;
&lt;p&gt;Parallax can help giving an illusion of movement. Different frames of references move at different rates. For example you are travelling in a car. The mountains in the distant move rather slowly when compared to the rate at which the fences on the road move. You get a better feel of movement and distance as well due to this.&lt;/p&gt;
&lt;p&gt;Two variables &lt;code class=&quot;language-text&quot;&gt;backgroundScroll&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;groundScroll&lt;/code&gt; are declared to keep track of how much the respective images have moved. The background mountain image and the ground image slowly move across the screen and wrap around the screen when a certain point is reached. These variables will be used to compare against those certain points.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- speed at which we should scroll our images, scaled by dt&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; BACKGROUND_SCROLL_SPEED &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; GROUND_SCROLL_SPEED &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Two variables to store the rate at which the background and the ground move. &lt;strong&gt;It’s a convention to set variable names to all caps if they are not going to manipulated i.e they are some kind of constants.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now he shows the technique he uses to get the mountain and the ground to infinitely scroll across the screen. The actual image has two copies of the same mountain next to each other. So it creates the effect of wrapping around the screen. When a certain point is reached we just snap it back to the original position. Have a look at the picture below.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4df19510377318a95442fea082d34beb/4b190/looping-point-concept.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 119.59459459459461%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgME/9oADAMBAAIQAxAAAAG53JZ7azuZLixF/wD/xAAUEAEAAAAAAAAAAAAAAAAAAAAw/9oACAEBAAEFAh//xAAWEQEBAQAAAAAAAAAAAAAAAAABEDH/2gAIAQMBAT8BdjP/xAAZEQADAQEBAAAAAAAAAAAAAAAAAQIhETH/2gAIAQIBAT8BjJGQ+rR+n//EABQQAQAAAAAAAAAAAAAAAAAAADD/2gAIAQEABj8CH//EABoQAQEAAgMAAAAAAAAAAAAAAAEAEDFxgZH/2gAIAQEAAT8hb2NTBzhI7jV//9oADAMBAAIAAwAAABB7J8D/xAAYEQEBAQEBAAAAAAAAAAAAAAABABEhMf/aAAgBAwEBPxDuHCGOkeX/xAAaEQEAAgMBAAAAAAAAAAAAAAABABEhMaHw/9oACAECAQE/EK2PuxWrFcym6f/EABwQAQEAAgIDAAAAAAAAAAAAAAERADEQIUFxgf/aAAgBAQABPxCo7wr4zo39wwkX1lGQcDFrig9Li//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;looping-point-concept&quot;
        title=&quot;&quot;
        src=&quot;/static/4df19510377318a95442fea082d34beb/1c72d/looping-point-concept.jpg&quot;
        srcset=&quot;/static/4df19510377318a95442fea082d34beb/a80bd/looping-point-concept.jpg 148w,
/static/4df19510377318a95442fea082d34beb/1c91a/looping-point-concept.jpg 295w,
/static/4df19510377318a95442fea082d34beb/1c72d/looping-point-concept.jpg 590w,
/static/4df19510377318a95442fea082d34beb/4b190/looping-point-concept.jpg 800w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It makes logical sense to snap back the picture once the first mountain reaches the end of the screen (if we continue going forward and if the left corner of the screen touches the second mountain the image will no longer cover the entire screen).&lt;/p&gt;
&lt;p&gt;However we needn’t be so pedantic while setting the looping point of the ground’s image. If you notice it has a pattern that keeps repeating itself anyway. We shouldn’t notice any difference even if we set an arbitrary value.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;backgroundScroll &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;backgroundScroll &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;
                   BACKGROUND_SCROLL_SPEED &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; BACKGROUND_LOOPING_POINT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code above shows how it’s achieved. We curb the image’s movement beyond a certain point by using &lt;code class=&quot;language-text&quot;&gt;% BACKGROUND_LOOPING_POINT&lt;/code&gt; on the probable future position of the image.&lt;/p&gt;
&lt;p&gt;There are ways to save memory (using an image that has twice the width of the regular image doesn’t seem very efficient, does it?). You could use a regular image and render it twice to create the desired effect. Then once a certain point is reached snap them back to their original position. Since there’s only one image and both the drawables point to the image, memory requirements are lesser. This same technique can be applied even for rendering more copies of the same image (it’ll be easier to appreciate the savings in memory from texture sizes now. You can get the same effect without using an image that is 4 times as wide as the normal image).&lt;/p&gt;
&lt;div id=&quot;games-are-illusions&quot;&gt;
&lt;p&gt;He shows a &lt;a href=&quot;https://www.youtube.com/channel/UCHTnEwQKNwm49CQeCVZogMw&quot;&gt;YouTube video&lt;/a&gt; where they’ve hacked the camera of a few games. They can now see things outside the reach of a normal user. By seeing things beyond the normal boundaries they spot a lot of tricks used in game development to keep memory requirements low. For example:-&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A game only had the face of mountain rendered. It looked gigantic but on rotating the camera one could see that it’s actually hallow. By not having to render those points and vertices a huge deal of memory is saved.&lt;/li&gt;
&lt;li&gt;A monster is positioned in a shop in such a way that you can only see it’s face. On digging deeper they notice it doesn’t have legs but the user is oblivious to that fact.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In short games give the &lt;strong&gt;illusion&lt;/strong&gt; of doing lots of grand things by using neat tricks.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for a few parallax sites.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;bird2 “The Bird Update”&lt;/h2&gt;
&lt;p&gt;He creates a bird class. Recall from the previous lecture that it’s a convention to start the name of class with an upper case letter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; Bird&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- load bird image from disk and assign its width and height&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;image &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bird.png&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWidth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHeight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- position bird in the middle of the screen&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_WIDTH &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VIRTUAL_HEIGHT &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;self.image&lt;/code&gt; has a reference to an object of the class &lt;code class=&quot;language-text&quot;&gt;Image&lt;/code&gt;. So &lt;code class=&quot;language-text&quot;&gt;image:getWidth()&lt;/code&gt; is just a member function in the image class. The same applies to &lt;code class=&quot;language-text&quot;&gt;image:getHeight()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;x and y (&lt;code class=&quot;language-text&quot;&gt;self.x&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;self.y&lt;/code&gt; respectively) coordinates are set so that the bird is exactly in the center. If you don’t understand the calculation used to determine it, please refer how Colton center aligns text in the last lecture.&lt;/p&gt;
&lt;p&gt;The bird doesn’t move along the X axis at all during the game. It starts vertically and horizontally centered. It only moves along the Y axis during the game.&lt;/p&gt;
&lt;p&gt;The Bird class also has a render method. Recall that delegating stuff to their respective classes can help reduce clutter in the main files, help us think more abstractly about the game and helps a lot with scaling.&lt;/p&gt;
&lt;h2&gt;bird3 “The Gravity Update”&lt;/h2&gt;
&lt;p&gt;Gravity’s forces an object to fall faster and faster (recall that it has an acceleration of 9.8 m/s^2). So the bird should fall faster and faster.&lt;/p&gt;
&lt;p&gt;A Bird class is created and relevant functions refactored to it.&lt;/p&gt;
&lt;p&gt;In Bird.lua he sets &lt;code class=&quot;language-text&quot;&gt;GRAVITY to 20&lt;/code&gt;. It’s a value that he found to work well. You can experiment and set any value. &lt;code class=&quot;language-text&quot;&gt;self.dy&lt;/code&gt; is the change in the Bird Y coordinate due to gravity.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; Bird&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- apply gravity to velocity&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; GRAVITY &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dt

    &lt;span class=&quot;token comment&quot;&gt;-- apply current velocity to Y position&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice in the code snippet above how &lt;code class=&quot;language-text&quot;&gt;GRAVITY&lt;/code&gt; is added to &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; again and again. So &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; i.e the bird’s movement becomes larger and larger as time progresses thus imitating the actual behaviour of gravity.&lt;/p&gt;
&lt;h2&gt;bird4 “The Anti-Gravity Update”&lt;/h2&gt;
&lt;p&gt;Now we try to add the jumping action once the space key is pressed. Intuitively you know that it should move in the opposite direction of gravity. &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; should be negative (so that the bird moves up) and it should move up slower and slower as time progresses. By changing the sign of &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; from positive to negative we can make it move in the opposite direction. If &lt;code class=&quot;language-text&quot;&gt;-5&lt;/code&gt; gets the bird up by 5 pixels, &lt;code class=&quot;language-text&quot;&gt;-3&lt;/code&gt; will get the bird up by 3 pixels. We want to slowly reduce the rate at which it moves up and eventually it should start moving down again.&lt;/p&gt;
&lt;p&gt;This is done by adding small positive value to &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; over time. See lines 29 - 36 in Bird.lua and run through the changes on a piece of paper for better understanding.&lt;/p&gt;
&lt;p&gt;He also designs a way to refactor input handling to their respective classes so as to avoid clutter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- main.lua&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- line 70&lt;/span&gt;
    love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keysPressed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;--line 77&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keypressed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- add to our table of keys pressed this frame&lt;/span&gt;
    love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keysPressed&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;true&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;escape&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;quit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;-- line 98 - 110&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- other stuff here&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- reset input table&lt;/span&gt;
    love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keysPressed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Line 70 in main.lua creates a global table to keep track of all the keys pressed. In Lua everything (except the basic data types) are tables. So &lt;code class=&quot;language-text&quot;&gt;love.keyboard.keyPressed&lt;/code&gt; simply adds a new field to the table &lt;code class=&quot;language-text&quot;&gt;love.keyboard&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Line 77 shows that every time a key is pressed the relevant key is set to true in the global table. We reset the table every frame (line 98 - 110). We wouldn’t want keyPresses to stick.&lt;/p&gt;
&lt;p&gt;Now that we have a global table which has a record of all the keys pressed in that very frame, we can use it to query keypresses. Every class can look for keypresses it cares about and we can thus eliminate a large number of if conditions in main.lua. Example below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; Bird&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- apply gravity to velocity&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; GRAVITY &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; dt

    &lt;span class=&quot;token comment&quot;&gt;-- wasPressed in just a helper function which access the&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- global keyPressed table we just created and returns&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- true or false&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasPressed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;space&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;-- apply current velocity to Y position&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dy
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how the Bird class can simply check if space was pressed or not every frame and act accordingly. main.lua only updates the global table and individual classes can use &lt;code class=&quot;language-text&quot;&gt;love.keyboard.wasPressed&lt;/code&gt; (a function defined by us) to check if a key they care about was pressed in the last frame or not.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;http://game.engineering.nyu.edu/projects/exploring-game-space/&quot;&gt;nice in-depth write up&lt;/a&gt; on predicting the difficulty of Flappy Bird.&lt;/p&gt;
&lt;h2&gt;bird5 “The Infinite Pipe Update”&lt;/h2&gt;
&lt;p&gt;We need to keep destroying pipes as they leave the view. One could argue that we only use pointers (references) to the image object for every pipe we create and they wouldn’t amount to much. Colton explains that given enough time, we’ll run out of memory (and our game will definitely use more memory than required) and crash.&lt;/p&gt;
&lt;p&gt;If you notice the &lt;code class=&quot;language-text&quot;&gt;init&lt;/code&gt; function in &lt;code class=&quot;language-text&quot;&gt;Bird.lua&lt;/code&gt;, it’ll become obvious that for every bird we put on the screen, it loads an image rather than pointing to a preloaded image object. It wasn’t a necessary design decision because we’re absolutely certain that we won’t load more than one bird into memory. The decision to share the image amongst all the pipes becomes necessary because there are infinite pipes.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;local PIPE_SCROLL = -60&lt;/code&gt; is set so that we can use it to smoothly move the pipe from the left to the right (recall that -60 is multiplied by dt).&lt;/p&gt;
&lt;p&gt;Have a look at the &lt;code class=&quot;language-text&quot;&gt;Pipe:init()&lt;/code&gt;, you will notice that the X coordinate is just set outside the screen. The pipe exists but is outside the user’s view (recall that pipes don’t appear as soon you start the game).&lt;/p&gt;
&lt;p&gt;Colton has used a long pipe sprite. By giving it different Y coordinates you can make it look like they have different heights. Notice in the picture below that all pipes have the same length but appear to be different to the user.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a7bc0c5d3f238ecf11c95964b8e52ef2/a2510/pipe-different-heights.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.4054054054054%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDAf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGWjpMYX//EABUQAQEAAAAAAAAAAAAAAAAAABAB/9oACAEBAAEFAmP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAXEAADAQAAAAAAAAAAAAAAAAAAAREQ/9oACAEBAAE/IUQmmf/aAAwDAQACAAMAAAAQfC//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAZEAADAQEBAAAAAAAAAAAAAAAAASExEUH/2gAIAQEAAT8QRYtIVo0dQij5Tw0f/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;pipe-different-heights&quot;
        title=&quot;&quot;
        src=&quot;/static/a7bc0c5d3f238ecf11c95964b8e52ef2/1c72d/pipe-different-heights.jpg&quot;
        srcset=&quot;/static/a7bc0c5d3f238ecf11c95964b8e52ef2/a80bd/pipe-different-heights.jpg 148w,
/static/a7bc0c5d3f238ecf11c95964b8e52ef2/1c91a/pipe-different-heights.jpg 295w,
/static/a7bc0c5d3f238ecf11c95964b8e52ef2/1c72d/pipe-different-heights.jpg 590w,
/static/a7bc0c5d3f238ecf11c95964b8e52ef2/a8a14/pipe-different-heights.jpg 885w,
/static/a7bc0c5d3f238ecf11c95964b8e52ef2/a2510/pipe-different-heights.jpg 1000w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;random.seed()&lt;/code&gt; is set in main.lua (it’s typicall a global thing which effects the random function as a whole hence we set it in the main file). A function to get the width of the pipe is created (will be helpful when we want to destroy pipes or check for scoring).&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Pipe:update()&lt;/code&gt; method is a single line function which updates it’s X coordinate. &lt;code class=&quot;language-text&quot;&gt;PIPE_SCROLL&lt;/code&gt; is the speed at which the pipe should scroll - &lt;code class=&quot;language-text&quot;&gt;self.x = self.x + PIPE_SCROLL * dt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A table to keep track of the pipes currently in the screen is created in main.lua. We keep appending new pipe objects without specifying any key. It mimics the behaviour of a linked list.&lt;/p&gt;
&lt;p&gt;A variable &lt;code class=&quot;language-text&quot;&gt;spawnTimer&lt;/code&gt; is initialised to keep track of the time elapsed since a new pipe was created. If it exceeds 2 seconds we create a new pipe and append it to the table.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- line number 116&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- dt is the time passed since the last frame&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- if we keep doing this every frame&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- we can get the actual time elapsed&lt;/span&gt;
    spawnTimer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; spawnTimer &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; dt

    &lt;span class=&quot;token comment&quot;&gt;-- spawn a new Pipe if the timer is past 2 seconds&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; spawnTimer &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        table&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pipes&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Added new pipe!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        spawnTimer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have a table which keep storing all the pipes created. We iterate through all the pipes stored in the table and check if the right edge of the pipe (left corner coordinate + the width of the sprite) has crossed the left edge of the screen or not. If it has, we simple delete the pipe (see lines 129 - 136 in main.lua).&lt;/p&gt;
&lt;p&gt;Also remember to have the right render order. If the pipes are rendered before the background image, the background image is simply drawn over the pipes and pipes remain hidden from view.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; and check out the link on table iteration in Lua.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;bird6 “The Pipe Pair Update”&lt;/h2&gt;
&lt;p&gt;A new class for clubbing pipes together is created. It uses components (pipes) to build something more complex.&lt;/p&gt;
&lt;p&gt;The earlier table that keeps track of pipe pairs is renamed appropriately to &lt;code class=&quot;language-text&quot;&gt;pipePairs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The variable &lt;code class=&quot;language-text&quot;&gt;local lastY&lt;/code&gt; hold the Y coordinate of the last pipe. We use this value while generating the next pipe. We want pipes that have gaps that are reasonably close to each other so that the game is playable. For this we need some information about the last pipe.&lt;/p&gt;
&lt;p&gt;Line 132 of main.lua -&gt; &lt;code class=&quot;language-text&quot;&gt;math.max() and math.min()&lt;/code&gt; are used to sandwich the Y coordinate of the pipe such that they are at least 10 pixels below the top edge of the screen and are at least 90 pixels away from the bottom edge of the screen. &lt;code class=&quot;language-text&quot;&gt;math.random()&lt;/code&gt; is used to reduce or increase the Y coordinate by upto 20 pixels with respect to the Y coordinate of the last pipe.&lt;/p&gt;
&lt;p&gt;Tweak the &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt; value to vary the level of difficulty or to make the pipes look more natural.&lt;/p&gt;
&lt;p&gt;Now the &lt;code class=&quot;language-text&quot;&gt;Pipe&lt;/code&gt; class takes a string and a Y coordinate. This makes it easier to use the PipePair class. We can pass in &lt;code class=&quot;language-text&quot;&gt;lower&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;upper&lt;/code&gt; to invert the pipe.&lt;/p&gt;
&lt;p&gt;Check line 26 of PipePair.lua to see how the lower pipe is rendered using the Y coordinate of the upper pipe. PipePair also has a member variable called &lt;code class=&quot;language-text&quot;&gt;remove&lt;/code&gt; that acts as a flag. If marked as true it is deleted from our table that keeps track of pipePairs. Read lines 143 - 157 of main.lua to see how PipePairs are updated and deleted. Do not delete elements from a table while iterating through it. It’ll result in indices being skipped.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Changes to the &lt;code class=&quot;language-text&quot;&gt;Pipe&lt;/code&gt; Class&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;init&lt;/code&gt; takes in the orientation (lower or upper).&lt;/li&gt;
&lt;li&gt;Use of parameters to invert the image and set the Y coordinate of the pipe depending on the orientation of the pipe. See line 39 in Pipe.lua. We scale upper pipes by -1. Scaling by -1 gives a mirror image (hence upside down) but the size remains the same. Scaling by 2 doubles the size. Also notice how the Y coordinate is taken care of by using an if condition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Interesting Overflow Error&lt;/strong&gt;&lt;br&gt;
If we let the bird fall for a while below the screen, it’ll suddenly appear from the top edge of the screen. Recall how it falls faster and faster (&lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; becomes very large) and then all of a sudden &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; overflows and becomes very negative (negative &lt;code class=&quot;language-text&quot;&gt;dy&lt;/code&gt; results in an upward movement), one fine frame it renders above the screen and then gravity starts to act and it then falls from the top.&lt;/p&gt;
&lt;p&gt;Stuff like speed of generation of pipes, gap height, lastY value etc can be tweaked to give a different feel and vary the difficulty of the game.&lt;/p&gt;
&lt;h2&gt;bird7 “The Collision Update”&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;local scrolling = true&lt;/code&gt; in main.lua is used to toggle pause and scroll states. If the bird collides with any of the pipes, it’s set to false and also pauses further rendering.&lt;/p&gt;
&lt;p&gt;We iterate over the table of pipes to check if the bird collides with any of them or not (lines 152 - 157 in main.lua).&lt;/p&gt;
&lt;p&gt;We use Axis Aligned Bounding Boxes just like last time. You might be wondering that the bird isn’t a rectangle and won’t entirely fill in the rectangle formed by it’s X and Y coordinates. You are right about it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; Bird&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;collides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pipe&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- the 2&apos;s are left and top offsets&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- the 4&apos;s are right and bottom offsets&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- both offsets are used to shrink the bounding box to give the player&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- a little bit of leeway with the collision&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; pipe&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; pipe&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; PIPE_WIDTH &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; pipe&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; pipe&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; PIPE_HEIGHT &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We give an offset of 2 &amp;#x26; 4 (see the code snippet above) so that we don’t frustrate the users. If we go by the actual X and Y coordinate, the bird will be close to the pipe (but not touch it) and yet the user would lose the game as the bird doesn’t reach the corner of the box formed by the X and Y coordinates. This would really frustrate the user. In addition we give in a couple of extra pixels so that it actually looks like it’s colliding. Also by giving a few extra pixels of space we are being more liberal to the end user and might actually make it more enjoyable for him.&lt;/p&gt;
&lt;p&gt;Colton briefly describes an alternative style of refactoring. Instead of giving the bird a collides method, you can create a generic function which takes in two drawables and checks if they collide or not. It’s more scalable.&lt;/p&gt;
&lt;p&gt;It is interesting to note that at times you might not observe a pixel perfect collision. The bird might be too much into the pipe. The collision function isn’t faulty nor was it’s execution delayed, the bird probably has moved too much in a single frame and we check for collisions after it has made it’s move (remember that movement, checking for collisions etc happens once every frame).&lt;/p&gt;
&lt;h2&gt;bird8 “The State Machine Update”&lt;/h2&gt;
&lt;p&gt;He showed the possible different states. Check slide#30 for the same. Certain input keys and conditions trigger transition from one state to another.&lt;/p&gt;
&lt;p&gt;He imports a class called StateMachine, a base StateMachine class along with few game specific StateMachine classes. Also a few fonts are initialised.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;gStateMachine&lt;/code&gt; is declared in Main.lua. It is a table with some mapping to States (each state contains functions that are relevant to it). It is a convention to prefix global variables with a &lt;code class=&quot;language-text&quot;&gt;g&lt;/code&gt; so that it’s instantly recognisable that it’s changing some global state (even though it doesn’t tell which file the global actually resides in). Likewise &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt; denotes that it’s a member field of a class.&lt;/p&gt;
&lt;p&gt;Now the &lt;code class=&quot;language-text&quot;&gt;love.update(dt)&lt;/code&gt; function in main.lua only directly updates code that is common to all states (the mountains and the ground keep scrolling irrespective of which state the game is in). It doesn’t make sense to duplicate this across all states and therefore remains in main.lua. Everything else is delegated to the respective function that &lt;code class=&quot;language-text&quot;&gt;gStateMachine&lt;/code&gt; calls. Similar is the case of the &lt;code class=&quot;language-text&quot;&gt;love.draw()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;StateMachine&lt;/code&gt; class is taken from the book mentioned earlier as optional reading in the lecture. &lt;code class=&quot;language-text&quot;&gt;StateMachine&lt;/code&gt; is a generic class and also a wrapper that we use render, update (position, health, score etc), switch and exit states (mostly for clean up. Graphic objects need to be destroyed etc). &lt;strong&gt;This is the class that actually takes in states like TitleScreenState, PlayState etc during it’s initialisation. It can be thought of controlling or managing the states in the way of calling their respective exit, render and update logic whenever needed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;BaseState&lt;/code&gt; initiates empty methods which can be inherited. It saves us from writing some broilerplate code for each state. &lt;code class=&quot;language-text&quot;&gt;TitleScreenState&lt;/code&gt; for instance inherits &lt;code class=&quot;language-text&quot;&gt;BaseState&lt;/code&gt; so it has the exact function definitions of &lt;code class=&quot;language-text&quot;&gt;BaseState&lt;/code&gt; and then some changes and additions are made to it’s functions. I would like to repeat:- &lt;strong&gt;TitleScreenState has it’s own member functions for cleaning, rendering etc but it’s controlled by the StateMachine class. The StateMachine class just handles possible states.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s like having a group of kids with different abilities (the state classes) and a teacher who takes charge of them (the StateMachine class).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;bird9 “The Score Update”&lt;/h2&gt;
&lt;p&gt;A new score state is now included. Line number 96 of main.lua shows the relevant function call as well.&lt;/p&gt;
&lt;p&gt;A new member variable &lt;code class=&quot;language-text&quot;&gt;scored&lt;/code&gt; in introduced in PipePair.lua. If the bird goes past the right edge of the pipe it is set to true. The score is checked by iterating through all the pairs of pipes (lines 53 - 61 of &lt;code class=&quot;language-text&quot;&gt;state/PlayState.lua&lt;/code&gt;). We check if the X coordinate of the bird has crossed the X coordinate of the pipe’s right edge (add the width of the pipe to the X coordinate of the left edge).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt; &lt;span class=&quot;token comment&quot;&gt;-- simple collision between bird and all pipes in pairs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pair &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pipePairs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pipe &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pairs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pipes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bird&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;collides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pipe&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
            gStateMachine&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;change&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;score&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                score &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;score
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If it collides with a pipe, we use &lt;code class=&quot;language-text&quot;&gt;gStateMachine:change()&lt;/code&gt; to switch from the play state to the score state which displays the final score. If you recall &lt;code class=&quot;language-text&quot;&gt;gStateMachine:change()&lt;/code&gt; can take in optional parameters as well. We pass in the score. By writing the &lt;code class=&quot;language-text&quot;&gt;gStateMachine:change()&lt;/code&gt; function in this fashion, we can pass in local variables while switching to another state. This saves us from creating global variables just for sharing data between two states. If we had to share a variable across all states or many states it would &lt;strong&gt;at times&lt;/strong&gt; make sense to make the variable global. However only the &lt;code class=&quot;language-text&quot;&gt;PlayState&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ScoreState&lt;/code&gt; need the score variable (no other state uses it), so it is better to keep your code base functional and pass in stuff required by the state by the way of a function.&lt;/p&gt;
&lt;p&gt;Similarly we switch to the score state if the bird touches the ground (lines 92 - 96 from &lt;code class=&quot;language-text&quot;&gt;state/PlayState.lua&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&quot;bird10&quot;&gt;bird10 &quot;The Countdown Update&quot;&lt;/h2&gt;
&lt;p&gt;It’s just another state. A new class &lt;code class=&quot;language-text&quot;&gt;CountDownState&lt;/code&gt; is created and a new key is added to &lt;code class=&quot;language-text&quot;&gt;gStateMachine&lt;/code&gt; which maps to the relevant function (look closely - the inline function actually returns an object). He uses hugeFont (initialised earlier) to display 3..2..1.&lt;/p&gt;
&lt;p&gt;A few fields are added to the &lt;code class=&quot;language-text&quot;&gt;CountDownState&lt;/code&gt; class. &lt;code class=&quot;language-text&quot;&gt;count&lt;/code&gt; is used to keep track of the seconds pending until play and &lt;code class=&quot;language-text&quot;&gt;timer&lt;/code&gt; keeps track of the quantum of time elapsed since the last decrement in &lt;code class=&quot;language-text&quot;&gt;count&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;COUNTDOWN_TIME&lt;/code&gt; is the time between each tick, it’s set to 0.75 because 1 second between each tick is a little long.&lt;/p&gt;
&lt;p&gt;Recall how we kept track of time to spawn pipes (kept adding dt through every frame) until it reached 2 seconds. A similar approach is used. &lt;code class=&quot;language-text&quot;&gt;self.timer = self.timer % COUNTDOWN_TIME&lt;/code&gt; is executed once the sum of the accumulated dts crosses 0.75. &lt;code class=&quot;language-text&quot;&gt;% or modulo&lt;/code&gt; is used to preserve information if the timer happens to exceed 0.75 (we would lose this information if we just set &lt;code class=&quot;language-text&quot;&gt;self.timer&lt;/code&gt; to 0), it starts the next tick with the excess time from the last tick. This helps keep a smooth track of time (if excess time is taking during a tick, we deduct that much in the next tick).&lt;/p&gt;
&lt;p&gt;When &lt;code class=&quot;language-text&quot;&gt;self.count&lt;/code&gt; touches 0, we use &lt;code class=&quot;language-text&quot;&gt;gStateMachine&lt;/code&gt; to switch to the play state.&lt;/p&gt;
&lt;p&gt;The title screen now enters the countdown state instead of activating the play state directly.&lt;/p&gt;
&lt;h2&gt;bird11 “The Audio Update”&lt;/h2&gt;
&lt;p&gt;We now have a table of sounds. They all map to data types that hold audio. The sound effects were created using &lt;strong&gt;Bfxr&lt;/strong&gt;. He also used a free soundtrack from &lt;a href=&quot;https://freesound.org&quot;&gt;FreeSound&lt;/a&gt; &lt;strong&gt;(Please be sure to check the licensing terms before using them)&lt;/strong&gt;. He also sets one of the audio files to loop infinitely. Flappy Bird is an infinite game and the background music shouldn’t stop abruptly.&lt;/p&gt;
&lt;p&gt;Sound effects are added in the respective places. For instance sounds earned for a point scored is places just below the code responsible for updating the score. In line 80 of PlayState.lua he layers two sounds on top of each other for the desired effect (quite common in games and sound engineering). &lt;code class=&quot;language-text&quot;&gt;sounds[&apos;explosion&apos;]&lt;/code&gt; is white noise and &lt;code class=&quot;language-text&quot;&gt;sounds[&apos;hurt&apos;]&lt;/code&gt; is a downward or sine wave type of sound.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; if you’re curious about sound wave types.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;bird12 “The Mouse Update”&lt;/h2&gt;
&lt;p&gt;It’s left as an exercise to the viewer. Use the function &lt;code class=&quot;language-text&quot;&gt;love.mousepressed(x, y, button)&lt;/code&gt;. Remember how keypresses were made global to relieve main.lua. A similar approach can be used for mouse clicks as well. Each class can take care of the input keys that they care about.&lt;/p&gt;
&lt;p&gt;You can find the code for same in the GitHub repository though.&lt;/p&gt;
&lt;h2&gt;End&lt;/h2&gt;</content:encoded></item><item><title><![CDATA[GD50 Lecture 01 - Pong]]></title><description><![CDATA[This is a part of a series of notes. You can find notes to other lectures here
Please feel free to bring to my attention mistakes, other…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources-01-pong/</link><guid isPermaLink="false">27cb9134-28fe-4e72-b557-ea69610ebcb3</guid><pubDate>Sun, 28 Jan 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a part of a series of notes. You can find notes to other lectures &lt;a href=&quot;/introduction-game-development-gd50-notes-resources/&quot;&gt;here&lt;/a&gt;
Please feel free to bring to my attention mistakes, other interesting resources and feedback via the comments section. I’m all ears and will do my best to incorporate them into the blog post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://missingsentinelsoftware.com/notable-love-games&quot;&gt;Some Games Made Using Love&lt;/a&gt; - The list is quite interesting. If you feel Love and Lua aren’t worth your time, &lt;strong&gt;please&lt;/strong&gt; do have a look.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/buildapc/comments/1544hx/explaining_vsync_and_other_things/&quot;&gt;What is VSync?&lt;/a&gt; - Read the first three paragraphs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hqi0114mwtY&quot;&gt;2 Min Video on Anti Aliasing&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Texture_filtering#Nearest-neighbor_interpolation&quot;&gt;Nearest Neighbour Interpolation&lt;/a&gt; - The Wikipedia article is actually quite understandable. This is used to create the box like retro feel.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PL601FC994BDD963E4&quot;&gt;State Machines&lt;/a&gt; - Amazing series on the “Theory of Computation”. The First 2-3 videos should suffice to get an intuitive feel of State Machines.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lua.org/pil/3.6.html&quot;&gt;Table Syntax in Lua&lt;/a&gt; - Have a quick glance if you have the time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/5525817/inline-conditions-in-lua-a-b-yes-no&quot;&gt;Ternary Operator in Lua&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_rand.aspx&quot;&gt;Simple Algorithm to Generate Random Numbers&lt;/a&gt; - If you are interested in getting a feel of how random numbers are generated. This will no way help you with this particular course though.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Lua&lt;/h2&gt;
&lt;p&gt;The lecture starts off with Colton talking a bit about &lt;strong&gt;Lua&lt;/strong&gt;. It’s the Portuguese word for moon and was released in the year 1993 in Brazil. JavaScript / Python like language intended for use in larger applications. Especially popular in the game industry. It helped fasten development time by reducing compile time of large projects. Everything is a table in Lua. It’s very popular for storing data and code. I’ve personally seen many projects use Lua to write configuration files. In addition many in memory databases use Lua for stored procedures.&lt;/p&gt;
&lt;h2&gt;Love 2D&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Love 2D&lt;/strong&gt; is a game development framework written in C++ which uses Lua as it’s scripting language. Fast prototyping and support all platforms (even web and mobile).&lt;/p&gt;
&lt;h2&gt;Game Loops&lt;/h2&gt;
&lt;p&gt;It is essential to understand &lt;strong&gt;Game Loops&lt;/strong&gt;. Games are an infinite loop which keep collecting user input (key presses, mouse movement, joystick movement), process them and render changed stuff on the screen. All this keeps happening as long as the user keeps playing. &lt;a href=&quot;http://gameprogrammingpatterns.com/game-loop.html&quot;&gt;Link Mentioned in the Slides&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;2D Coordinate System&lt;/h2&gt;
&lt;p&gt;2D Games use a &lt;strong&gt;2D Coordinate System&lt;/strong&gt; that is very similar to the one you are very familiar with. The origin is at the top left corner of the screen though and Y keep increasing as you keep going down.&lt;/p&gt;
&lt;h2&gt;Pong-0 “The Day-0 Update”&lt;/h2&gt;
&lt;p&gt;You can follow along the progress of the game by opening &lt;code class=&quot;language-text&quot;&gt;pong-0&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;pong-1&lt;/code&gt; and so on in order. Small incremental changes are made in every update.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;-- This is used for initialising stuff like game state.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- [[ Called every frame. dt is given the value since&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- the elapse of the last frame.]]&lt;/span&gt;
love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- called each frame. Use it to draw things.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- Draw stuff on the screen. Can also align stuff&lt;/span&gt;
love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;align&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;-- Window related stuff. fullscreen, vsync, window resizable or not&lt;/span&gt;
love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;width&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; height&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- Love 2D looks for a main.lua file to execute the game&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;lua&quot;&gt;&lt;pre class=&quot;language-lua&quot;&gt;&lt;code class=&quot;language-lua&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    love&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;Hello Pong!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;-- text to render&lt;/span&gt;
        &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;                      &lt;span class=&quot;token comment&quot;&gt;-- starting X (0 since we&apos;re going to center it based on width)&lt;/span&gt;
        WINDOW_HEIGHT &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;-- starting Y (halfway down the screen)&lt;/span&gt;
        WINDOW_WIDTH&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;           &lt;span class=&quot;token comment&quot;&gt;-- number of pixels to center within (the entire screen here)&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;center&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;-- alignment mode, can be &apos;center&apos;, &apos;left&apos;, or &apos;right&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;6 is subtracted (line number 5 in the above snippet) to accommodate space (height) taken by the font i.e 12 units.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; for VSync.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Pong-1 “The Low Res Update”&lt;/h2&gt;
&lt;p&gt;View Slide #21 for some more functions.&lt;/p&gt;
&lt;p&gt;Steps are taken to give the font a retro like feel. I don’t understand how texture filtering algorithms work but in simple terms they decide how to scale textures. You have to choose the best filter for your needs. Textures like images lose quality and become blurry when zoomed in or may seem quirky when scaled down.&lt;/p&gt;
&lt;p&gt;He showed a few texture filters and an appropriate filter that can give the desired retro fill.&lt;/p&gt;
&lt;p&gt;They also start using a simple library called &lt;code class=&quot;language-text&quot;&gt;Push&lt;/code&gt; that takes care of scaling and resizing according to window dimensions. The official repository says &lt;em&gt;push is a simple resolution-handling library that allows you to focus on making your game with a fixed resolution&lt;/em&gt;. You basically design the game for one screen size (called virtual width and height in the lecture) and push automatically scales stuff so that they look consistent on various screens. You can checkout the GitHub &lt;a href=&quot;https://github.com/Ulydev/push&quot;&gt;repository&lt;/a&gt; for more details.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check the &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; section and read about anti aliasing and nearest neighbour interpolation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p id=&quot;filters-extra-info&quot;&gt;&lt;b&gt;Here&apos;s some extra information about filters from an authoritative source.&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;nearest-neighbour filtering is always used to preserve pixelation when downscaling and upscaling textures. Information is often lost while downscaling but it’s always used to give those boxes (retro like feel).&lt;/li&gt;
&lt;li&gt;bilinear filtering interpolates between pixels to create subpixels when upscaling particularly, resulting in blurriness.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pong-2 “The Rectangle Update”&lt;/h2&gt;
&lt;p&gt;See slide #25 for the documentation of the functions used.&lt;/p&gt;
&lt;p&gt;Fonts are immutable objects in Love 2D. So you have to load your font with respective sizes. You can’t use the same font with different sizes with one load. It probably loads the font with the specified size and stores it as some texture hence the need to load the font again even if you just want to change the size.&lt;/p&gt;
&lt;p&gt;Every time you print something to the screen using printf, it uses the last set colour and font. It’s very similar to the way OpenGL operates.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check the &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; section and read about State Machines.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Pong-3 “The Paddle Update”&lt;/h2&gt;
&lt;p&gt;We poll to check if certain keys are held down every frame. It is important to understand key presses are not the same as holding the key. If the movement keys are held on we move the paddle by changing it’s X and Y positions. Also we need to store the X and Y coordinates of the paddle in variables.&lt;/p&gt;
&lt;p&gt;PaddleSpeed is set to a value 200. To ensure that the speed of movement remains constant at all Frame Rates we don’t move it by a fixed value. Instead we want a smooth and even movement. So we multiple 200 by the dt (in fraction of a second) between each frame. Say our system is quite slow and the frame gets updated only 40 times every second so dt is 0.025 seconds. 0.025 * 200 gives 5. So the paddle ends up moving 5 units every frame.&lt;/p&gt;
&lt;p&gt;You have to instantiate the same font with the sizes you want to use it. Say you want to use ‘Arial’ in the heading and also for smaller text you will have to load it twice with the respective sizes. Love 2D probably converts a font into some kind of texture once they are loaded. So remember that fonts are immutable in Love 2D.&lt;/p&gt;
&lt;h2&gt;Pong-4 “The Ball Update”&lt;/h2&gt;
&lt;p&gt;Pseudorandom generators are used to initialise the position of the ball. They normally use the time as the seed. Time is represented using a large number and therefore is a nice seed.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Math.min()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Math.max()&lt;/code&gt; is used to confine the paddle within the boundaries of the box. The position is updated either to the current position + delta movement or to the value where it touches the box. You can check lines 84 - 91 for the implementation.&lt;/p&gt;
&lt;p&gt;Also the ball’s dx and dy can be changed randomly to deflect the ball at different angles.&lt;/p&gt;
&lt;p&gt;A variable called gamestate is introduced to uniquely identify each state. For instance a key might do different things when the game is paused as against when the user is actually playing. An open menu, the pause screen, the victory screen are all examples of different states that a game can transition to.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check the &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; section and read about Pseudorandom Generators.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Pong-5 “The Class Update”&lt;/h2&gt;
&lt;p&gt;Classes:- Kind of similar in spirit to structs in C. Relevant variables are grouped together with associated functions. They help write modular code especially when things have an internal state to maintain. Bundles of data and code that are together. All variables related to a particular object (Ball, Paddle) and functions (move, collision detection etc) are refactored to their respective Classes.&lt;/p&gt;
&lt;p&gt;The native way of using Classes in Lua is quite complex and isn’t similar to other programming languages that you might be familiar with. So they use a library called &lt;strong&gt;Class&lt;/strong&gt; to create an abstraction that can enable you to use classes in a similar spirit.&lt;/p&gt;
&lt;p&gt;Also it’s a convention in programming to capitalise the first letter of Class names and class related files for easy identification.&lt;/p&gt;
&lt;h2&gt;Pong-6 “The FPS Update”&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;..&lt;/code&gt; operator can be used to concatenate strings in Lua.&lt;/p&gt;
&lt;p&gt;He starts displaying the number of frames our computer can render every second. It takes a second or two to calculate the value before displaying the correct FPS.&lt;/p&gt;
&lt;h2&gt;Pong-7 “The Collision Update”&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Axis Aligned Bounding Boxes&lt;/strong&gt;. It works when objects aren’t rotated and it’s an extremely simple collision detection algorithm. The axis of the object should perfectly align with our main axis. No edge of the desired box should exceed or cross the edge of the other box.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The ball accelerates as the game progresses. It’s done by the way of multiplying dx by 1.03 every time we detect a paddle collision.&lt;/li&gt;
&lt;li&gt;When we detect a collision we abruptly shift the ball by 4-5 units in the other direction. Remember that we run 60 frames per second and in the future frames it might be possible that the paddle continues to collide, direction is changed again and this cycle might continue endlessly.&lt;/li&gt;
&lt;li&gt;Change in dy value for randomness in angles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pong-8 “The Score Update”&lt;/h2&gt;
&lt;p&gt;It was skipped. He accidentally updated Pong-9 with the relevant code.&lt;/p&gt;
&lt;h2&gt;Pong-9 “The Serve Update”&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Started keeping track of game score.&lt;/li&gt;
&lt;li&gt;Thinking of games as State Machines are quite useful.&lt;/li&gt;
&lt;li&gt;Can be used to thoroughly inspect, understand transitions and refactor the game at large. Also can be used to represent all actions and possible screens. Transitions between states happen when user gives an input (mouse click, keyboard presses etc).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pong-10 “The Victory Update”&lt;/h2&gt;
&lt;p&gt;Score checking and transition to a new state called “done”. They use this state for distinguishing it from other states and thus enable different behaviour using if statements. Larger applications use modular ways to handle states. In the case of this small application they could do away with strings.&lt;/p&gt;
&lt;h2&gt;Pong-11 “The Audio Update”&lt;/h2&gt;
&lt;p&gt;Static assets like audio files can be stored in memory and played or they can be streamed from a file every time you want to play. Normally smaller files are loaded into memory during initialisation as opening files and streaming them is a slower process. For larger audio tracks it’s better to stream them as they can be many megabytes in size and might increase RAM usage unnecessarily.&lt;/p&gt;
&lt;p&gt;You could even loop music so that it plays infinitely for cases like background music for the entire game or a particular level.&lt;/p&gt;
&lt;p&gt;He also recommends using an application called &lt;strong&gt;Bfxr&lt;/strong&gt; to create simple game audio.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Check the &lt;a href=&quot;#resources&quot;&gt;resources&lt;/a&gt; section and read about Lua Tables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Pong-12 “The Resize Update”&lt;/h2&gt;
&lt;p&gt;Push takes in a texture and scales it. It needs a reference height and width to preserve aspect ratio. It also letter boxes (add some margin or padding) in case one of the dimensions is too large. This way you can avoid distorted aspect ratios and make your game look decent in all device sizes.&lt;/p&gt;
&lt;h2&gt;End&lt;/h2&gt;</content:encoded></item><item><title><![CDATA[Introduction to Game Development GD50 - Notes and References]]></title><description><![CDATA[Notes, links and other resources that I find useful while taking this game development course. I always end up leaving courses midway and…]]></description><link>https://abhirath.me/introduction-game-development-gd50-notes-resources/</link><guid isPermaLink="false">d4ccad8d-287b-4aff-a1f2-51e703e393c7</guid><pubDate>Fri, 26 Jan 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Notes, links and other resources that I find useful while taking &lt;a href=&quot;https://cs50.github.io/games/&quot;&gt;this&lt;/a&gt; game development course. I always end up leaving courses midway and have decided to publish notes online for this particular course to build up some accountability.&lt;/p&gt;
&lt;p&gt;I’ll try to get the notes online latest by 2-3 days post the release of the lecture. Life and laziness can get in the way at times. &lt;strong&gt;Update:- I’m far far away from this goal. Sorry about that.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I’ll also link to other material that I’ve found useful in the past (example lecture 1 doesn’t explain the algorithm for generating random numbers since it’s clearly outside the scope of the course, I’ll be linking to material that I’ve used in the past to understand the same)&lt;/p&gt;
&lt;p&gt;At times I’ll probably skip the less interesting parts for the sake of brevity (for instance at times I might avoid bombarding you with documentation as it can be found in the course slides) and I’ll try highlighting the meaty bits.&lt;/p&gt;
&lt;h2&gt;How to Use this?&lt;/h2&gt;
&lt;p&gt;It can help use revise stuff. This is no way a substitute for the videos. Also you can use these notes to learn a little more about related concepts without having to Google for them yourself. I see myself using these notes after a couple of months as a quick way to refresh my memory without having to watch all the videos again.&lt;/p&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-01-pong/&quot;&gt;Lecture 01 - Pong&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-02-flappy-bird/&quot;&gt;Lecture 02 - Flappy Bird&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-03-breakout/&quot;&gt;Lecture 03 - Breakout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-04-match-3/&quot;&gt;Lecture 04 - Match 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-05-super-mario-bros/&quot;&gt;Lecture 05 - Super Mario Bros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lecture 06 - Coming Soon&lt;/li&gt;
&lt;li&gt;Lecture 07 - Coming Soon&lt;/li&gt;
&lt;li&gt;Lecture 08 - Coming Soon&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/introduction-game-development-gd50-notes-resources-09-3d-helicopter-game/&quot;&gt;Lecture 09 - Super Mario Bros&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please feel free to bring to my attention mistakes, other interesting resources and feedback using the comments section. I’m all ears and will do my best to incorporate them into these notes.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Novel DS & Algos Roundup #1]]></title><description><![CDATA[These are a few novel algorithms that I stumbled upon this year. I intend to curate and jot down stuff like this on a regular basis from now…]]></description><link>https://abhirath.me/novel-data-structures-algorithms-roundup-1/</link><guid isPermaLink="false">6673f5fc-2179-4bcf-8962-14017a32304a</guid><pubDate>Sat, 04 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;These are a few novel algorithms that I stumbled upon this year. I intend to curate and jot down stuff like this on a regular basis from now on so that I can quickly get to speed in the future (that is once I’ve forgotten about them). These also serve as notes. I don’t have to hunt down these links in the future.&lt;/p&gt;
&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#bloom-filters&quot;&gt;Bloom Filters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#music-shuffling&quot;&gt;Music Shuffling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#rsync&quot;&gt;Rsync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#hyperloglog&quot;&gt;Hyperloglog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pratt-parsing&quot;&gt;Pratt Parsing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;bloom-filters&quot;&gt;Bloom Filters&lt;/h2&gt;
&lt;p&gt;It’s a space efficient algorithm that checks if a particular item exists in a list or not. It trades memory requirements for accuracy. It has a very high accuracy but isn’t right all the time (you can tune it to use more memory and increase accuracy or reduce memory requirement and accuracy at the same time). Ingenious use of hashing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://prakhar.me/articles/bloom-filters-for-dummies/&quot;&gt;Bloom Filter for Dummies&lt;/a&gt;&lt;br&gt;
This is a well explained article keeping a sample usage in mind. Loved it.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://llimllib.github.io/bloomfilter-tutorial/&quot;&gt;Tutorial with a Demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;music-shuffling&quot;&gt;Music Shuffling&lt;/h2&gt;
&lt;p&gt;Random algorithms obviously aren’t deterministic. When using them it’s possible that at times you might end up the same number multiple times clustered together. For example 1, 2, 2, 8, 4, 5, 5, 5. This algorithm ensures that the songs are uniformly distributed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://keyj.emphy.de/balanced-shuffle/&quot;&gt;The Art of Music Shuffling&lt;/a&gt;&lt;br&gt;
The above link is visually explained and is very easy to grok.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;rsync&quot;&gt;Rsync&lt;/h2&gt;
&lt;p&gt;Rsync efficiently transfers only the differences between the two files. Say you have an outdated file A on your server and the latest file A on your personal computer. You have to replace the file on the server with the latest file. The naive way to send the file would be to send the entire file from your computer to the server. It uses more bandwidth and takes more time.&lt;/p&gt;
&lt;p&gt;The smarter way would be to just send the differences between both the files. Only the parts that have actually changed. Rsync uses hashing to find out the differences and can then enable you to send only the differences saving you time and bandwidth.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tutorials.jenkov.com/rsync/overview.html&quot;&gt;Overview of How Rsync Works&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;hyperloglog&quot;&gt;Hyperloglog&lt;/h2&gt;
&lt;p&gt;I stumbled upon this during my attempt to read the source code of Redis. It is used to return the number of distinct elements in a list or container. It uses lesser memory than the traditional approach (iterate over each thing, if not already encountered increase count by 1) but isn’t exact. It’s pretty accurate that even Redis uses it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://antirez.com/news/75&quot;&gt;Explanation by Antirez&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/12327004/how-does-the-hyperloglog-algorithm-work&quot;&gt;StackOverflow&lt;/a&gt;&lt;br&gt;
Points to a number of related resources and gives a decent explanation as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;pratt-parsing&quot;&gt;Pratt Parsing&lt;/h2&gt;
&lt;p&gt;Pratt parsing is a simple parsing technique. I haven’t worked with parsers so I don’t know the benefits it offers over other parsing techniques.&lt;/p&gt;
&lt;p&gt;These tutorials go really in depth.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/&quot;&gt;Pratt Parsers: Expression Parsing Made Easy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/&quot;&gt;Top Down Operator Precedence Parsing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://crockford.com/javascript/tdop/tdop.html&quot;&gt;Explanation and Code by Crockford&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Redis Source Code - DS and Algos - adlist]]></title><description><![CDATA[If you are not aware of the main article, please read it first - Index of Deep Dive into the Source Code of Redis. Please keep the source…]]></description><link>https://abhirath.me/redis-data-structures-algorithms-adlist/</link><guid isPermaLink="false">5ba05b48-7576-4b4b-b78d-985edef5992e</guid><pubDate>Sat, 04 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you are not aware of the main article, please read it first - &lt;a href=&quot;/deep-dive-into-the-source-code-of-redis/&quot;&gt;Index of Deep Dive into the Source Code of Redis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Please keep the source code of Redis handy. Also have search commands for your respective text editors handy. You might have to perform quite a few searches :)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Meta Info&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Difficulty&lt;/strong&gt; - Very Easy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Should be Familiar with&lt;/strong&gt; -
&lt;ul&gt;
&lt;li&gt;Doubly Linked Lists&lt;/li&gt;
&lt;li&gt;Pointers in C (specially void*)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;adlist.c &amp;#x26; .h&lt;/h2&gt;
&lt;p&gt;This file is quite easy to understand. Perhaps you could try it out yourself even if you consider yourself a noob.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It’s a doubly linked list which allows you to store anything. It uses void* in the value field to point to anything. Structures used - &lt;strong&gt;listNode&lt;/strong&gt;, &lt;strong&gt;listIter&lt;/strong&gt; and &lt;strong&gt;list&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;node&lt;/strong&gt; struct is a single unit of a list. It has a pointer to next, prev and a void* pointer so that it can store anything.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;listIter&lt;/strong&gt; struct is used to create a neat iterator (cleaner that what you normally would do in C but not as clean as the ones in languages like Python or JavaScript). It’s handy to access the next element, duplicate the list etc. Directions are defined as 0 &amp;#x26; 1. 0 goes forward from the head to the tail and vice versa. I’ll explain a bit more about it below.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;list&lt;/strong&gt; struct has three function pointers (&lt;strong&gt;free&lt;/strong&gt;, &lt;strong&gt;dup&lt;/strong&gt; and &lt;strong&gt;match&lt;/strong&gt;). I’ll explain their uses shortly.&lt;/li&gt;
&lt;li&gt;Macros are used to access the elements inside structs. For instance it’s easier to get the length using a function rather than using a pointer.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/*
 * Remember macros are substituted
 * before compilation. So writing a function is actually
 * less efficient (forget over optimisation for a while) than a macro
 * And why not make use of the elegant features that C has to offer?
 */&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name function&quot;&gt;listLength&lt;/span&gt;&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;len&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Cleaner as people prefer using&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// functions or member variables rather than pointers&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;listLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// cleaner than (l)-&gt;len&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;free&lt;/strong&gt;, &lt;strong&gt;match&lt;/strong&gt; &amp;#x26; &lt;strong&gt;dup&lt;/strong&gt;&lt;br&gt;
If you head over to the code you will notice that the &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt; structure’s value parameter is a &lt;code class=&quot;language-text&quot;&gt;void *pointer&lt;/code&gt;. It means it can point to any value under the sun. You could point it to a struct that represents a client who just sent a request. Say you’re done and want to free the entire doubly linked list. If it were a simple int, just freeing every node in the doubly linked list would do. Remember the &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt; itself is a dynamically allocated object and you have to free it. The value parameter might also point to another dynamically allocated object. The client struct might have arrays for IP, the actual request and so on which need to be freed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Say now you decide that your doubly linked list should hold dog kennels. It probably has an additional pointer to a dog struct which also should be freed. The freeing mechanism therefore differs for each struct. To generalise the library so that it
accommodate any use case you can pass in your custom function to free. It’ll be called for every node when you free the list.&lt;/p&gt;
&lt;p&gt;The same logic goes for match and duplicate. ints and chars can be directly compared but what about pointers? What if you want to compare two identical book names but different pointers point to them. A simple == check will return false as the pointers are not equivalent. You would have to follow the pointer and compare the entire string. So you can pass in a custom function that will be called when you have to compare values in the doubly linked list.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I’ll just skip over the very obvious functions. The explanation given above should be sufficient to understand them.&lt;/p&gt;
&lt;p&gt;Some things worth noting. Might be useful in case you decide to write a doubly linked list or design an API ;)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//After is an additional parameter that specifies if the node is to be&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// after or before the position of *old_node&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;listInsertNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;list&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; list&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; listNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;old_node&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; after&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nothing fancy but it’s a simple example of using the same function to do many things by modifying the flags you pass in.&lt;/p&gt;
&lt;hr&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Returns a pointer to the head or tail&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// You don&apos;t have to use list-&gt;next or list-&gt;prev to access elements&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// one by one. You can pass in an itertor and keep calling next to&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// access all the elements of the list. Imagine the ease.&lt;/span&gt;
listIter &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listGetIterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;list &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; direction&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
listIter &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listIter &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;iter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Say I want to empty a list.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Without the abstraction above I&apos;d have to&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// for forward iteration&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;temp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; list&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; temp &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; temp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; temp&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// some operation to perform&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// for backward iteration&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;listNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;temp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; list&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;tail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; temp &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; temp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; temp&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;prev&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// some operation to perform&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Example duplicating or emptying a list&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// With the abstraction above&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 0 is used to set the direction&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// either head to tail or tail to head&lt;/span&gt;
listIter &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;studentsIter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;listGetIterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studentList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;listNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;studenIter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// some operation&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you are not able to appreciate the improvement, let me jump in.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Read the two for loops in the code snippet above. Look the number of times I have to
deal with the pointer. I also have to increment it. Say I perform such operations 20 times,
I’d be writing this for loop 20 times. I could accidentally interchange head and tail
while copying and pasting stuff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The for loop is my style of iterating over a doubly linked list. You might
prefer a do-while loop for the same. Such small differences can crop up
and clutter the mind of the person reading the program. So anyone who wants to
iterate over the list should use the function rather than their own style.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It thus is common practice to create functions for things even if they are
trivial or don’t reduce the number of lines.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Another thing to notice. By giving it a name it becomes clearer as to what’s
being done. To best elaborate imagine a complex single line statement (eg regex matching after string concatenation and slicing). Wouldn’t it be better to just make a function rather than have the programmer try understanding the various parts of that single line.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Provides an option to get element at a certain position like how&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// you&apos;d do in a normal array. Also supports negative indices found&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// in languages like Python. Nothing fancy in this function but I like&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// the way he handles negative indices.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// -1 returns the last element, -2 the second last and so on&lt;/span&gt;
listNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;list &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;long&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    listNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; list&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;tail&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;prev&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; list&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Deep Dive into the Source Code of Redis]]></title><description><![CDATA[This is a work in progress. I’ll keep updating this article on a regular basis. This is my attempt to thoroughly understand and document the…]]></description><link>https://abhirath.me/deep-dive-into-the-source-code-of-redis/</link><guid isPermaLink="false">af179259-9d0d-4ae9-ba13-4b14955e0364</guid><pubDate>Fri, 03 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a work in progress. I’ll keep updating this article on a regular basis.&lt;/p&gt;
&lt;p&gt;This is my attempt to thoroughly understand and document the code base of Redis. I’ve used actual file names which Redis uses and have split them into categories which I think they best fit.&lt;/p&gt;
&lt;h2&gt;DS and Algos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/redis-data-structures-algorithms-adlist/&quot;&gt;adlist&lt;/a&gt;&lt;br&gt;
A generic doubly linked list&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/redis-data-structures-algorithms-ziplist/&quot;&gt;ziplist&lt;/a&gt;&lt;br&gt;
A memory efficient doubly linked list for integers and strings&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/redis-data-structures-algorithms-zipmap/&quot;&gt;zipmap&lt;/a&gt;&lt;br&gt;
A memory efficient but slow data structure that maps a string to another string&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Some Major Functionality&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/redis-helper-libraries-event-loop/&quot;&gt;ae&lt;/a&gt;&lt;br&gt;
An event driven library to concurrently perform operations like network requests etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Helper Libraries&lt;/h2&gt;
&lt;p&gt;Processes Links&lt;/p&gt;
&lt;h2&gt;Good to Know&lt;/h2&gt;
&lt;p&gt;header guards&lt;/p&gt;
&lt;h2&gt;Flow Once You Start Redis&lt;/h2&gt;</content:encoded></item><item><title><![CDATA[Google File System Summarised (Part 3)]]></title><description><![CDATA[Link to Part 1:- Google File System Summarised Part 1 Link to Part 2:- Google File System Summarised Part 2 System Interactions Mutations…]]></description><link>https://abhirath.me/google-file-system-paper-explained-summary-part-3/</link><guid isPermaLink="false">ea6d558d-cf16-4636-8dcd-5e9b1617856d</guid><pubDate>Tue, 31 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Link to Part 1:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-1/&quot;&gt;Google File System Summarised Part 1&lt;/a&gt;&lt;br&gt;
Link to Part 2:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-2/&quot;&gt;Google File System Summarised Part 2&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;System Interactions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mutations obviously have to be performed on the all the replicas. Say a client wants to mutate a file. Amongst the many replicas avai lable, the master grants a lease (think of it as permission to be modified). They call this particular replica the &lt;strong&gt;Primary&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The lease (permission) times out in 60 seconds. It however keeps getting extended as long as a client is mutating it.&lt;/li&gt;
&lt;li&gt;The primary decides the order of mutations that are to be applied. All the other replicas follow it.&lt;/li&gt;
&lt;li&gt;Control and data flow are decoupled. All the replicas follow the primary for the order of mutation. Data is stored in each chunkserver’s buffer and used when the time comes. Process of data transfer is explained below.&lt;/li&gt;
&lt;li&gt;The client gets the location of the primary and all the replicas. It caches this information to reduce the involvement of the master. - Data is passed to all the replicas. A scheme that exploits network topology is used rather than what you’d normally expect (i.e passing to the primary and then to the replicas). Also each server uses it’s full network bandwidth to pass data to the closest replica rather than split it’s capacity by passing to multiple servers simultaneously. Say the client wants to push to 4 chunkservers (S1 to S4). The closest server to the client is S1. The client uses all it’s bandwidth to pass data to S1. Closest to S1 is S2. S1 uses all it’s capacity rather than splitting transfer rate between S2 and S3. They also minimise delays by pipelining the transfer over TCP. Also a chunkserver forwards as it keeps receiving (it does not wait for the entire data) to further minimise delays. They have a setup which enables them to measure distances between chunkservers using IP Addresses.&lt;br&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 335px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a85a2442075d2fb6916b6fe44baf21d8/c0051/google-file-system-data-control-flow.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.51351351351352%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB9ElEQVR42oVT6ZKiYAyc938V38EqcS3/MCOCHHILciggl8DHudvKlOvg7Gyq+AghTTqd8Pb7yYZhaLuuu11927ZdD6dDvL/bLdr3z/lv462qqizLL1FomGYYBudzgEsSBVUz4vhimobjuOfzOU1TFJiCEU2SBAhVVSVJYFnucLBgiPu+J+/3HMfpuh5F0ffgOI5BFb6syMtfSzjgOfQDIRUh9Y08Hp6Q08rIBv/3j4/5fE7gleWzHBPkFzDgEORoW4LAs1sWzSuKAp5gNNHpH+Cud472ZrPhdvzpdJJlGWAwGtv5CTzShs/zu9VqBZKEkCzLHvH/VC7LEqk0TVMUBX+czaPya9ufYGSAoappqiLzvKBpetM02+3WMAzXdYprMar2fWWkQt0kTW3rwGwZ9JxnmSiKvu/jo23ToGZ8iVzHRdoUPNqoqiAI6/UaDtjmeQ61x56TJPZ8H0KggTFzCsY7lmWpJYUFD8IQyEfP8QV7aiKC07btF/Aw6JrKMAxNv4uSpKhqcjeAQXuxWMxmM99zzYPVNO1r5cHzHEmSdN10XAdWFBDrOmHX3CX4Aia3hayu1wInJoQJo4W6JjVOUmNV8SEctyRC/oJHD4R3O945OkEQSHsU1zz/hJ8E07MsGyPUDUPXDU3TFFmp62ZK+3X1f7Y/NgcB0Co+XTIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Google File System Data and Control Flow&quot;
        title=&quot;&quot;
        src=&quot;/static/a85a2442075d2fb6916b6fe44baf21d8/c0051/google-file-system-data-control-flow.png&quot;
        srcset=&quot;/static/a85a2442075d2fb6916b6fe44baf21d8/12f09/google-file-system-data-control-flow.png 148w,
/static/a85a2442075d2fb6916b6fe44baf21d8/e4a3f/google-file-system-data-control-flow.png 295w,
/static/a85a2442075d2fb6916b6fe44baf21d8/c0051/google-file-system-data-control-flow.png 335w&quot;
        sizes=&quot;(max-width: 335px) 100vw, 335px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;When all the replicas have received the data, the client then sends a write request to the primary. It gives a serial ID to every mutation (possibly from multiple clients). Also remember that it already has the data in it’s internal buffer. The primary forwards the requests to all the replicas (the primary has executed all the mutation requests by now). They mimic the order followed by the primary.&lt;/li&gt;
&lt;li&gt;The primary replies to the client. Errors encountered at the replicas are reported to the client. The mutation will not fail at the primary as it only forwards requests after it’s done executing them. The client retries a few times. The details like does it retry only the failed chunks or all the chunks again etc aren’t delved into in the paper.&lt;/li&gt;
&lt;li&gt;Atomic Append Records (appending at least once at the end of a file if you recall from the last part) follows a very similar process. However unlike a new file it cannot be written at an offset which the client chooses. The primary replica chooses the offset at which the file should be appended (if many clients write to the same file the offsets are more prone to clash and create undefined regions). There’s an additional check that happens. If appending the new data causes the chunk to exceed 64 MB, it pads the current chunk to take 64 MB and retries the append in the next chunk. Append sizes cannot exceed 1/4th the size of the file to keep such fragmentation in control. GFS only guarantees that data will be written at least once but each replica of a chunk might not be identicaly byte by byte (I’m a little fuzzy about this but I think differences are caused by different amounts of padding used or data being appended more than once on particular chunkservers).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Snapshots&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Copies a file or directory almost instantaneously.&lt;/li&gt;
&lt;li&gt;Standard copy-on-write techniques used. Read more about it on &lt;a href=&quot;https://en.wikipedia.org/wiki/Copy-on-write&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Used while creating copies or as a precautionary measure while creating checkpoints.&lt;/li&gt;
&lt;li&gt;All outstanding leases are revoked. It prevents mutations to the file(s) during the process.&lt;/li&gt;
&lt;li&gt;The newly created snapshot points to the same chunks as the source file (remember copy-on-write? To save resources a reference to the particular chunk is used rather than creating a duplicate copy). Actual copies or deep copies are only made when clients make a request to modify the chunks.&lt;/li&gt;
&lt;li&gt;On the first write operation to that chunk post the snapshot, the master notices that it has a reference count greater than one. Reference count is used to keep track of the number of shadow copies or references(as explained in the previous point) that exist of the particular chunk. Since it’s a mutation, the references should now be turned into copies as the original probably should not be touched (they are part of a snapshot if you recall). The master tries to optimise this process as well. Instead of sending the chunk over the network and creating copies across chunkservers, it requests chunkservers that already have that particular chunk stored locally to create another copy. It grants a lease to one of these chunkservers. After all this is done it sends the client information about the primary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Master Operations&lt;/h2&gt;
&lt;h3&gt;Namespace Management and Locking&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Master needs to acquire locks for some of it’s operations. Example while taking a snapshot.&lt;/li&gt;
&lt;li&gt;Efficient locking mechanism over directory and files so that many concurrent operations can be performed.&lt;/li&gt;
&lt;li&gt;The master does not have a per directory data strucuture that lists the content of that directory. It just maps fullpathnames to metadata (prefixes are compressed to reduce RAM usage by metadata).&lt;/li&gt;
&lt;li&gt;So &lt;code class=&quot;language-text&quot;&gt;/home/user/data.dat&lt;/code&gt; is actually a key with some metadata as value. There are no directories as such in GFS. The metdata from the key &lt;code class=&quot;language-text&quot;&gt;/home/user/data.dat&lt;/code&gt; points to relevant locations. Reading these locations enables the client to get the file.&lt;/li&gt;
&lt;li&gt;Each opeartion requires various locks. For example &lt;code class=&quot;language-text&quot;&gt;/d1/d2.../dn/leaf&lt;/code&gt; (leaf indicates the final directory or file it is performing an operation on) it will acquire read locks on &lt;code class=&quot;language-text&quot;&gt;/d1&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/d1/d2&lt;/code&gt;… &lt;code class=&quot;language-text&quot;&gt;/d1/d2.../dn&lt;/code&gt; and a writers locks on &lt;code class=&quot;language-text&quot;&gt;/d1/d2.../dn/leaf&lt;/code&gt;. Getting a writers lock allows writing to &lt;code class=&quot;language-text&quot;&gt;/d1..../dn/leaf&lt;/code&gt; and a reader’s lock on the remaining directories prevent &lt;code class=&quot;language-text&quot;&gt;/d1&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/d1/d2&lt;/code&gt; etc from being deleted or renamed. &lt;strong&gt;To my understanding&lt;/strong&gt; directory &lt;code class=&quot;language-text&quot;&gt;/d1&lt;/code&gt; indicates all keys (fullpath file names) which start with &lt;code class=&quot;language-text&quot;&gt;/d1&lt;/code&gt;. Given full paths to files, if two filepaths start with &lt;code class=&quot;language-text&quot;&gt;/d1&lt;/code&gt; they belong to the same directory.&lt;/li&gt;
&lt;li&gt;They give an example of the locking system prevents a file being created in a directory which is being snapshotted. I’m not sure if my understanding is correct, so it’d be better if I skip it. I couldn’t find any other link online which explained this particular section in depth.&lt;/li&gt;
&lt;li&gt;Multiple file creations can happen in the same directory as well. Both the writers acquire a read lock on the directory (the directory is protected from being renamed, deleted or snapshotted) and write locks on the files being written (this serialises attempts to create a file with the same name).&lt;/li&gt;
&lt;li&gt;Read-write lock objects are lazily allocated and deleted. They are acquired by level in the namespace tree and then lexicographically within the same level. Doing this (shallow to deep) prevents deadlocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Replica Placement&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Physical placement of servers across racks.&lt;/li&gt;
&lt;li&gt;Make sure replicas exist in different racks to maximise data availability and integrity. Say an entire rack is down due to an outage clients can still read and write.&lt;/li&gt;
&lt;li&gt;They explain that bandwidth in and out of a rack maybe less than the sum of the bandwidths of individual machines. Hence placing it in various racks can help clients exploit reads from various racks. In the case of mutations where the client has to send data, multiple racks actually are disadvantageous as data has to travel longer distances. It’s a tradeoff that they are quite satisfied about.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Creation, Re-Replication, Rebalancing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Creation and Re-Replication&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The goals of a master are to place replicas on servers with less than average disk utilisation, spread replicas across racks and reduce the number of recent “creation or writes” to each server (even though writes are cheap they are accessed by many clients simultaneously even while being written (recall checkpointing by writers and readers) which might create additional load).&lt;/p&gt;
&lt;p&gt;Chunks need to be re-replicated if the number of copies fall (data corruption on a server or a replica is unavailable) below the threshold (normally it’s set to 3 but it’s configurable as mentioned earlier). Instead of re-replicating all of them at once the master prioritises re-replication to prevent these cloning operations from becoming bottlenecks. Restrictions are placed on the bandwidth of each server for re-replication so that client requests aren’t compromised.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How are Re-replications Prioritised?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A chunk which is two short of desired replicas is given precedence over a chunk which is short by one.&lt;/li&gt;
&lt;li&gt;Live files rather than recently deleted files (discussed in the Garbage Collection section). Files that are marked as deleted are just renamed temporarily and deleted only after a few days. So replicas of them can exist for a few days as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Rebalancing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Master also rebalances regularly to achieve the above said goals. It may move replicas form one rack to another, try to bring disk usage in a server closer to the average and so on. Any new chunkserver is filled up gradually by the master rather than flood it with loads of write operations.&lt;/p&gt;
&lt;h3&gt;Garbage Collection&lt;/h3&gt;
&lt;p&gt;Any file deletion is logged immediately but the resource isn’t deleted immediately. It is renamed to some hidden folder. The master regularly scans the filesystem and deletes such files if they are older than 3 days. It also deletes metadata of chunks that have no files (it can check its file to chunk mapping and find out chunkservers that are not used) or only contains deleted files. Also during exchange of HeartBeat messages the master can instruct other chunkservers to delete replicas of the type of chunks described above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages Over Eager Deletion&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bookkeeping is reduced. Master does not keep track of messages lost (and hence keep retrying) in an environment where component failures are common.&lt;/li&gt;
&lt;li&gt;Done in batches when load is less.&lt;/li&gt;
&lt;li&gt;Tagged along with regular activities like namespace scanning.&lt;/li&gt;
&lt;li&gt;Safety net against accidental deletions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage isn’t available immediately. Poses problems when storage space is scarce. (It is possible to reduce the period to trigger deletion from 3 days to a lower value)&lt;/li&gt;
&lt;li&gt;Applications that frequently create and delete files might put the system under stress (storage is used immediately but freeing can take 3 or so days). To overcome all this the clients can specify directories that are to be stored without replication. They can also specify directories where deletion takes place immediately.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Stale Replication Detection&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The master increments the chunk version everytime it grants a lease. After the replicas of this chunk make mutations they are updated to the current version as well.&lt;/li&gt;
&lt;li&gt;If the replica isn’t available during mutation it would miss the mutation and hence would show an outdated version number. During regular garbage collection the master can take care of such replicas.&lt;/li&gt;
&lt;li&gt;Additionally the master sends the version number to a client while it requests a mutation and also while a chunkserver clones another chunkserver.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I haven’t covered Section 5 (Fault Tolerance and Diagnosis). Mostly because the post is already pretty long and also I’m lazy. Moreover Section 5 is only around a page long and can easily be grokked provided you have a reasonable idea of what I covered in these 3 parts.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Review of the Book "i want 2 do project. tell me wat 2 do."]]></title><description><![CDATA[This is a short review of a book that I read last year. Summary for people in a hurry:- Just out of College? - I’d definitely recommend…]]></description><link>https://abhirath.me/i-want-2-do-project-tell-me-wat-2-do-book-review/</link><guid isPermaLink="false">6442fa13-7c12-4a5b-b484-47c139bc518a</guid><pubDate>Fri, 20 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is a short review of a book that I read last year.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Summary for people in a hurry:-&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Just out of College?&lt;/strong&gt; - I’d definitely recommend reading the book end to end.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reasonable Experience?&lt;/strong&gt; - Skim through everything and drill down on areas of your choice. You’ll pick up a few neat things you weren’t aware of.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Veteran?&lt;/strong&gt; - Reading it end to end won’t be good use of your time. I’d recommend selective choosing and going through the reference section (less than 1 page for every topic covered) for recommendations (books, blogs etc). They are pretty interesting and will help you delve deeper.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;At first when I saw the photo of Shakthi Kannan with the book on his website I thought that he was holding some sort of banner and was looking for projects to work on.&lt;/p&gt;
&lt;p&gt;It’s an excellent read for people who know how to code but are yet to digest the fine details of the trade. College students with no work experience are a perfect example. Shakthi covers a wide plethora of information (really wide) that programmers are expected to know. People who’ve learned Computer Science at home from books / online tutorials should definitely read it. I strongly feel it fills certain gaps that help smoothen your journey as a programmer.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ba4c2edbed942d9183e897d42f028503/29d31/i-want-2-do-project-tell-me-wat-2-do.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.64864864864865%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAgAD/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdVmocY//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQABBQJf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGhAAAgIDAAAAAAAAAAAAAAAAAAEQIRFBgf/aAAgBAQABPyGjMJi4Xo//2gAMAwEAAgADAAAAEFff/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAQACAgMAAAAAAAAAAAAAAAEAESFxQVGB/9oACAEBAAE/EDKArmCJMjYRaeS+hNT/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;quotes from the book i want 2 do project tell me what 2 do&quot;
        title=&quot;&quot;
        src=&quot;/static/ba4c2edbed942d9183e897d42f028503/1c72d/i-want-2-do-project-tell-me-wat-2-do.jpg&quot;
        srcset=&quot;/static/ba4c2edbed942d9183e897d42f028503/a80bd/i-want-2-do-project-tell-me-wat-2-do.jpg 148w,
/static/ba4c2edbed942d9183e897d42f028503/1c91a/i-want-2-do-project-tell-me-wat-2-do.jpg 295w,
/static/ba4c2edbed942d9183e897d42f028503/1c72d/i-want-2-do-project-tell-me-wat-2-do.jpg 590w,
/static/ba4c2edbed942d9183e897d42f028503/29d31/i-want-2-do-project-tell-me-wat-2-do.jpg 700w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I love the quotes that he mentions in the book. I’ve started following many of the authors of those quotes. The details that he stresses on are useful. For instance I remember him mentioning to be careful while posting to mailing lists as the mails are often stored permanently on those servers (I could instantly relate when I saw a few substandard emails and later learned that they were hosted on some email listing site). I’ve also understood the importance of a few things that he mentions months later when I encountered them at my job. I particularly like the resource section of the book, it helps me quickly glance things I want to read more about. He has also explained things quite well using real life examples. Many of the books / resources mentioned in the book are spot on (I’ve read many of the books he mentioned before reading his book and I can personally vouch for them). He doesn’t leave out health and sanity. I was under the impression that RSI was a distant possibility (I was proved wrong again. People who I know very well have suffered in the past). I’ve realised that I am going to face more problems than I care to admit and on the bright side there are always going to be helpful sources that I haven’t even considered. Many of the tips that he mentions will not be applicable to you at this very moment or help you solve your current problem but you’ll find them useful sooner or later.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you’ve had even a little experience with online communities, have attended a few local meetups or have worked for sometime in a real work environment you might be aware of many things that he discusses in the book. You would still benefit if you glanced through a few sections of your interest. I am confident that you will stumble upon a few tips / tools that you wouldn’t have been aware of.&lt;/p&gt;
&lt;p&gt;If you’re a veteran and are involved in open source development from quite some time, this book isn’t for you. You’d be better off researching specific areas that you think you need to improve / streamline.&lt;/p&gt;
&lt;hr&gt;</content:encoded></item><item><title><![CDATA[Google File System Summarised (Part 2)]]></title><description><![CDATA[Link to Part 1:- Google File System Summarised Part 1 Link to Part 3:- Google File System Summarised Part 3 I’ve tried matching the sections…]]></description><link>https://abhirath.me/google-file-system-paper-explained-summary-part-2/</link><guid isPermaLink="false">7cdfc791-6c3d-46a9-bc43-2bfb020bee00</guid><pubDate>Fri, 13 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Link to Part 1:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-1/&quot;&gt;Google File System Summarised Part 1&lt;/a&gt;&lt;br&gt;
Link to Part 3:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-3/&quot;&gt;Google File System Summarised Part 3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve tried matching the sections and the content appearing below them as closely as possible to the original paper. However I’ve shuffled sections in a few instances for the sake of brevity and ease of understanding.&lt;/p&gt;
&lt;h2&gt;Metadata&lt;/h2&gt;
&lt;p&gt;Three types of Metadata. The first two are persistent and are also replicated on remote machines. All mutations to the first two are logged to an operation log&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;file-namespaces&lt;/li&gt;
&lt;li&gt;file to chunk mapping&lt;/li&gt;
&lt;li&gt;location of chunk replicas (not persistent)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;In-Memory Data Structures&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stored in memory thus fast.&lt;/li&gt;
&lt;li&gt;Periodic scan of state made possible because it’s efficient (enables garbage collection and re-replication).&lt;/li&gt;
&lt;li&gt;Approx 64 bytes of data for each 64 MB chunk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drawback&lt;/strong&gt; - Master limited by the amount of RAM. But it’s easily overcome by adding more RAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Chunk Locations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No persistent&lt;/strong&gt; record of chunks that hold the replicas. They’ve reasoned that the chunkserver ultimately decides if it has that chunk or not. The portion of the disk might have gone bad or might have vanished for some reason. Hence a persistent model only makes things harder as everytime the chunks in a chunkserver changes the master has to be notified and updated about the same. With hundreds of servers it’d contribute considerably to technical debt.&lt;/li&gt;
&lt;li&gt;Master collects this data during startup or whenever a new chunkserver joins.&lt;/li&gt;
&lt;li&gt;Master can monitor changes with the heartBeat message it sends.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Operation Log&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Record of important metadata changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Helps in defining the order of concurrent changes. Maintains a logical timeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Files and chunks and their versions are identified by the logical times at which they were created. (Master maintains a version number for each chunk to identify up-to-date chunks and stale ones. Whenever the master gives the client permission to append, it updates the version number and informs all up-to-date replicas as well. So if a chunk server is down, it misses the version update. When the failed chunkserver is up again, the master can garbage collect that particular chunk as it’s an older version.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Should be stored reliably and only shown to clients when the change is persistent. Since it’s cardinal, it is replicated across machines. Logs are batched before being written to disk on the local master as well as remote machines to reduce burden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The master can restore it’s state by replaying these logs. Even during re-replication when logs are read from disk, they are batched to reduce it’s impact.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When logs size increased beyond a threshold, the master creates a checkpoint (it’s in the form of a binary tree that maps files to chunks and requires no parsing) and stores it to disk.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Incoming requests to mutate files should not be blocked while the master is creating a checkpoint. To tackle this the master switches to a new log file in a separate thread. Creating such a checkpoint takes a minute or so for a cluster with a few million lines. This new checkpoint includes all the mutations before it. (I’m not sure as to how it’s done)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recovery only needs the latest complete checkpoint and associated log files. Older checkpoints and log files can be deleted (though Google keeps them safe in case of disasters).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The code written to help the master recover after failure detects and skips incomplete checkpoints (so failure during checkpointing is taken care of).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Consistency Model&lt;/h2&gt;
&lt;p&gt;As mentioned earlier weak consistency (different clients may see different data for small periods of time. They’ve ensured that it doesn’t drastically effect the clients though.) for performance and simplicity.&lt;/p&gt;
&lt;p&gt;Let’s start by explaining a few terms for those who aren’t familiar with GFS. The terms &lt;em&gt;consistent&lt;/em&gt;, &lt;em&gt;defined&lt;/em&gt;, &lt;em&gt;undefined&lt;/em&gt;, &lt;em&gt;inconsistent&lt;/em&gt; defined a file region or chunk in this context.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistent&lt;/strong&gt; - A file region is consistent if all the clients see the same data no matter which chunkserver they read from.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Defined&lt;/strong&gt; - It is a region after a file mutation. The client can see the mutation in it’s entirety. Say one client wants to append data and there is no other client appending to that chunk, it is defined. By implication defined also means consistent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Undefined&lt;/strong&gt; - When many clients mutate a region successfully, it is not possible to see what one particular client has written. It however is consistent.&lt;br&gt;
Failed concurrent writes leads to chunks that are undefined and inconsistent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Mutations are either writes (new files) or appends to existing files.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mutations are applied in the same order to all the replicas.&lt;/li&gt;
&lt;li&gt;Stale replicas do not participate in mutations (recall version numbers for each chunk).&lt;/li&gt;
&lt;li&gt;GFS lets a client write new data at a location that the client seems fit. However clients cannot append to a file as per their wish. GFS gives them a file offset to write to (GFS may include some padding to take care of concurrent writes to the file).&lt;/li&gt;
&lt;li&gt;They’ve also mentioned that some data might get corrupted (many writers writing to the same region) in the process but the amount of data which can get corrupted (inconsistent as explained earlier) pales in comparison to the total data. Applications (normally work on the entire data set) can still work uneffected.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How are data inconsistencies dealt with?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you recall clients cache chunk location data. So it might read data from a stale replica. When this happens agreed that it doesn’t get the complete file but it doesn’t get outdated or wrong data either. Moreover the cache timeout limits the possibility. When the cache expires and the master is contacted again it gets updated info.&lt;/li&gt;
&lt;li&gt;Applications (i.e clients) can distinguish between defined and undefined regions.&lt;/li&gt;
&lt;li&gt;GFS identifies stale servers by handshaking (recall heartBeats) and ensures data integrity by checksumming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Also keep in mind that the clients have to accommodate to ensure the overall success of the Distributed File System.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mutations only by appending. No overwriting of existing data in chunks.&lt;/li&gt;
&lt;li&gt;If the writer(client writing to the filesystem) generates a new file, it renames it to something permanent after it’s done or periodically checkpoints it. These checkpoints can also include checksum or hashes.&lt;/li&gt;
&lt;li&gt;The readers (clients reading the data) only read data upto the latest checkpoint.&lt;/li&gt;
&lt;li&gt;Client side checkpointing also ensures that readers don’t read data that writers feel are incomplete. Say the writer creates a checkpoint (indicates that it is done writing that portion) and then starts appending (still in progress), the reader only reads upto the checkpoint.&lt;/li&gt;
&lt;li&gt;The clients have to deal with duplicates (as GFS promises to append at least once, so it might append a record more than once) and padding (GFS may or may not let a writer append immediately after file end). The writers have to write some extra information (special bits or patterns) to indicate the start of an actual record. This helps avoid padding. Unique identifiers can be used for each record so when readers access the data they can avoid the identifiers they’ve already encountered.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This part would have given you a hint of what happens behind the hood. I’ll cover more details about the flow in the next part.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Awesome Computer Graphics Resources]]></title><description><![CDATA[Please keep in mind that I haven’t even started most of them. I find the links mentioned here to be great learning material and would…]]></description><link>https://abhirath.me/awesome-computer-graphics-resources/</link><guid isPermaLink="false">dd99502d-0782-47ae-aa02-1b6b88f029a4</guid><pubDate>Sat, 07 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Please keep in mind that I haven’t even started most of them. I find the links mentioned here to be great learning material and would eventually like to work my way through them. So I’m not in a position to prescribe learning paths.&lt;/p&gt;
&lt;h3&gt;Grok the Graphics Pipeline&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html&quot;&gt;An Intro to Modern OpenGL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://antongerdelan.net/opengl/vertexbuffers.html&quot;&gt;Vertex Buffer Objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://antongerdelan.net/opengl/shaders.html&quot;&gt;Shaders&lt;/a&gt;&lt;br&gt;
Same blog as the one mentioned above. Anton has other great stuff as well.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fgiesen.wordpress.com/2011/07/09/a-trip-through-the-graphics-pipeline-2011-index/&quot;&gt;Graphics Pipeline Explained in Great Detail&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Some Simple Tutorials&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://lazyfoo.net/tutorials/SDL/index.php&quot;&gt;SDL Tutorials by Lazy Foo&lt;/a&gt;&lt;br&gt;
SDL is quite popular. It’s a cross platform game development library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lighthouse3d.com/tutorials/&quot;&gt;Lighthouse 3D Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learnopengl.com/&quot;&gt;LearnOpenGL&lt;/a&gt;&lt;br&gt;
Another great set of tutorials written in a fashion that resembles a book. Have stumbled upon this site many times.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ogldev.atspace.co.uk/&quot;&gt;50 Small Incremental Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://alfonse.bitbucket.io/oldtut/index.html&quot;&gt;Learning Modern 3D Graphics Programming&lt;/a&gt;&lt;br&gt;
Written in the form of a tiny book. Well written. Tops in my list of todos.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://open.gl/introduction&quot;&gt;Another Great Set Written as a Book&lt;/a&gt;&lt;br&gt;
Again not exactly a tutorial but more like a book. By the comments it has garnered I wager that it’s awesome.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hand Held Projects&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://roguesharp.wordpress.com/&quot;&gt;Create a Roguelike Game in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://handmadehero.org/&quot;&gt;Create a Complete Professional Quality Game&lt;/a&gt;&lt;br&gt;
Looks very promising. It’s composed of videos and I think it’ll be of great help to people who want to work in the gaming industry.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inspiration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.shadertoy.com/&quot;&gt;Loads of User Submitted Shaders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://js13kgames.com/&quot;&gt;JavaScript Gamer Under 13kb&lt;/a&gt;&lt;br&gt;
Super cool concept. You have to build a game using JavaScript under 13kb (assets, code everything!). The kind of stuff that they’ve build is unbelievable. The source code for most of them are easily available as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Blogs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.realtimerendering.com/blog/&quot;&gt;Real Time Rendering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Notes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.songho.ca/opengl/index.html&quot;&gt;Songho’s Notes on OpenGL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/&quot;&gt;Linear Algebra for Game Developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Google File System Summarised (Part 1)]]></title><description><![CDATA[Paper:- Google File System Link to Part 2:- Google File System Summarised Part 2 Link to Part 3:- Google File System Summarised Part 3 The…]]></description><link>https://abhirath.me/google-file-system-paper-explained-summary-part-1/</link><guid isPermaLink="false">36aa9781-c170-402a-9f83-673e959482fa</guid><pubDate>Thu, 05 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Paper:- &lt;a href=&quot;http://sgotiweb.epn.edu.ec/~emafla/Cursos/CD/docs/gfs-sosp2003.pdf&quot;&gt;Google File System&lt;/a&gt;&lt;br&gt;
Link to Part 2:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-2/&quot;&gt;Google File System Summarised Part 2&lt;/a&gt;&lt;br&gt;
Link to Part 3:- &lt;a href=&quot;/google-file-system-paper-explained-summary-part-3/&quot;&gt;Google File System Summarised Part 3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Google File System has inspired many Distributed File Systems (Big Table and HDFS to name a few). It’s interesting to note that GFS gives up strong consistency (it promises to be eventually consistent) for the sake of simplicity and performance. Also GFS was developed for certain kinds of applications (example mapreduce) and &lt;strong&gt;IS NOT&lt;/strong&gt; suitable for most applications. Moreover Google has replaced GFS with &lt;a href=&quot;https://www.systutorials.com/3202/colossus-successor-to-google-file-system-gfs/&quot;&gt;Colossus&lt;/a&gt; as a response to changing needs.&lt;/p&gt;
&lt;h2&gt;Need Case and Assumptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hundreds or thousands of inexpensive computers accessed by a large number of clients. &lt;strong&gt;One Master Server&lt;/strong&gt;. Components fail often.&lt;/li&gt;
&lt;li&gt;Multi GB files are common. Millions of 100MB sized files. Each file contains application objects like web documents (my understanding is that the files are similar to zipped files. One large file containing many small files). Arguments for large files
&lt;ul&gt;
&lt;li&gt;Fewer large sized files are better than billions of Kilobyte sized files (storing metadata and file mappings becomes a pain as we will see later on)&lt;/li&gt;
&lt;li&gt;Redesign IO operations and block sizes due to the specific needs of the applications&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Most of the file mutations append data. Random writes in a file is almost zero.&lt;/li&gt;
&lt;li&gt;Once a file is written, it is mostly read. Most of the times the reads are sequential. Surprisingly a large number of applications can benefit from such an assumption. Data analysis applications passing through large chunks of data, mapreduce applications reading large files during reduction stage etc. Therefore there are two types of read operations.
&lt;ul&gt;
&lt;li&gt;Large Streaming Reads - Reads 100s of KBs of data sequentially.&lt;/li&gt;
&lt;li&gt;Random Reads - Reads a few KBs at some offset of a file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Applications &amp;#x26; GFS have to complement each other’s design. This increase flexibility.
&lt;ul&gt;
&lt;li&gt;Normally clients requesting data cache it. Clients using GFS should not cache it as the data is large and might be subject to change. (Clients only cache metadata like location to a particular file on a chunk)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Interface&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Familiar but does not implement POSIX.&lt;/li&gt;
&lt;li&gt;Create, Read, Open, Delete.&lt;/li&gt;
&lt;li&gt;Snapshot and Record Append.&lt;/li&gt;
&lt;li&gt;Record Append supports simultaneous appends from multiple clients without blocking.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Architecture&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1 master many chunkservers&lt;/li&gt;
&lt;li&gt;Chunkservers
&lt;ul&gt;
&lt;li&gt;Uniquely identified by 64 bit integers&lt;/li&gt;
&lt;li&gt;Store files on local disk as Linux files&lt;/li&gt;
&lt;li&gt;Replicated. Normally 3 times (can be configured)&lt;/li&gt;
&lt;li&gt;They take care of reading and writing data. The master gives the client the chunkserver location and the file byte range.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Master
&lt;ul&gt;
&lt;li&gt;HeartBeat messages - Periodic communication with chunkservers. Gives instructions and finds out more about their state.&lt;/li&gt;
&lt;li&gt;Metadata (map individual file to a chunk and byte range, location of each individual chunk, replicas store etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Single Master&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Simplified actions when it comes to file mapping and replication. Single leaders and masters are known to reduce complexity (Eg &lt;a href=&quot;/raft-distributed-system-consensus-algorithm-explained/&quot;&gt;Raft Consensus Algorithm&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Minimum involvement with the clients. Say the client wants to read or write to a file, it gets the location from the master and deals with that chunk server. Also this metadata (i.e server location (with details of their replicas( and byte offset for a particular file) is cached. So the client needn’t bother the master frequently for metadata.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Chunk or Block Size&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Key design parameter. They’ve designed each block size to use 64MB. To help you contrast :- A normal linux system uses 4KB as it’s block size.&lt;/li&gt;
&lt;li&gt;Larger block size reduces client master interaction. It can get the required details about file locations in one request. It is not uncommon for clients to cache metadata for multi TB datasets hence even random reads can be performed without the involvement of the master.&lt;/li&gt;
&lt;li&gt;Lazy space allocation is used as a counter measure to internal fragmentation. Read &lt;a href=&quot;https://stackoverflow.com/questions/18109582/what-is-lazy-space-allocation-in-google-file-system&quot;&gt;this StackOverflow question&lt;/a&gt; for more details. You can also read about &lt;a href=&quot;https://en.wikipedia.org/wiki/Sparse_file&quot;&gt;Sparse Files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Since clients are probably going to read data from a chunkserver for a long period of time (remember the base assumption, files are large and data is read sequentially), it can make use of a persistent TCP connection.&lt;/li&gt;
&lt;li&gt;Small files can turn the chunkserver which house them into hot spots (active with lots of incoming requests). This problem can be alleviated by having more replicas of such files. &lt;a href=&quot;https://stackoverflow.com/questions/46577706/why-do-small-files-create-hot-spots-in-the-google-file-system&quot;&gt;This StackOverflow&lt;/a&gt; discussion might be of use. The requests are therefore distributed over a larger number of servers.&lt;/li&gt;
&lt;li&gt;They had an executable hosted (it fit in a single block). It was used by hundreds of machine on startup at the same time and this created problems. They solved this issue by increasing the replication factor and staggering the application start times (instead of starting all the applications that needed the file at once, they spread it out to reduce the number of concurrent requests). This is another such occassion where they’ve resorted to making modifications to the client to keep the architecture simple.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ll cover the remaining sections in the future :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Awesome Distributed Systems Resources]]></title><description><![CDATA[New to the Concept of Awesome Lists? They are a curation of exciting resources on a particular subject. They are actually quite popular…]]></description><link>https://abhirath.me/awesome-distributed-systems/</link><guid isPermaLink="false">ab8a3305-867d-4f20-87d9-6b20f44d8044</guid><pubDate>Wed, 27 Sep 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;New to the Concept of Awesome Lists?&lt;/h3&gt;
&lt;p&gt;They are a curation of exciting resources on a particular subject. They are actually quite popular these days.&lt;/p&gt;
&lt;p&gt;This list would have been incomplete without the input of &lt;a href=&quot;https://www.github.com/shrayasr&quot;&gt;Shrayas&lt;/a&gt;. I’ll keep adding stuff as and when something catches my eye. Please keep in mind that I haven’t personally gone through most of them. Some of them are recommendations by people I know and I’ve actually read a few of these resources.&lt;/p&gt;
&lt;h3&gt;Blog Posts and Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.somethingsimilar.com/2013/01/14/notes-on-distributed-systems-for-young-bloods/&quot;&gt;Notes on Distributed Systems for Young Bloods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ksat.me/a-plain-english-introduction-to-cap-theorem&quot;&gt;Plain English Introduction to CAP Theorem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://prakhar.me/articles/understanding-rpcs/&quot;&gt;Understanding RPCs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/12347673/5698202&quot;&gt;CA CP and AP&lt;/a&gt;&lt;br&gt;
Read this StackOverflow answer after you’ve read the Plain English Introduction to CAP Theorem.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/peterj/cap-theorem-explained-2kmb&quot;&gt;Why CA systems can’t exist?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://highscalability.com&quot;&gt;High Scalability&lt;/a&gt;&lt;br&gt;
An awesome blog with loads of resources on Distributed Systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Papers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://lamport.azurewebsites.net/pubs/time-clocks.pdf&quot;&gt;Time, Clocks and the Ordering of Events in a Distributed System&lt;/a&gt;&lt;br&gt;
This is the most cited paper in computer science.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://static.googleusercontent.com/media/research.google.com/en//archive/mapreduce-osdi04.pdf&quot;&gt;MapReduce: Simplified Data Processing on Large Clusters&lt;/a&gt;&lt;br&gt;
A novel way developed at Google to abstract away problems concerning distributed systems from the end programmer.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://raft.github.io/raft.pdf&quot;&gt;In Search of an Understandable Consensus Algorithm&lt;/a&gt;&lt;br&gt;
A relatively easy to understand consensus algorithm. I’ve written notes for this paper &lt;a href=&quot;/raft-distributed-system-consensus-algorithm-explained/&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf&quot;&gt;Paxos Made Simple&lt;/a&gt;&lt;br&gt;
Paxos (a consensus algorithm which people consider pretty hard to understand) explained in simpler terms.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://static.googleusercontent.com/media/research.google.com/en/us/archive/gfs-sosp2003.pdf&quot;&gt;Google File System&lt;/a&gt;&lt;br&gt;
Distributed file system at Google. It is 14 years older than this blog post. Google has made a quite a few changes to their file system in light of recent developments. I’ve written notes for this paper &lt;a href=&quot;/google-file-system-paper-explained-summary-part-1/&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;People to Follow&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Aphyr
He runs Jepsens. Jepsens focuses on the safety of distrbuted systems and puts their claims to a test. He trains people as well. &lt;a href=&quot;https://github.com/aphyr/distsys-class&quot;&gt;Notes from his 2 day training&lt;/a&gt;. They’ve also analysed various leading databases and queues. You can find the reports &lt;a href=&quot;https://jepsen.io/analyses&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Other Links that Have Lists&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://caitiem.com/2017/09/07/getting-started-with-distributed-systems/&quot;&gt;Resources for Getting Started with Distributed Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/theanalyst/awesome-distributed-systems&quot;&gt;Awesome List by theanalyst&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Quick Hacks 1]]></title><description><![CDATA[Here are a few ways of solving problems that deviate from the norm. They aren’t the best solutions nor do I recommend you to use these in…]]></description><link>https://abhirath.me/quick-hacks-1/</link><guid isPermaLink="false">a517553e-9c9b-4edc-ba71-77d88ec194aa</guid><pubDate>Tue, 26 Sep 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here are a few ways of solving problems that deviate from the norm. They aren’t the best solutions nor do I recommend you to use these in production or critical systems. These may or may not be elegant or well expressed.&lt;/p&gt;
&lt;p&gt;I think these are quite creative. I intend to document more of these as I find (and hopefully create in the future) them. I wager that they are a nice gentle examples of thinking outside the box. Also these are examples of how one tool can be used to solve a wide variety of problems.&lt;/p&gt;
&lt;h2&gt;1. Removing Duplicates and Sort&lt;/h2&gt;
&lt;p&gt;I don’t recall where I saw this (It was some Go repository). Now languages like Python, Haskell and JavaScript have inbuilt functions to remove duplicates from lists or arrays. Go does not.&lt;/p&gt;
&lt;p&gt;You can quickly whip up an one liner in Python. Let’s see how this problem was solved in Go.&lt;/p&gt;
&lt;p&gt;I feel this is a neat hack as you don’t have to implement a function to remove duplicates. The guy basically used the sort function and turned it to a tool to help him remove duplicates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem:-&lt;/strong&gt; It’s a slice (array, list whatever) of Strings. Go has a function to sort a slice of strings but no inbuilt function to remove duplicates.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;strings&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;sort&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// a function which takes in a list of strings and returns a list of strings&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SortAndRemoveDuplicates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;badList &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; lastIteration &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// a variable to hold the return value&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; finalList &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// badList is now sorted but still has duplicates&lt;/span&gt;
    sort&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Strings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;badList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// we iterate over the sorted list&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; individualString &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;range&lt;/span&gt; badList &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// since it&apos;s sorted same strings appear together&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// if the last added string to the final list it is a duplicate&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// we only add it to the new list if the current string is not&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// identical to the previous string that was added&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; individualString &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; lastIteration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            finalList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;finalList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; individualString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            lastIteration &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; individualString
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; finalList
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;2. Accessing Elements in an Array&lt;/h2&gt;
&lt;p&gt;I saw this in a competitive programming repository.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem:-&lt;/strong&gt; Access two consecutive elements in an array. If it’s the last element access the first element. First and second, second and third and so on until last and first. The length of the list is known in advance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:-&lt;/strong&gt; I &lt;em&gt;think&lt;/em&gt; reduce (the functional programming pattern) is a good fit for an elegant solution to this problem. However I haven’t tried implementing it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// normal straightforward way&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; indexOfLast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; myList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// hacky way&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// we just append the first element to the end&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// myList is now [1,2,3,4,5,6,7,8,1]&lt;/span&gt;
myList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; myList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; indexOfLast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; myList&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s very similar to “Array Rotation” (Courtesy:- &lt;a href=&quot;https://www.reddit.com/user/henrebotha&quot;&gt;Henre Botha&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;3. Bank Withdrawal Checking&lt;/h2&gt;
&lt;p&gt;I read this in the book &lt;strong&gt;The Go Programming Language&lt;/strong&gt; by Alan Donovan and Brian Kernighan.&lt;/p&gt;
&lt;p&gt;This is not a hack nor does it reduce work. I felt it gives a different approach to the problem. Many might disagree.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; balance &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Deposit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    balance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; balance &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; amount
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// normally we check if balance is greater&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// than the amount to be withdrawn&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Withdraw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; balance &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; amount &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        balance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; balance &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; amount
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// withdrawal was a success&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// failed&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// A different way&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Withdraw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Deposit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// we use deposit to make a negative deposit&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; balance &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// if balance is less than 0, we add the original amount back&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;Deposit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;4. Rounding to the Nearest Integer&lt;/h2&gt;
&lt;p&gt;I don’t recall the source.&lt;/p&gt;
&lt;p&gt;**Problem:-**Rounding floats to their nearest complete values.&lt;br&gt;
5.1 -&gt; 5.0&lt;br&gt;
5.7 -&gt; 6.0&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Normal way&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# returns 5.0&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# returns 6.0&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# A different way&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; math

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;my_round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;float_please&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Please google math.ceil if you arent&apos; aware of what it does&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Just think about the different scenarios. I&apos;m&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# pretty sure you won&apos;t need an explanation :)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ceil&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;float_please &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

my_round&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# returns 5.0&lt;/span&gt;
my_round&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5.7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# return 6.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;End&lt;/h3&gt;
&lt;p&gt;I’ll try my best to keep note of the link or repository that house such solutions from this point onwards. Also if you are aware of similar hacks or alternate ways of solving problems, please comment them below :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Raft (A Consensus Algorithm) Explained]]></title><description><![CDATA[An attempt to understand and annotate Raft. I’ll also be linking to other resources that helped me get a better grip of the material in this…]]></description><link>https://abhirath.me/raft-distributed-system-consensus-algorithm-explained/</link><guid isPermaLink="false">d19b65cf-343b-4f49-a313-b836ff60b79b</guid><pubDate>Sat, 23 Sep 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;An attempt to understand and annotate Raft. I’ll also be linking to other resources that helped me get a better grip of the material in this paper. I will &lt;strong&gt;not&lt;/strong&gt; contrast Raft and Paxos as I do not understand Paxos. Also I’ve left out 3 small topics (Cluster Changes, Log Compaction and Client Interaction) that are quite easy to grok once you understand the crux of the algorithm.&lt;/p&gt;
&lt;p&gt;Paper:- &lt;a href=&quot;https://raft.github.io/raft.pdf&quot;&gt;Raft&lt;/a&gt;&lt;br&gt;
Recommended By:- &lt;a href=&quot;https://github.com/shrayasr&quot;&gt;Shrayas Rajagopal&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Recommended Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Replicated State Machines&lt;/strong&gt; - A common practice in distributed systems to replicate data across multiple systems. So even if one or a few of them go down, the system as a whole can function with the help of the copies. Instead of copying data, the replica and the primary system execute the same exact commands in the same order.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://harry.me/blog/2013/07/07/id-like-to-have-an-argument-a-primer-on-consensus/&quot;&gt;Consensus Problem Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://harry.me/blog/2014/12/27/neat-algorithms-paxos/&quot;&gt;Quick Look into Paxos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In case you don’t know what a RPC is - &lt;a href=&quot;https://prakhar.me/articles/understanding-rpcs/&quot;&gt;Understanding RPCs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Algorithm Explained&lt;/h2&gt;
&lt;p&gt;You can kind of see Raft in action here - &lt;a href=&quot;http://thesecretlivesofdata.com/raft/&quot;&gt;Raft Visually Explained&lt;/a&gt;. I’m pretty sure I won’t be able to explain it better than them. You can come back to this article for some of the smaller not so important details that isn’t covered by this visualisation.&lt;/p&gt;
&lt;h3&gt;Basics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;To increase understandability they focused on two general approaches of problem simplification. The consensus problem is broken into three relatively independent subproblems (&lt;strong&gt;Leader Election&lt;/strong&gt;, &lt;strong&gt;Log or State Replication&lt;/strong&gt;, &lt;strong&gt;Safety&lt;/strong&gt;). They’ve tried reducing the state space whenever possible by using randomised approaches&lt;/li&gt;
&lt;li&gt;They’ve emphasised on the importance of having a leader. It greatly simplifies decision making&lt;/li&gt;
&lt;li&gt;Leaders typically operate until they fail&lt;/li&gt;
&lt;li&gt;At any given time each server is a &lt;em&gt;leader&lt;/em&gt;, &lt;em&gt;follower&lt;/em&gt; or a &lt;em&gt;candidate&lt;/em&gt;. When a node first comes to life it always is a follower. If it doesn’t receive a &lt;em&gt;heartbeat&lt;/em&gt;(an acknowledgement from the Leader) message for a specified time, it assumes there is no leader and gets promoted to &lt;em&gt;candidate&lt;/em&gt;. It nominates itself and starts an election. If that particular node wins majority it becomes the leader for that term&lt;/li&gt;
&lt;li&gt;Each server can vote for one candidate on a first-come-first-serve basis. Assume node 1 and 2 have timed out and are requesting for votes. Node 1 reaches out to node 3 before node 2, node 3 will vote in favour of node 1&lt;/li&gt;
&lt;li&gt;Time is divided into units called terms. Terms are represented by positive consecutive integers. Each node keeps track of&lt;/li&gt;
&lt;li&gt;Terms act as a logical clock. Say a node becomes the leader for term 2 and becomes unavailable (network cable unplugged or whatever) after some time. One of the functional follower nodes timeout and enter candidate state and eventually becomes the leader. When the unavailable leader return to the cluster it notices that it’s term 3 (remember it was the leader for term 2), it steps down and becomes a follower&lt;/li&gt;
&lt;li&gt;Terms are also used to find and fix anomalies in data between different nodes&lt;/li&gt;
&lt;li&gt;Servers communicate using Remote Procedure Calls. They are issued in parallel for performance gains&lt;/li&gt;
&lt;li&gt;There can only be one leader for a particular term. Say servers become lose connectivity and are split into two groups that can communicate amongst themselves. One of the groups is now void of a leader. One of the nodes in the group without a leader initiates an election by becoming a candidate. It’s then chosen as a leader and all the nodes of that group increment their term by one. Two different leaders can exist for these groups given that they are leaders for different terms&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Leader Election&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The entries (or change in state) flow through the leader to the other nodes in the system. Greatly reduces complexity and increased understandability&lt;/li&gt;
&lt;li&gt;As explained earlier a &lt;em&gt;candidate&lt;/em&gt; initiates an election if it doesn’t get a &lt;em&gt;heartbeat&lt;/em&gt; for a said duration. One of the following can happen when an election is initiated
&lt;ul&gt;
&lt;li&gt;It wins the vote if it secures a majority. Once it wins, it sends out &lt;em&gt;heartbeats&lt;/em&gt; to other servers to claim authority and also to prevent elections unnecessarily. There are additionally safety checks before a &lt;em&gt;candidate&lt;/em&gt; can take charge, I’ll cover them in a bit&lt;/li&gt;
&lt;li&gt;It receives a &lt;em&gt;heartbeat&lt;/em&gt; or &lt;em&gt;appendEntry&lt;/em&gt; (RPC to change state) from a leader during the voting process. It checks the term. If the term matches it’s current term or is higher, it realises that a new leader isn’t needed and transitions to become a follower. If the term is dated, it rejects the RPC as it probably is from the leader of an older term&lt;/li&gt;
&lt;li&gt;There’s a split vote or tie between two or more servers. Winning isn’t enough to become a leader, you need majority support. All the servers increment their term (this term had no leader) and initiate a re-election&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Randomised timeouts are used to prevent split votes. If they had the same timeout, if a leader fails, many of the nodes might timeout in quick succession and the distributed system will witness many candidates. However if they had different timeouts, one of the node times out and becomes the leader even before other nodes get a chance to timeout&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Log Replication&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Once the troop has a leader, it begins responding to clients. Each client request contains a command to be executed by the replicated state machines (modify an existing entry or add new entries etc)&lt;/li&gt;
&lt;li&gt;The leader makes the changes (or appends the client command to it’s log) and sends out RPCs (&lt;em&gt;AppendEntries&lt;/em&gt;) in parallel to all the other nodes ordering them to do the same. Please note that the leader doesn’t commit the the entry just yet. The log entry is only committed when it is able to replicate the said change by the client in more than half the number of servers. It then returns the result of that execution to the client&lt;/li&gt;
&lt;li&gt;A single or a few slow nodes will not impact performance at all. Once majority is achieved the entry is committed, the leader indefinitely tries sending RPCs to slow nodes until it gets a response&lt;/li&gt;
&lt;li&gt;Log Matching Property (every command or entry has an index and term)
&lt;ul&gt;
&lt;li&gt;If two entries have the same index and term, they store the same command&lt;/li&gt;
&lt;li&gt;If two entries in different logs have the same index and term, then the logs are identical in all preceding entries&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The first property is a result of the fact that the leader creates at most one entry with a said index in a term. Also log entries never change position&lt;/li&gt;
&lt;li&gt;The second property is maintained quite easily as well. When the leader sends out an &lt;em&gt;AppendEntries&lt;/em&gt; RPC, it also includes the index and term of the preceding entry in it’s own log. If the follower’s latest entry does not match the preceding entry given in the RPC, it rejects it. It refuses new entries. This is a safety check mechanism. So if a follower responds to an AppendEntry the leader knows for sure that the particular follower’s log matches it’s log until that entry&lt;/li&gt;
&lt;li&gt;If the follower rejects it’s AppendEntries RPC (implying inconsistencies), the leader looks up the logs of the follower. It finds the latest entry upto which they agree upon and delete every entry after that. It then sends all it’s entries to the follower after that point in time (they’ve also pointed a possible optimisation. The follower can send the conflicting entry instead of the leader having to search for it)&lt;/li&gt;
&lt;li&gt;A leader never overwrites or deletes entries in it’s own log&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Safety&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Election Restriction&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The leader must have all committed entries&lt;/li&gt;
&lt;li&gt;When a candidate sends out a &lt;em&gt;RequestVoteRPC&lt;/em&gt;, it also sends out details about it’s logs (last committed entry). The voter can deny to vote for that candidate if it’s logs are more up to date than the candidate&lt;/li&gt;
&lt;li&gt;Raft uses terms and entry index to determine the more recent log. If between two logs, one of them ends with a term 1 and the other has term 2, obviously the one with term 2 is more recent. If the logs have the same term, the longer log (therefore greater index) is more recent&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Committing Entries From Previous Terms&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Say a leader copies entries to a majority of the servers but crashes before committing the entry&lt;/li&gt;
&lt;li&gt;A new leader is chosen. It is now implied that at least one of the server with the new uncommitted entry has voted for the new leader (because a new entry is accepted only with majority and the same goes for a new leader)&lt;/li&gt;
&lt;li&gt;It is important to keep in mind that only entries from the current term are committed by counting replicas across nodes&lt;/li&gt;
&lt;li&gt;In short previous term’s uncommitted entry if accepted by a majority of the nodes are automatically handled and committed when a new entry in a new term is received. They’ve explained the argument on page 9 of the paper&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Miscellaneous&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Follower and Candidate Crashes&lt;/strong&gt;&lt;br&gt;
They are quite easily handled. Say a follower crashes, the leader indefinitely tries sending it the same RPC. When the follower is back up, it then receives it and responds thus completing the cycle. Keep in mind that this wont’ effect performance as the leader only waits for the majority to respond. So a single or a few nodes don’t matter&lt;br&gt;
Say a follower receives the RPC, appends the entries but fails before responding - When the follower is backup, it will receive the same RPC from the leader. Raft RPCs are idempotent. It notices the entry in it’s log and rejects it&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timing and Availability&lt;/strong&gt;&lt;br&gt;
This section explains something critical but very obvious for the proper functioning of the system. Say it takes 10 milliseconds to broadcast a message from the leader to all the followers the election timeout as you guessed it must be larger than 10 milliseconds (if it’s less than the broadcastTime, servers will keep timing out on a continuous basis assuming the absence of a leader)&lt;br&gt;
&lt;em&gt;MTBF&lt;/em&gt; is the average time between failures for a single server. It’s typically several months or more&lt;br&gt;
&lt;em&gt;MTBF&lt;/em&gt; and &lt;em&gt;broadcastTime&lt;/em&gt; are properties of the underlying system. &lt;em&gt;electionTimeout&lt;/em&gt; can however be manually set
In short this should be &lt;code class=&quot;language-text&quot;&gt;broadcastTime &amp;lt; electionTimeout &amp;lt; MTBF&lt;/code&gt; MTBF should be much larger than the electionTimeout. When a leader crashes, the system will be unavailable for a duration roughly equivalent to the electionTimeout. Therefore the electionTimeout should be a very small portion of overall time. Say the leader crashes every 6 months or so and the electionTimeout is 500 milliseconds. The system is therefore unavailable for 500 ms every 6 months.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Python Threading With Simple Examples]]></title><description><![CDATA[I generally love the synchronous and predictable nature of Python. No promises, callbacks and nested code. Life’s good. Elegant and no time…]]></description><link>https://abhirath.me/python-threading-with-simple-stateless-functions/</link><guid isPermaLink="false">f29826eb-5c91-413c-a754-288412725efe</guid><pubDate>Sun, 11 Jun 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I generally love the synchronous and predictable nature of Python. No promises, callbacks and nested code. Life’s good. Elegant and no time spent fixing async bugs. I rarely ever miss JavaScript’s async nature. Moreover I’ve hardly needed to use threads in Python.&lt;/p&gt;
&lt;p&gt;However when using Python for network or disk intensive tasks, you start feeling the pain. JavaScript’s async nature would obviously make it much faster and you can imagine the time you’d save if you’d have say scrape large amounts of data and write them to disk on a regular basis. Also at times you might need threads to perform complex calculations faster.&lt;/p&gt;
&lt;p&gt;Do keep in mind though - &lt;a href=&quot;https://realpython.com/python-gil/&quot;&gt;Python is limited by a Global Interpreter Lock (GIL)&lt;/a&gt;. Threads you create don’t really execute code in a parallel fashion.&lt;/p&gt;
&lt;h2&gt;Creating Threads&lt;/h2&gt;
&lt;p&gt;Having additional threads can significantly increase the complexity of your program. You will need to ensure that they don’t compete for the same resources at the same time (race conditions), Global Interpreter Locks in Python, ensure that certain statements execute only after all the threads are done executing their assigned tasks and so on.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; threading
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Got the url you asked for\n Status Code:-&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code

thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
thread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Exit&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the example above &lt;code class=&quot;language-text&quot;&gt;print &quot;Exit&quot;&lt;/code&gt; is called as soon the thread is created and will appear on the console before the &lt;code class=&quot;language-text&quot;&gt;print &quot;Got the url you asked for&lt;/code&gt;. We shall see how to overcome this in the &lt;code class=&quot;language-text&quot;&gt;join&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;Now let’s try creating an arbitrary number of threads and also store them so that we can do other stuff with them later on.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; threading
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thread_number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hi, I&apos;m thread number &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Here&apos;s the status code &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

thread_list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;xrange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    thread_list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    thread_list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how we store the threads in a list. This time I’m also supplying an integer so that we can identify them. Hopefully it’ll make things easier later on.&lt;/p&gt;
&lt;h2&gt;Joins&lt;/h2&gt;
&lt;p&gt;You also need a mechanism to control the flow of code. Say you want to read the file only after a thread has made a network request and written something to file. Jump back to the first example on the page. &lt;code class=&quot;language-text&quot;&gt;print &quot;Exit&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once a join statement is called in context to a thread, execution pauses unless the thread is done with it’s task. Continuing example one.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; threading
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Got the url you asked for\n Status Code:-&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code

thread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
thread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
thread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Code after this gets executed only after the thread is done executing.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Exit&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Comparing total time taken&lt;/h3&gt;
&lt;p&gt;Without using threads.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Time Taken - 25 seconds&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; threading
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time

tic &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thread_number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;xrange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

toc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Time Taken:-  &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toc &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; tic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; seconds&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using threads. I’ve blindly used 25 threads. In practice the number of threads are only set after careful analysis and trial and error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time Taken - 6 seconds&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; threading
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time

tic &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; thread_number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    status_code &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;thread_number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;status_code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

thread_list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;xrange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    thread_list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threading&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Thread&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    thread_list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;xrange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    thread_list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

toc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Time Taken:-  &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toc &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; tic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; seconds&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the example above I use multiple join statements in a loop. Let me brief you about the flow.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;.join()&lt;/code&gt; is called on the first thread. So the main thread is blocked until thread one finishes execution.&lt;/li&gt;
&lt;li&gt;Now the interpreter tries to &lt;code class=&quot;language-text&quot;&gt;.join()&lt;/code&gt; the second thread. Let’s assume it has already finished execution. It does not block the main thread and immediately calls &lt;code class=&quot;language-text&quot;&gt;.join()&lt;/code&gt; on the third thread.&lt;/li&gt;
&lt;li&gt;This continues till the 25th thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Try Making Them Functional&lt;/h2&gt;
&lt;p&gt;You can reduce complexity when using threads if you reduce their impact on common state. Eg:- If you create threads that access the same file, you might run into race conditions. You would have to lock and unlock the resource and so on. You could perhaps structure them in such a way that they read and write to their own files.&lt;/p&gt;
&lt;p&gt;If performing complex calculations using threads, organise them in such a way that they take in inputs and give out outputs. That’s it. By inputs and outputs I mean they shouldn’t change the value of a variable or write disk to file or do anything that might effect something else. Think about it. By having functions that don’t change anything externally, you greatly reduce the complexity of your code and you also make testing easier.&lt;/p&gt;
&lt;h2&gt;How Many Threads?&lt;/h2&gt;
&lt;p&gt;There’s no magic number. Also the advise to create threads equivalent to 2 * number of CPU cores is hardly applicable and you should refrain from following it. Also be aware of the Global Interpreter Lock. I’d suggest reading the following StackOverflow answers &lt;a href=&quot;https://stackoverflow.com/questions/481970/how-many-threads-is-too-many&quot;&gt;How many threads is too many?&lt;/a&gt; and &lt;a href=&quot;https://stackoverflow.com/questions/19369724/the-right-way-to-limit-maximum-number-of-threads-running-at-once&quot;&gt;The right way to limit maximum number of threads&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Downloading Stuff with Firefox and Selenium]]></title><description><![CDATA[Selenium Not Required Selenium Becomes Necessary Pesky Confirmation Dialogs Alternative One Enter Firefox Profiles Consider this small…]]></description><link>https://abhirath.me/download-stuff-with-firefox-selenium-python/</link><guid isPermaLink="false">b0e1ff72-c98f-4978-b329-ed57bdbf50c1</guid><pubDate>Thu, 02 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;div id=&quot;post-index&quot;&gt;
&lt;h2&gt;Index&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#selenium-not-required&quot;&gt;Selenium Not Required&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#selenium-becomes-necessary&quot;&gt;Selenium Becomes Necessary&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#pesky-confirmation-dialogs&quot;&gt;Pesky Confirmation Dialogs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#alternative-one&quot;&gt;Alternative One&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#enter-firefox-profiles&quot;&gt;Enter Firefox Profiles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;selenium-not-required&quot;&gt;Selenium Not Required&lt;/h2&gt;
&lt;p&gt;Consider this small example where &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; or Python’s &lt;code class=&quot;language-text&quot;&gt;urllib&lt;/code&gt; are sufficient. You want to download 1000 zip files from URI’s having a set pattern.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;examplesite.com/download/1.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;examplesite.com/download/2.zip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;examplesite.com/download/3.zip&lt;/code&gt; and so on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case you could write a Bash or a Python script that keeps incrementing an integer, append it to the desired string, fetch the content of the URI and save the content in your desired location. Emulating a browser doesn’t even make sense in this case. It’ll be much slower due to GUI coming into picture, might not work on different versions of Firefox (I’ve faced this issue. Selenium often stops working with new updated versions of Firefox. It’s a good idea to turn off auto update in case you use Selenium often).&lt;/p&gt;
&lt;h2 id=&quot;selenium-becomes-necessary&quot;&gt;Selenium Becomes Necessary&lt;/h2&gt;
&lt;p&gt;You’ve probably used Selenium to automate tests for your web application or to scrape some data from a few websites. It is also possible to use Selenium to download stuff automatically and save them in your desired location. Selenium might be handy in the following conditions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The app uses JavaScript and HTML5 to create a CSV that can then be downloaded.&lt;/li&gt;
&lt;li&gt;Download link is randomly generated by the server. It changes from time to time or there is no recognisable pattern in a bunch of files.&lt;/li&gt;
&lt;li&gt;Some websites try blocking scripts (programmatic access) and only access via browsers (real humans). They have some mechanisms to help them achieve the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pesky-confirmation-dialogs&quot;&gt;Pesky Confirmation Dialogs&lt;/h3&gt;
&lt;p&gt;You can press download buttons using Selenium. But what about those confirmation boxes that appear asking you if you really want to download that particular file? Selenium as of today has no way to interact with those confirmation dialog boxes.&lt;/p&gt;
&lt;h3 id=&quot;alternative-one&quot;&gt;Alternative One&lt;/h3&gt;
&lt;p&gt;Firefox has various options pertaining to dowloads like default location, alert on complete, auto download etc. You can make system wide changes on Firefox and you might have to fiddle with some advanced settings on Firefox (visit &lt;code class=&quot;language-text&quot;&gt;about:config&lt;/code&gt; on your browser to change such settings). So you can tune it such that it doesn’t ask for confirmation nor the location thus avoiding those dialog boxes. The problem with this approach is that your code isn’t going to work on your friend’s system out of the box and these changes are going to effect your browsing experience.&lt;/p&gt;
&lt;h3 id=&quot;enter-firefox-profiles&quot;&gt;Enter Firefox Profiles&lt;/h3&gt;
&lt;p&gt;Firefox provides an API to change it’s configuration. We’ll be using Selenium to interact with the API and temporarily use a particular configuration for our purposes. This increases the probability of it working on different computers and also gives you a way to preserve your default settings.&lt;/p&gt;
&lt;p&gt;After a decent amount of time spent on StackOverflow and Google and testing various methods given by people I found the following code to work for me :)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; selenium &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; webdriver


fp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; webdriver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FirefoxProfile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
fp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;set_preference&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;browser.download.folderList&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
fp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;set_preference&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;browser.download.manager.showWhenStarting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
fp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;set_preference&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;browser.download.dir&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getcwd&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data_directory_path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
fp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;set_preference&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;browser.helperApps.neverAsk.saveToDisk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/csv, text/csv, application/pdfss, text/csv, application/excel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
fp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;set_preference&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;browser.download.manager.showAlertOnComplete&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

driver &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; webdriver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Firefox&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firefox_profile&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Followed by code to download the stuff you desire&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item></channel></rss>