<?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[Tanseer Saji]]></title><description><![CDATA[Backend engineer with 5 years designing scalable, high-performance APIs. Skilled in Python, FastAPI, Next.js, Express.js, Docker, Kubernetes, and AWS—passionate about AI-driven automation.]]></description><link>https://tanseersaji.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 23:10:55 GMT</lastBuildDate><atom:link href="https://tanseersaji.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[What keeps me up at night]]></title><description><![CDATA[It is 2 AM. I am staring at the ceiling again.
This used to happen before big releases or when something was broken in production and I could not figure it out. Now it is something else. It is the qui]]></description><link>https://tanseersaji.com/what-keeps-me-up-at-night</link><guid isPermaLink="true">https://tanseersaji.com/what-keeps-me-up-at-night</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Thu, 19 Mar 2026 13:40:08 GMT</pubDate><content:encoded><![CDATA[<p>It is 2 AM. I am staring at the ceiling again.</p>
<p>This used to happen before big releases or when something was broken in production and I could not figure it out. Now it is something else. It is the quiet thought that shows up after all the noise fades.</p>
<p><em>AI can write code.</em></p>
<p>Not toy examples. Real code. Code that looks like something I would have written after years of doing this job.</p>
<p>I am a senior software engineer. I have spent years getting here. Late nights, messy systems, strange bugs that made no sense until they suddenly did. That experience used to feel like a moat. Lately, it feels thinner.</p>
<p>For a while, I leaned on that experience. I told myself there were things AI would never understand: the weird decisions buried inside old systems, the half-broken logic that only exists because something else depends on it, the kind of knowledge you only get from being there when things went wrong.</p>
<h3>The Ground is Moving</h3>
<p>Then I started seeing things that did not fit that story. I watched an AI refactor a block of code I had been avoiding for days. It was not perfect, but it was clean and readable and better than what was there. A few days later, it pointed out a subtle concurrency bug. The kind that usually takes time and patience to track down. It caught it in seconds.</p>
<p>That was the moment something shifted for me. The machine does not “understand” the way we do. But it does not need to. With enough context, it can trace patterns across a codebase and arrive at something that works. It can hold more of the system in its head than I ever could. And it does not get tired.</p>
<p>That is the part that keeps me up sometimes. Not fear in a dramatic sense. Just a quiet realization that the ground under the role is moving. We are not competing with tools anymore. We are standing next to systems that can generate more output in a minute than we can review in an hour.</p>
<p>The math is different now.</p>
<h3>Where Experience Still Matters</h3>
<p>For a while, I kept asking myself the same question: <em>If the machine can write the code, what exactly am I being paid for?</em></p>
<p>That question forced me to look at my work in a way I had not before. I do not get paid to type fast. I do not get paid to remember syntax. The value has never really been in the act of writing code. It just looked that way because that was the visible part.</p>
<p>The value is in deciding what should be built. In knowing when something is wrong even if it compiles. In understanding the tradeoffs that are not written anywhere. In taking responsibility when things break. Those are the moments where the cost of being wrong is high. That is where experience still matters.</p>
<p>A modern commercial jet flies almost entirely on autopilot, but we still pay pilots a premium to handle that 1% of pure uncertainty. Software development is rapidly shifting toward this exact model.</p>
<p>I started changing how I work. I let the AI handle the parts I used to grind through: setting up endpoints, filling in repetitive logic, getting a rough draft of something on the screen. I use it to scan through files when I have a vague idea of where a bug might be hiding. It is fast. It clears space.</p>
<h3>Directing the Process</h3>
<p>The interesting part is what happens after that. I spend more time deciding if the feature should exist at all. I look at how it fits into the system instead of just how to implement it. When something breaks, I am not just fixing a function. I am tracing how data flows through multiple services and figuring out where the assumptions failed.</p>
<p>There is also a new kind of work that did not exist before. Guiding the AI. Breaking a vague problem into something it can handle. Knowing when to trust the output and when to throw it away. It feels less like writing code and more like directing a process.</p>
<p>That shift took some time to accept. It felt like I was letting go of something I had worked hard to get good at. But the alternative is worse: holding on to a version of the job that is slowly disappearing.</p>
<h3>The Right Side of the Line</h3>
<p>The role is changing whether we like it or not. Some parts of software development will shrink. The kind of work that is repetitive and predictable is already being absorbed by these tools. There is no point pretending otherwise.</p>
<p>What remains is harder. You need to see the system as a whole. You need to make decisions with incomplete information. You need to deal with people, not just code. You need to take responsibility for outcomes that go beyond a single pull request. That is where the job is moving.</p>
<p>I still wake up at 2 AM sometimes.</p>
<p>The feeling is different now. It is not just worry. It is curiosity mixed with a bit of pressure. There is a version of this field where the people who adapt get to build things faster and at a scale that was not possible before.</p>
<p>We don't need 10x engineers anymore. We just need 1x engineers with 10x leverage.</p>
<p>There is also a version where you get left behind because you kept doing things the old way. I am trying to stay on the right side of that line.</p>
<p>The tools have changed. The expectations have changed. The core question has not:</p>
<p><em>What problems are worth solving, and how do you solve them well?</em></p>
]]></content:encoded></item><item><title><![CDATA[Hooked - How Habit-Forming Products Capture Our Attention]]></title><description><![CDATA[Hooked: How Habit-Forming Products Capture Our Attention
Nir Eyal's Hooked dives into the psychology behind the apps we can't seem to put down—from Facebook to Instagram and even Google. The book unpacks a simple yet powerful cycle that transforms or...]]></description><link>https://tanseersaji.com/hooked-how-habit-forming-products-capture-our-attention</link><guid isPermaLink="true">https://tanseersaji.com/hooked-how-habit-forming-products-capture-our-attention</guid><category><![CDATA[book review]]></category><category><![CDATA[Startups]]></category><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Tue, 04 Feb 2025 15:05:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741076246361/93eaf7e0-9c59-43cd-aeec-56d01e4af375.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Hooked: How Habit-Forming Products Capture Our Attention</strong></p>
<p>Nir Eyal's <em>Hooked</em> dives into the psychology behind the apps we can't seem to put down—from Facebook to Instagram and even Google. The book unpacks a simple yet powerful cycle that transforms ordinary products into habit-forming experiences.</p>
<p>At the core of every addictive app is a four-step loop:</p>
<ol>
<li><p><strong>Trigger:</strong> Everything begins with a prompt—a nudge that makes you think, "I should check this." Whether it's a notification or the subtle lure of FOMO (fear of missing out), triggers are the spark that kickstart our engagement.</p>
</li>
<li><p><strong>Action:</strong> Responding to that trigger, users take an action within the app. This might be scrolling through a feed or tapping on a new message. The action is typically simple enough to execute without much thought.</p>
</li>
<li><p><strong>Variable Reward:</strong> Unlike predictable rewards, variable rewards keep us guessing. Each action leads to a slightly different outcome, making the experience both exciting and unpredictable. This uncertainty taps into our brain’s reward system, compelling us to return again and again.</p>
</li>
<li><p><strong>Investment:</strong> Finally, users invest something—be it time, data, or effort. This investment not only enhances the product’s value but also sets the stage for future triggers. The more you invest, the deeper your engagement becomes.</p>
</li>
</ol>
<p>Eyal illustrates that by thoughtfully designing products around this cycle, creators can cultivate lasting habits that keep users coming back. In essence, <em>Hooked</em> is both a blueprint for building engaging technology and a cautionary tale of how easily our attention can be captured. Whether you're a product designer or a curious user, this book offers fascinating insights into the mechanics behind our digital addictions.</p>
]]></content:encoded></item><item><title><![CDATA[Basic web server implementation using inbuilt python tools]]></title><description><![CDATA[In my previous article, I talked about implementing the HTTP protocol over a standard TCP socket. Today, I will be using few libraries available in python that implements HTTP and try to build something like Flask web framework.
What is Flask Web Fra...]]></description><link>https://tanseersaji.com/basic-web-server-implementation-using-inbuilt-python-tools</link><guid isPermaLink="true">https://tanseersaji.com/basic-web-server-implementation-using-inbuilt-python-tools</guid><category><![CDATA[Python]]></category><category><![CDATA[web server]]></category><category><![CDATA[Flask Framework]]></category><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Wed, 03 Apr 2024 02:20:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741076453509/eaccf0de-3648-4071-8ede-a6a1407d6bff.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous article, I talked about implementing the HTTP protocol over a standard TCP socket. Today, I will be using few libraries available in python that implements HTTP and try to build something like Flask web framework.</p>
<h2 id="heading-what-is-flask-web-framework">What is Flask Web Framework</h2>
<p>Flask is a lightweight and versatile web framework for Python, designed to make building web applications simple and easy. It provides the tools and libraries needed to develop web applications quickly and efficiently, with minimal boilerplate code. Flask follows the WSGI (Web Server Gateway Interface) standard, making it compatible with a wide range of web servers. Its simplicity, flexibility, and extensive documentation have made it a popular choice among developers for creating web applications, APIs, and more.</p>
<p>Here’s an example of Flask code that we try to create using inbuilt libraries in Python.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template
<span class="hljs-keyword">import</span> os

PORT = os.getenv(<span class="hljs-string">'PORT'</span>)

app = Flask(__name__)

<span class="hljs-meta">@app.route('/', methods=["GET"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'index.html'</span>, context={
        <span class="hljs-string">"PORT"</span>: PORT
    })

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(port=PORT)
</code></pre>
<p>The <code>index.html</code> looks like this.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- File - index.py --&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is an HTTP server running of Port: {PORT}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<h2 id="heading-http-server-class">HTTP Server class</h2>
<p>Python provides basic functionalities to implement HTTP protocol under <code>http.server</code> module. We will using this as our base for our version of Flask.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - myflask.py</span>

<span class="hljs-keyword">import</span> http.server <span class="hljs-keyword">as</span> http_server

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyFlask</span>():</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, http_handler=http_server.SimpleHTTPRequestHandler</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        self.http_handler = http_handler

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span>(<span class="hljs-params">self, host=<span class="hljs-string">"localhost"</span>, port=<span class="hljs-number">3000</span></span>):</span>
        httpd = http_server.HTTPServer((host, port), self.http_handler)
        print(<span class="hljs-string">f"Running server at <span class="hljs-subst">{host}</span>:<span class="hljs-subst">{port}</span>"</span>)
        httpd.serve_forever()
</code></pre>
<p>Now let’s create a server file that import as uses <code>MyFlask</code> class.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask

app = MyFlask()

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run()
</code></pre>
<p>If you run main.py at this point, and open http://localhost:3000 you can see <code>index.html</code> getting rendered.</p>
<pre><code class="lang-bash">python3 main.py
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074626818/696d4368-1231-4430-841c-ca20fea7904c.png" alt="Basic implementation" /></p>
<p>Here <code>SimpleHTTPRequestHandler</code> simply rendered the current working directory and since <code>index.html</code> happens to be there, the server simply returned the contents of that file. If we rename index.html to something else then an <code>Index Of</code> page will be rendered.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074627921/c784f800-1c8b-4e22-8d43-8d9446941ce5.png" alt="Index of screen" /></p>
<h2 id="heading-building-routes">Building Routes</h2>
<p>What we have built works, but that only provides a simple static website server with no added security. We can change this behavior by implementing our own https handler. we can do this simply by defining a Http Request Handler class and passing it through to the <code>MyFlask</code> constructor</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run()
</code></pre>
<p>Now let’s define this <code>MyHttpRequestHandler</code> class.</p>
<h3 id="heading-structure-of-http-request-handler">Structure of HTTP Request Handler</h3>
<p>To implement a custom HTTP request handler from scratch, you would typically subclass the <code>SimpleHTTPRequestHandler</code> class from the <code>http.server</code> module. This allows you to define custom behavior for handling different types of HTTP requests, such as GET, POST, PUT, DELETE, etc.</p>
<p>You can handle more HTTP methods by implementing <code>do_{method}</code> method inside <code>MyHttpRequestHandler</code> class. For example, <code>do_POST</code>, <code>do_DELETE</code>, <code>do_PATCH</code>, etc.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask
<span class="hljs-keyword">from</span> http.server <span class="hljs-keyword">import</span> SimpleHTTPRequestHandler

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHttpRequestHandler</span>(<span class="hljs-params">SimpleHTTPRequestHandler</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">do_GET</span>(<span class="hljs-params">self</span>):</span>
        self.send_error(<span class="hljs-number">418</span>)

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074629146/f11bd091-5f8b-4c5f-b371-a4a74242d2f2.png" alt="Teapot 418 HTTP Error" /></p>
<p>The problem with this implementation is that the server will return HTTP error 418 no matter the page you try to visit.</p>
<p>We can easily implement routes by performing some pattern matching over the <code>self.path</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask
<span class="hljs-keyword">from</span> http.server <span class="hljs-keyword">import</span> SimpleHTTPRequestHandler

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHttpRequestHandler</span>(<span class="hljs-params">SimpleHTTPRequestHandler</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">do_GET</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.path == <span class="hljs-string">"/"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Hello World&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run()
</code></pre>
<p>You might find the order I wrote the command inside <code>do_GET</code> kind of similar to the HTTP Response format we discussed in our <a target="_blank" href="https://idiomaticprogrammers.com/post/create-http-server-from-scratch/">Create HTTP server from Scratch</a> article.</p>
<pre><code class="lang-plaintext">HTTP/1.1 200 OK
Content-Type text/html

&lt;p&gt;Hello World&lt;/p&gt;
</code></pre>
<p>First we sent the response code which is <code>200</code> in this case. Then we list all our headers, in this case just <code>Content-Type</code> and once we listed all the required headers we mark the end of headers using <code>self.end_headers()</code> and finally we write the body and encoded it as bytes.</p>
<p>If you want to support another page, we can simply add another pattern matching.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask
<span class="hljs-keyword">from</span> http.server <span class="hljs-keyword">import</span> SimpleHTTPRequestHandler

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHttpRequestHandler</span>(<span class="hljs-params">SimpleHTTPRequestHandler</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">do_GET</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.path == <span class="hljs-string">"/"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Hello World&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">elif</span> self.path == <span class="hljs-string">"/page1"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Rendering Page 1&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074630902/89e60301-664b-45aa-8d6b-add84f8ce0c7.jpeg" alt="Custom Routes" /></p>
<h3 id="heading-handling-html-template-expressions">Handling HTML template expressions</h3>
<p>Now finally let’s do some context filling something like we do in Flask.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask
<span class="hljs-keyword">from</span> http.server <span class="hljs-keyword">import</span> SimpleHTTPRequestHandler

<span class="hljs-keyword">import</span> os

PORT = (os.getenv(<span class="hljs-string">'PORT'</span>) <span class="hljs-keyword">or</span> <span class="hljs-number">3000</span>) <span class="hljs-comment"># port 3000 by default</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHttpRequestHandler</span>(<span class="hljs-params">SimpleHTTPRequestHandler</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">do_GET</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.path == <span class="hljs-string">"/"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Hello World&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">elif</span> self.path == <span class="hljs-string">"/page1"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Rendering Page 1&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">elif</span> self.path == <span class="hljs-string">"/port"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            res_body = open(<span class="hljs-string">'index.html'</span>,<span class="hljs-string">"r"</span>).read().format_map({
                    <span class="hljs-string">"PORT"</span>:PORT
            })
            self.wfile.write(res_body.encode()) <span class="hljs-comment"># HTTP body</span>

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(port=PORT)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074631981/69d3d8e3-7025-4a4f-a4ca-faa9715e1596.png" alt="HTML Template" /></p>
<h3 id="heading-managing-error-codes">Managing Error codes</h3>
<p>Final missing piece in our HTTP server puzzle is managing different error codes. In <code>SimpleHTTPRequestHandler</code> there is a method called <code>send_error()</code> this is used send an error code to the client. We have used this method in the beginning before we implemented the route.</p>
<pre><code class="lang-python"><span class="hljs-comment"># File - main.py</span>

<span class="hljs-keyword">from</span> myflask <span class="hljs-keyword">import</span> MyFlask
<span class="hljs-keyword">from</span> http.server <span class="hljs-keyword">import</span> SimpleHTTPRequestHandler

<span class="hljs-keyword">import</span> os

PORT = (os.getenv(<span class="hljs-string">'PORT'</span>) <span class="hljs-keyword">or</span> <span class="hljs-number">3000</span>) <span class="hljs-comment"># port 3000 by default</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHttpRequestHandler</span>(<span class="hljs-params">SimpleHTTPRequestHandler</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">do_GET</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.path == <span class="hljs-string">"/"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Hello World&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">elif</span> self.path == <span class="hljs-string">"/page1"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            self.wfile.write(<span class="hljs-string">"&lt;p&gt;Rendering Page 1&lt;/p&gt;"</span>.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">elif</span> self.path == <span class="hljs-string">"/port"</span>:
            self.send_response(<span class="hljs-number">200</span>) <span class="hljs-comment"># Send HTTP code</span>
            self.send_header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/html"</span>) <span class="hljs-comment"># Send Headers</span>
            self.end_headers() <span class="hljs-comment"># Mark the end of Headers</span>
            res_body = open(<span class="hljs-string">'index.html'</span>,<span class="hljs-string">"r"</span>).read().format_map({
                    <span class="hljs-string">"PORT"</span>:PORT
            })
            self.wfile.write(res_body.encode()) <span class="hljs-comment"># HTTP body</span>
        <span class="hljs-keyword">else</span>:
            self.send_error(<span class="hljs-number">404</span>)

app = MyFlask(MyHttpRequestHandler)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(port=PORT)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074633149/bceb6768-fea9-48ea-b806-d2aa83367fcf.png" alt="Error 404 Page" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, while implementing a custom HTTP request handler can provide valuable insight into how web servers operate and how frameworks like Flask, Jinja, or Django function under the hood, for most practical purposes, using the <code>SimpleHTTPRequestHandler</code> provided by the <code>http.server</code> module is often the better choice.</p>
<p>The <code>SimpleHTTPRequestHandler</code> is ideal for testing, prototyping, and learning purposes due to its simplicity and ease of use. It allows for quick setup of a basic HTTP server that can serve static files and handle simple GET requests. Moreover, it provides a straightforward platform for experimenting with web development concepts without the added complexity of implementing a custom request handler.</p>
<p>However, it's important to note that while the <code>SimpleHTTPRequestHandler</code> is suitable for testing and learning, it is not the optimal solution for a production-ready server. Production environments typically require more advanced features such as security, scalability, performance optimization, and support for various HTTP methods beyond just GET requests. In such cases, using a mature and feature-rich web framework like Flask, Jinja, or Django, which are specifically designed for building robust web applications, would be the recommended approach.</p>
<h2 id="heading-reference">Reference</h2>
<ol>
<li><p>https://docs.python.org/3/library/http.server.html</p>
</li>
<li><p>https://github.com/python/cpython/blob/main/Doc/library/http.server.rst</p>
</li>
<li><p>https://http.dev/418</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Create HTTP server from Scratch]]></title><description><![CDATA[I was testing some NGINX config files last night when I started to wonder how NGINX understands it all? Somehow this curiosity inspired me to go down the rabbit hole to understand the inner workings of HTTP. What I found was a relatively uncomplicate...]]></description><link>https://tanseersaji.com/create-http-server-from-scratch</link><guid isPermaLink="true">https://tanseersaji.com/create-http-server-from-scratch</guid><category><![CDATA[Python]]></category><category><![CDATA[web servers]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[socket]]></category><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Wed, 20 Mar 2024 15:47:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741076485457/a9b4d99a-2b4b-41ff-b2d7-e2687a1b5cb8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was testing some NGINX config files last night when I started to wonder how NGINX understands it all? Somehow this curiosity inspired me to go down the rabbit hole to understand the inner workings of HTTP. What I found was a relatively uncomplicated sets of rules that all web servers abide by. In this blog, I’ll try to explain what I understood from HTTP and build a simple HTTP server from scratch in Python.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>My goal is to create a web server which accepts a POST request and it will echo back whatever JSON body it receives. Let’s start by understanding what HTTP is.</p>
<p>HTTP or HyperText Transfer Protocol are a set of rules that regulate the transfer of hypertext files such as HTML, media file, text, json, XML, etc. ensuring the clients and servers understand each other.</p>
<h2 id="heading-an-overview-of-http">An Overview of HTTP</h2>
<p>HTTP is a protocol that was built on top of TCP or Transmission Control Protocol which is used to connect two computers and exchange data stream across the network. TCP’s role is to ensure data are reliably delivered from source to destination computer.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1710950250/Idiomatic%20Programmers/create-http-server-from-scratch/Untitled.png" alt="Source: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)" /></p>
<p>Source: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview">https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview</a></p>
<p>In most cases two computers or programs connected via HTTP works in a client-server configuration where there will be multiple clients such as Web Browsers, Terminals, etc. are connected to a server. The message sent by client are called <strong>Requests</strong> and the message sent by the server as an answer is called <strong>Responses</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074474104/2789d0a0-ccbf-4a4a-bdf6-9891ef986d3d.png" alt="HTTP Architecture" /></p>
<h2 id="heading-http-message-format">HTTP message Format</h2>
<p>Before we jump into building our HTTP server from scratch, we need to understand how we should format our messages so that it becomes a valid HTTP request or response.</p>
<h3 id="heading-http-requests">HTTP Requests</h3>
<p>A valid HTTP request contains three sections, a request line, headers and request body.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074475574/39fa155b-5c4d-4520-9238-8ecce23bbe44.png" alt="HTTP Request format" /></p>
<ol>
<li><strong>Request Line</strong>: This is the very first line of a HTTP request, this specifies the method we want to use such as GET, POST, PUT, etc. The actual URL or route we need to access in the server and the version of HTTP standard we are using. These days, most servers use either HTTP version 2 or HTTP version 3. But for our simple HTTP server we will be building for HTTP version 1.1 which is the simplest server we can build.</li>
<li><strong>Headers</strong>: Headers are used to convey some additional information for the server such as who is the Host of the request, where did the request originate from what is the user agent, etc.</li>
<li><strong>Body</strong>: A body contains the actual message we want to send the server. A body is only useful for some methods such as POST, PUT or PATCH and not required of methods such as GET, DELETE, etc.</li>
</ol>
<h3 id="heading-http-response">HTTP Response</h3>
<p>Similar to request, HTTP response also contains three sections. A Response line, Headers and Body.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074477231/f9b6b894-b4c3-4b81-9f9b-1be596aefb63.png" alt="HTTP Response format" /></p>
<ol>
<li><strong>Request Line</strong>: This is the very first line of a HTTP response, this the HTTP version used for the request, a status code such as 200 for success, 500 for server error, 404 for page not found, etc. And an optional phrase that accompanies the status code.</li>
<li><strong>Headers</strong>: Headers are used to convey some additional information for the client such as who is the Content Type of the response, total length of the message, etc.</li>
<li><strong>Body</strong>: The body contains the response that the server wants to send the client.</li>
</ol>
<h2 id="heading-python-implementation">Python Implementation</h2>
<p>Finally, we can start building a simple HTTP server in python using only the builtin libraries. We will be using the <code>socket</code> library which provides interfaces to open and manage a TCP connection. Since HTTP is a protocol built on top of TCP this should be an appropriate starting point for us.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket
server = socket.socket()
</code></pre>
<p>With these two lines we can instantiate a simple TCP socket, now we need to provide a host and a port so that we can start listening to it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    server.bind((<span class="hljs-string">'localhost'</span>,<span class="hljs-number">4000</span>))
    server.listen()
    print(<span class="hljs-string">"Server ready at localhost:4000"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    server.close()
<span class="hljs-keyword">finally</span>:
    server.close()
</code></pre>
<p>This will create a simple TCP server that listens to every message that is sent to <code>localhost</code> port <code>4000</code>. Now as long as our program is listening to <code>localhost</code> port <code>4000</code>, no other program can listen to it. Because of this reason, we have enclosed everything inside a try-except-finally block to ensure that we release the port in case something goes wrong.</p>
<p>At this stage, even though our program is listening to the TCP connection we have nothing in place to actually accept a connection from a client and read the message it wants to send us. Let’s do that now.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    server.bind((<span class="hljs-string">'localhost'</span>,<span class="hljs-number">4000</span>))
    server.listen()
    print(<span class="hljs-string">"Server ready at localhost:4000"</span>)

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-comment"># Accept a connection</span>
        (clientsocket, address) = server.accept()
        print(<span class="hljs-string">f"Connected to <span class="hljs-subst">{address}</span>"</span>)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    server.close()
<span class="hljs-keyword">finally</span>:
    server.close()
</code></pre>
<p>Note that the main motivation behind this article is understanding and building a simple HTTP server, not a secure one. With that being said, we made an infinite while loop inside which we accept an incoming connection. <code>server.accept</code>  wait for an incoming connection.  Return a new socket representing the connection, and the address of the client.</p>
<blockquote>
<p>On a side note, I have a huge OCD about nesting my code, so like to create a lot of helper functions that will help me avoid nested code as much as possible.</p>
</blockquote>
<p>Let’s create a helper function that will read all the data that the client has sent us.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_all_request_data</span>(<span class="hljs-params">clientsocket: socket.socket</span>)-&gt;bytes:</span>
    data = <span class="hljs-string">b''</span>
  <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
      <span class="hljs-keyword">try</span>:
        temp_data = clientsocket.recv(<span class="hljs-number">4096</span>, socket.MSG_DONTWAIT)
      data += temp_data
    <span class="hljs-keyword">except</span> BlockingIOError <span class="hljs-keyword">as</span> e:
      <span class="hljs-keyword">break</span>
  <span class="hljs-keyword">return</span> data
</code></pre>
<p>Let breakdown this function:</p>
<ol>
<li>We passed in the <code>clientsocket</code> object which we received from <code>server.accept()</code> from previous step.</li>
<li>We created another infinite loop that reads the data that client sent the server in chunks of 4096 bytes using <code>clientsocket.recv(4096, socket.MSG_DONTWAIT)</code>. By default <code>socket.recv</code> is a blocking function. Which means that it will wait for more data even if the client has sent everything. This might me useful for some use cases but we do not need this behaviour. So to override this, we used the flag <code>socket.MSG_DONTWAIT</code>. Adding this flag will raise a <code>BlockingIOError</code> when there is no more data to be read.</li>
<li>Throughout the while loop, we read the data in chunks and append it to a <code>data</code> variable and finally returned this variable.</li>
</ol>
<p>Let’s use the helper function we created to fetch client TCP data in our server.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    server.bind((<span class="hljs-string">'localhost'</span>,<span class="hljs-number">4000</span>))
    server.listen()
    print(<span class="hljs-string">"Server ready at localhost:4000"</span>)

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-comment"># Accept a connection</span>
        (clientsocket, address) = server.accept()
        print(<span class="hljs-string">f"Connected to <span class="hljs-subst">{address}</span>"</span>)

        <span class="hljs-keyword">try</span>:
        data = get_all_request_data(clientsocket)
        print(<span class="hljs-string">"Received:"</span>)
      print(data.decode())
      print(<span class="hljs-string">"--------------------------"</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        clientsocket.close()
    <span class="hljs-keyword">finally</span>:
      clientsocket.close()
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    server.close()
<span class="hljs-keyword">finally</span>:
    server.close()
</code></pre>
<p>At this point if you run the server and perform a curl request like so.</p>
<pre><code class="lang-bash">curl localhost:4000
</code></pre>
<p>You can see the raw HTTP request printed in your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074479131/ce320c9a-12f7-49b7-a4df-36f860ea512f.png" alt="Raw HTTP request" /></p>
<p>Now let’s make a class that would help us define valid HTTP request and response.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Request</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, req_data: bytes</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        lines = req_data.split(<span class="hljs-string">b'\r\n'</span>)
        raw_request_line = lines[<span class="hljs-number">0</span>].decode().split(<span class="hljs-string">" "</span>)
        self.method = raw_request_line[<span class="hljs-number">0</span>].strip()
        self.request_url = raw_request_line[<span class="hljs-number">1</span>].strip()
        self.http_version = raw_request_line[<span class="hljs-number">2</span>].strip()
        self.headers = {}
        <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> lines[<span class="hljs-number">1</span>:<span class="hljs-number">-1</span>]:
            <span class="hljs-keyword">if</span> len(line) == <span class="hljs-number">0</span>:
                <span class="hljs-keyword">continue</span>
            line = line.decode().split(<span class="hljs-string">":"</span>)
            self.headers[line[<span class="hljs-number">0</span>].strip()] = line[<span class="hljs-number">1</span>].strip()

        self.raw_message = lines[<span class="hljs-number">-1</span>].decode()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_response</span>(<span class="hljs-params">self, 
                    data: bytes, 
                    status_code: int = <span class="hljs-number">200</span>, 
                    content_type: str = <span class="hljs-string">'text/plain'</span></span>) -&gt; bytes:</span>
        response = <span class="hljs-string">b''</span>
        response += <span class="hljs-string">f'<span class="hljs-subst">{self.http_version}</span> <span class="hljs-subst">{status_code}</span>\r\n'</span>.encode()
        response += <span class="hljs-string">f"Content-Type: <span class="hljs-subst">{content_type}</span>\r\n"</span>.encode()
        response += <span class="hljs-string">f"Content-Length: <span class="hljs-subst">{len(data)}</span>\r\n"</span>.encode()
        response += <span class="hljs-string">b'\r\n'</span>
        response += data
        <span class="hljs-keyword">return</span> response
</code></pre>
<p>This class simply does some string manipulation to parse the request data from client based on the HTTP Request format that we discussed earlier. And similarly creates an HTTP response based on the HTTP Response format we discussed.</p>
<p>Let’s put this all together and build a simple HTTP server.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    server.bind((<span class="hljs-string">'localhost'</span>,<span class="hljs-number">4000</span>))
    server.listen()
    print(<span class="hljs-string">"Server ready at localhost:4000"</span>)

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-comment"># Accept a connection</span>
        (clientsocket, address) = server.accept()
        print(<span class="hljs-string">f"Connected to <span class="hljs-subst">{address}</span>"</span>)

        <span class="hljs-keyword">try</span>:
        data = get_all_request_data(clientsocket)
        print(<span class="hljs-string">"Received:"</span>)
        print(data.decode())
        print(<span class="hljs-string">"--------------------------"</span>)

      request = Request(data)

      response = request.get_response(
                            <span class="hljs-string">b'&lt;h1&gt;Welcome to my Server&lt;/h1&gt;'</span>, 
                            content_type=<span class="hljs-string">'text/html'</span>)
      print(<span class="hljs-string">"Sending:"</span>)
      print(response.decode())
      print(<span class="hljs-string">"--------------------------"</span>)

      clientsocket.send(response)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        clientsocket.close()
    <span class="hljs-keyword">finally</span>:
      clientsocket.close()
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    server.close()
<span class="hljs-keyword">finally</span>:
    server.close()
</code></pre>
<p><code>clientsocket.send(response)</code> will send the HTTP formatted response back to the client. Now that we are able to send and receive valid HTTP messages, we can open <code>http://localhost:4000</code> on our browser and see <code>&lt;h1&gt;Welcome to my Server&lt;/h1&gt;</code> rendered.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074480113/ed525f4d-93e1-43d9-8409-29d363b3dbcc.png" alt="Browser output" /></p>
<p>Finally we can build our echo server, an echo server simply returns whatever message you send.</p>
<h3 id="heading-final-code">Final Code</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket
<span class="hljs-keyword">import</span> traceback

PORT = <span class="hljs-number">4000</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Request</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, req_data: bytes</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        lines = req_data.split(<span class="hljs-string">b'\r\n'</span>)
        raw_request_line = lines[<span class="hljs-number">0</span>].decode().split(<span class="hljs-string">" "</span>)
        self.method = raw_request_line[<span class="hljs-number">0</span>].strip()
        self.request_url = raw_request_line[<span class="hljs-number">1</span>].strip()
        self.http_version = raw_request_line[<span class="hljs-number">2</span>].strip()
        self.headers = {}
        <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> lines[<span class="hljs-number">1</span>:<span class="hljs-number">-1</span>]:
            <span class="hljs-keyword">if</span> len(line) == <span class="hljs-number">0</span>:
                <span class="hljs-keyword">continue</span>
            line = line.decode().split(<span class="hljs-string">":"</span>)
            self.headers[line[<span class="hljs-number">0</span>].strip()] = line[<span class="hljs-number">1</span>].strip()

        self.raw_message = lines[<span class="hljs-number">-1</span>].decode()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_response</span>(<span class="hljs-params">self, 
                    data: bytes, 
                    status_code: int = <span class="hljs-number">200</span>, 
                    content_type: str = <span class="hljs-string">'text/plain'</span></span>):</span>
        response = <span class="hljs-string">b''</span>
        response += <span class="hljs-string">f'<span class="hljs-subst">{self.http_version}</span> <span class="hljs-subst">{status_code}</span>\r\n'</span>.encode()
        response += <span class="hljs-string">f"Content-Type: <span class="hljs-subst">{content_type}</span>\r\n"</span>.encode()
        response += <span class="hljs-string">f"Content-Length: <span class="hljs-subst">{len(data)}</span>\r\n"</span>.encode()
        response += <span class="hljs-string">b'\r\n'</span>
        response += data
        <span class="hljs-keyword">return</span> response

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_all_request_data</span>(<span class="hljs-params">clientsocket: socket.socket</span>)-&gt;bytes:</span>
    data = <span class="hljs-string">b''</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">try</span>:
            temp_data = clientsocket.recv(<span class="hljs-number">4096</span>, socket.MSG_DONTWAIT)
            data += temp_data
        <span class="hljs-keyword">except</span> BlockingIOError <span class="hljs-keyword">as</span> e:
            <span class="hljs-keyword">break</span>
    <span class="hljs-keyword">return</span> data

server = socket.socket()
<span class="hljs-keyword">try</span>:
    server.bind((<span class="hljs-string">'localhost'</span>, PORT))
    server.listen()
    print(<span class="hljs-string">f"Server running at port <span class="hljs-subst">{PORT}</span>"</span>)

    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        (clientsocket, address) = server.accept()
        print(<span class="hljs-string">f"Connected to <span class="hljs-subst">{address}</span>"</span>)

        <span class="hljs-keyword">try</span>:
            data = get_all_request_data(clientsocket)
            print(<span class="hljs-string">"Received:"</span>)
            print(data.decode())
            print(<span class="hljs-string">"--------------------------"</span>)

            request = Request(data)
            allowed_methods = [<span class="hljs-string">"GET"</span>, <span class="hljs-string">"POST"</span>]
            status_code = <span class="hljs-number">200</span> <span class="hljs-keyword">if</span> request.method <span class="hljs-keyword">in</span> allowed_methods <span class="hljs-keyword">else</span> <span class="hljs-number">405</span>

            <span class="hljs-keyword">if</span> status_code != <span class="hljs-number">200</span>:
                response = request.get_response(
                    <span class="hljs-string">f"<span class="hljs-subst">{request.method}</span> NOT Allowed"</span>.encode(), 
                    status_code=status_code)
            <span class="hljs-keyword">else</span>:
                <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">"POST"</span>:
                    content_type = request.headers.get(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'plain/text'</span>)
                    response = request.get_response(
                        request.raw_message.encode(), 
                        content_type=content_type)
                <span class="hljs-keyword">else</span>:
                    response = request.get_response(
                        <span class="hljs-string">b'&lt;h1&gt;Welcome to my Server&lt;/h1&gt;'</span>, 
                        content_type=<span class="hljs-string">'text/html'</span>)
            print(<span class="hljs-string">"Sending:"</span>)
            print(response.decode())
            print(<span class="hljs-string">"--------------------------"</span>)
            clientsocket.send(response)
        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            clientsocket.close()
        <span class="hljs-keyword">finally</span>:
            clientsocket.close()
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    server.close()
<span class="hljs-keyword">finally</span>:
    server.close()
</code></pre>
<p>And here's the output</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074481862/f13c2224-897b-44c7-9410-b12149b4a19d.png" alt="Custom server output" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Even though what we build in this article works fine, this is no way production ready. There are obviously a lot of potential for future improvements such as can we set this up to search HTML files, manage routes, manage error code.</p>
<p>We can also explore on how to use TLS encryption and make our server compatible with HTTPS standard. Or maybe implement newer version of HTTP like version HTTP/2 or HTTP/3.</p>
<p>The possibilities are endless.</p>
<h2 id="heading-references">References</h2>
<p>Majority of the information I got about how HTTP works from are from two sources.</p>
<ol>
<li>The official HTTP document from W3C (<a target="_blank" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">https://www.w3.org/Protocols/rfc2616/rfc2616.html</a>)</li>
<li>MDN web docs: An Overview of HTTP (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview">https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview</a>)</li>
<li>Debian recv system call manual (<a target="_blank" href="https://manpages.debian.org/bookworm/manpages-dev/recv.2.en.html">https://manpages.debian.org/bookworm/manpages-dev/recv.2.en.html</a>)</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Introduction to C++ Part 1]]></title><description><![CDATA[What is C++?
C++ is a versatile and powerful programming language that was developed as an extension of the C programming language. It combines procedural, object-oriented, and generic programming paradigms, making it suitable for a wide range of app...]]></description><link>https://tanseersaji.com/introduction-to-c-part-1</link><guid isPermaLink="true">https://tanseersaji.com/introduction-to-c-part-1</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Fri, 07 Jul 2023 08:59:08 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-c">What is C++?</h2>
<p>C++ is a versatile and powerful programming language that was developed as an extension of the C programming language. It combines procedural, object-oriented, and generic programming paradigms, making it suitable for a wide range of applications. C++ allows programmers to write efficient and high-performance code, making it a popular choice for system programming, game development, embedded systems, and more.</p>
<h3 id="heading-brief-history-and-evolution-of-c">Brief History and Evolution of C++</h3>
<p>C++ has a fascinating history that spans several decades. Let's take a brief look at its evolution:</p>
<ol>
<li><p>Origins in C: In the early 1970s, Dennis Ritchie developed the C programming language at Bell Labs. C quickly gained popularity due to its simplicity and portability, becoming a lingua franca for software development.</p>
</li>
<li><p>C with Classes: In the late 1970s, Bjarne Stroustrup, a Danish computer scientist, began working on extending the C language to support object-oriented programming. The result was "C with Classes," which introduced the concept of classes, derived classes, and other fundamental aspects of OOP.</p>
</li>
<li><p>C++ Emerges: In 1983, Stroustrup renamed "C with Classes" to C++, signifying its evolutionary nature. The "++" symbol represents an increment, indicating improvements over the C language. Stroustrup added features like virtual functions, function overloading, and operator overloading, cementing C++ as a distinct language.</p>
</li>
<li><p>Standardization Efforts: As C++ gained popularity, the need for a standardized version became evident. The first C++ standard, known as C++98 or C++03, was published in 1998. Subsequent revisions, including C++11, C++14, C++17, and C++20, introduced numerous enhancements and modern features to the language.</p>
</li>
<li><p>Features and Advancements: Over the years, C++ has evolved to provide a wide range of features, including templates, exceptions, namespaces, the Standard Template Library (STL), lambdas, and more. These advancements have significantly enhanced the expressiveness, productivity, and performance of C++ programs.</p>
</li>
<li><p>C++ in Modern Times: Today, C++ continues to be widely used and actively developed. The language maintains compatibility with C, allowing seamless integration with existing C codebases. It also offers extensive support across different platforms and compilers.</p>
</li>
</ol>
<p>C++ is a powerful programming language that builds upon the foundation of C while introducing key concepts of object-oriented programming. Its evolution from C with Classes to a standardized language has solidified its position as a versatile choice for developing complex software systems. In the next sections of this article, we will delve deeper into the syntax, features, and best practices of C++, empowering you to leverage its potential to the fullest.</p>
<h2 id="heading-setting-up-clion-ide">Setting up CLion IDE</h2>
<p>CLion is a powerful Integrated Development Environment (IDE) specifically designed for C++ development. In this article, we will guide you through the steps to set up CLion, so you can start writing C++ code efficiently. By the end of this guide, you'll have CLion installed and configured for your C++ projects.</p>
<ol>
<li><p>Installing CLion:</p>
<ul>
<li>Visit the JetBrains CLion website (<a target="_blank" href="https://www.jetbrains.com/clion/">https://www.jetbrains.com/clion/</a>) and download the appropriate version for your operating system.</li>
<li>Run the installer and follow the on-screen instructions to complete the installation process.</li>
<li>Launch CLion after the installation is complete.</li>
</ul>
</li>
<li><p>Configuring CLion:</p>
<ul>
<li>On the welcome screen, you can select "Do not import settings" if this is your first time using CLion or choose to import settings if you have a previous configuration you'd like to bring in.</li>
<li>Set up the Keymap preferences by selecting your preferred keymap scheme or customizing the key bindings according to your needs.</li>
<li>Configure the Appearance settings, including the theme, fonts, and colour scheme, to your liking.</li>
</ul>
</li>
<li><p>Creating a New C++ Project:</p>
<ul>
<li>Click on "Create New Project" or select "New Project" from the "File" menu.</li>
<li>In the project template selection window, choose "C++ Executable" or any other relevant template that suits your project requirements.</li>
<li>Specify the project name, location, and other necessary details. Click "Create" to create the project.</li>
</ul>
</li>
<li><p>Setting Up the Compiler:</p>
<ul>
<li>CLion typically comes bundled with JetBrains' custom C++ compiler, which provides a seamless development experience.</li>
<li>If you prefer using a different compiler, such as GCC or Clang, you can configure it in CLion's settings:<ul>
<li>Go to "File" -&gt; "Settings" (or "Preferences" on macOS).</li>
<li>Navigate to "Build, Execution, Deployment" -&gt; "Toolchains".</li>
<li>Click on the "+" button to add a new toolchain and select your preferred compiler.</li>
<li>Provide the necessary details and paths for the compiler installation and click "OK".</li>
</ul>
</li>
</ul>
</li>
<li><p>Configuring the Build System:</p>
<ul>
<li>CLion utilizes the CMake build system by default. CMake allows for easy project configuration and generation of build files.</li>
<li>CLion automatically detects CMakeLists.txt files in your project directory and configures the build system accordingly.</li>
<li>Modify the CMakeLists.txt file as per your project requirements, such as adding source files, libraries, and compiler flags.</li>
</ul>
</li>
<li><p>Building and Running a C++ Program:</p>
<ul>
<li>Open the main C++ source file in the CLion editor.</li>
<li>To build the project, click on the "Build" button or use the "Build" -&gt; "Build Project" option.</li>
<li>Once the build process completes without errors, you can run the program by clicking on the "Run" button or using the "Run" -&gt; "Run" option.</li>
<li>CLion provides a built-in debugger to help you with debugging your C++ programs. You can set breakpoints, step through code, and inspect variables during runtime.</li>
</ul>
</li>
</ol>
<h2 id="heading-basic-syntax-and-structure">Basic Syntax and Structure</h2>
<p>Understanding the basic syntax and structure of a programming language is fundamental to getting started with any programming endeavour. In this article, we will explore the core elements of C++, including the Hello World program, data types and variables, operators and expressions, control structures, and functions. By the end of this guide, you will have a solid foundation in C++ syntax and be able to write simple programs.</p>
<h3 id="heading-hello-world-program-in-c">Hello World program in C++</h3>
<p>The traditional Hello World program is a simple yet essential starting point for learning any programming language. In C++, it looks like this:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Hello, World!"</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<ul>
<li>Explanation:<ul>
<li><code>#include &lt;iostream&gt;</code>: This line includes the input/output stream library, which allows us to work with input and output operations in C++.</li>
<li><code>int main()</code>: Every C++ program must have a <code>main()</code> function as its entry point.</li>
<li><code>std::cout &lt;&lt; "Hello, World!" &lt;&lt; std::endl;</code>: The <code>std::cout</code> statement is used to display output to the console. In this case, it prints "Hello, World!".</li>
<li><code>return 0;</code>: The <code>return</code> statement ends the <code>main()</code> function and returns a value (0 in this case) to indicate successful execution.</li>
</ul>
</li>
</ul>
<h3 id="heading-data-types-and-variables">Data types and variables</h3>
<p>C++ provides several built-in data types to represent different kinds of values. Here are some commonly used data types:</p>
<ul>
<li><code>int</code>: Represents integer values.</li>
<li><code>float</code> and <code>double</code>: Represent floating-point (decimal) values with single and double precision, respectively.</li>
<li><code>char</code>: Represents a single character.</li>
<li><code>bool</code>: Represents boolean values (<code>true</code> or <code>false</code>).</li>
</ul>
<p>Variables are used to store and manipulate data. Here's an example of declaring and using variables:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> age = <span class="hljs-number">25</span>;
<span class="hljs-keyword">float</span> pi = <span class="hljs-number">3.14159</span>;
<span class="hljs-keyword">char</span> grade = <span class="hljs-string">'A'</span>;
<span class="hljs-keyword">bool</span> isStudent = <span class="hljs-literal">true</span>;
</code></pre>
<ul>
<li>Explanation:<ul>
<li>The <code>int</code>, <code>float</code>, <code>char</code>, and <code>bool</code> keywords are used to declare variables of the corresponding data types.</li>
<li>The <code>=</code> symbol is used for initialization, assigning a value to a variable.</li>
<li>Variables can be named according to your preference, but they must follow certain naming conventions and avoid reserved keywords.</li>
</ul>
</li>
</ul>
<h3 id="heading-operators-and-expressions">Operators and expressions</h3>
<p>Operators allow us to perform various operations on variables and values. Here are some common operators in C++:</p>
<ul>
<li>Arithmetic operators: <code>+</code>, <code>,</code>, <code>/</code>, <code>%</code> (addition, subtraction, multiplication, division, modulo)</li>
<li>Relational operators: <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>, <code>&gt;=</code> (equality, inequality, less than, greater than, less than or equal to, greater than or equal to)</li>
<li>Logical operators: <code>&amp;&amp;</code>, <code>||</code>, <code>!</code> (logical AND, logical OR, logical NOT)</li>
<li>Assignment operator: <code>=</code></li>
<li>Increment and decrement operators: <code>++</code>, <code>-</code></li>
</ul>
<p>Expressions combine variables, values, and operators to produce results. Here's an example:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">int</span> x = <span class="hljs-number">5</span>;
<span class="hljs-keyword">int</span> y = <span class="hljs-number">10</span>;
<span class="hljs-keyword">int</span> z = x + y;  <span class="hljs-comment">// z will be 15</span>
</code></pre>
<ol>
<li><strong>Control structures (if-else, loops):</strong>
Control structures allow us to control the flow of execution in a program. Here are two common control structures in C++:</li>
<li><p><strong>if-else statement:</strong></p>
<pre><code class="lang-cpp">  <span class="hljs-keyword">int</span> x = <span class="hljs-number">5</span>;
  <span class="hljs-keyword">if</span> (x &gt; <span class="hljs-number">10</span>) {
      <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"x is greater than 10"</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
  } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"x is less than or equal to 10"</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
  }
</code></pre>
</li>
<li><p><strong>loops (for loop):</strong></p>
<pre><code class="lang-cpp">  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">5</span>; i++) {
      <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; i &lt;&lt; <span class="hljs-string">" "</span>;
  }
  <span class="hljs-comment">// Output: 1 2 3 4 5</span>
</code></pre>
</li>
<li><p>Explanation:</p>
<ul>
<li>In the if-else statement, the condition inside the parentheses determines which block of code to execute based on the result.</li>
<li>The for loop consists of three parts: initialization, condition, and increment. It repeatedly executes the code block until the condition becomes false.</li>
</ul>
</li>
</ol>
<h3 id="heading-functions-and-procedures">Functions and procedures</h3>
<p>Functions are reusable blocks of code that perform specific tasks. They are essential for organizing and modularizing code. Here's an example:</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
    <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-keyword">int</span> result = add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
<span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Result: "</span> &lt;&lt; result &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
</code></pre>
<ul>
<li>Explanation:<ul>
<li>The <code>add()</code> function takes two integer parameters (<code>a</code> and <code>b</code>) and returns their sum.</li>
<li>The <code>result</code> variable stores the returned value from the <code>add()</code> function call.</li>
<li>The <code>std::cout</code> statement displays the result on the console.</li>
</ul>
</li>
</ul>
<h2 id="heading-object-oriented-programming-oop-concepts">Object-Oriented Programming (OOP) Concepts</h2>
<p>Object-Oriented Programming (OOP) is a powerful paradigm that allows us to organize code in a modular and reusable manner. In this article, we will explore key OOP concepts in C++, including classes and objects, encapsulation, inheritance, polymorphism, constructors and destructors, access specifiers, and function overloading and overriding. Through code snippets and explanations, we will gain a solid understanding of these fundamental concepts.</p>
<h3 id="heading-classes-and-objects">Classes and Objects:</h3>
<ul>
<li>Classes serve as blueprints for creating objects in C++.</li>
<li>A class defines the properties (data members) and behaviors (member functions) of an object.</li>
<li>Here's an example of a simple class in C++:</li>
</ul>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> {</span>
    <span class="hljs-keyword">int</span> width;
    <span class="hljs-keyword">int</span> height;

<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setDimensions</span><span class="hljs-params">(<span class="hljs-keyword">int</span> w, <span class="hljs-keyword">int</span> h)</span> </span>{
        width = w;
        height = h;
    }

    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
};
</code></pre>
<h3 id="heading-encapsulation-inheritance-and-polymorphism">Encapsulation, Inheritance, and Polymorphism:</h3>
<ul>
<li>Encapsulation is the practice of bundling data and the functions that operate on that data into a single unit (a class).</li>
<li>Inheritance allows the creation of new classes (derived classes) from existing ones (base classes), inheriting their properties and behaviors.</li>
<li>Polymorphism enables objects of different classes to be treated as objects of a common base class, facilitating code reusability and flexibility.</li>
<li>Here's an example demonstrating these concepts:</li>
</ul>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> {</span>
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">makeSound</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"The animal makes a sound.\\n"</span>;
    }
};

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> :</span> <span class="hljs-keyword">public</span> Animal {
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">makeSound</span><span class="hljs-params">()</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"The dog barks.\\n"</span>;
    }
};

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> :</span> <span class="hljs-keyword">public</span> Animal {
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">makeSound</span><span class="hljs-params">()</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"The cat meows.\\n"</span>;
    }
};
</code></pre>
<h3 id="heading-constructors-and-destructors">Constructors and Destructors:</h3>
<ul>
<li>Constructors are special member functions used to initialize objects of a class.</li>
<li>Destructors are used to perform cleanup tasks when an object goes out of scope or is explicitly destroyed.</li>
<li>Here's an example showing the usage of constructors and destructors:</li>
</ul>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> {</span>
    <span class="hljs-built_in">string</span> name;
    <span class="hljs-keyword">int</span> age;

<span class="hljs-keyword">public</span>:
    <span class="hljs-comment">// Constructor</span>
    Student(<span class="hljs-built_in">string</span> n, <span class="hljs-keyword">int</span> a) {
        name = n;
        age = a;
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Student object created.\\n"</span>;
    }

    <span class="hljs-comment">// Destructor</span>
    ~Student() {
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Student object destroyed.\\n"</span>;
    }
};
</code></pre>
<h3 id="heading-access-specifiers-public-private-protected">Access Specifiers (Public, Private, Protected):</h3>
<ul>
<li>Access specifiers determine the visibility and accessibility of class members.</li>
<li>Public members are accessible from anywhere in the program.</li>
<li>Private members can only be accessed within the class.</li>
<li>Protected members are accessible within the class and its derived classes.</li>
<li>Here's an example illustrating access specifiers:</li>
</ul>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> {</span>
<span class="hljs-keyword">private</span>:
    <span class="hljs-keyword">int</span> speed;

<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setSpeed</span><span class="hljs-params">(<span class="hljs-keyword">int</span> s)</span> </span>{
        speed = s;
    }

    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">getSpeed</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> speed;
    }
};
</code></pre>
<h3 id="heading-function-overloading-and-overriding">Function Overloading and Overriding:</h3>
<ul>
<li>Function overloading allows multiple functions with the same name but different parameters.</li>
<li>Function overriding occurs when a derived class provides its own implementation of a function defined in the base class.</li>
<li>Here's an example showcasing function overloading and overriding:</li>
</ul>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> {</span>
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Calculating area of a generic shape.\\n"</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">(<span class="hljs-keyword">int</span> length, <span class="hljs-keyword">int</span> width)</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Calculating area of a rectangle: "</span> &lt;&lt; length * width &lt;&lt; <span class="hljs-built_in">endl</span>;
    }
};

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> :</span> <span class="hljs-keyword">public</span> Shape {
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Calculating area of a circle.\\n"</span>;
    }
};
</code></pre>
<h2 id="heading-pointers-and-memory-management">Pointers and Memory Management</h2>
<p>Memory management is a critical aspect of C++ programming, and understanding pointers is essential for efficient memory handling. In this article, we will explore pointers and addresses, dynamic memory allocation using 'new' and <code>delete</code>, common memory leaks, and how to avoid them. We will also introduce smart pointers as a safer alternative for memory management in C++.</p>
<h3 id="heading-pointers-and-addresses">Pointers and Addresses</h3>
<p>Pointers are variables that store memory addresses. They allow us to manipulate data indirectly and efficiently. Let's see a simple example:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span> x = <span class="hljs-number">10</span>; <span class="hljs-comment">// Declare an integer variable</span>
    <span class="hljs-keyword">int</span>* ptr = &amp;x; <span class="hljs-comment">// Declare a pointer and initialize it with the address of 'x'</span>

    <span class="hljs-comment">// Output the value and address of 'x' using the pointer</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of x: "</span> &lt;&lt; *ptr &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Address of x: "</span> &lt;&lt; ptr &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In this code snippet, we declare an integer variable <code>x</code> and a pointer <code>ptr</code> that holds the address of <code>x</code>. We then use the pointer to access the value of <code>x</code> using the dereference operator (<code>*ptr</code>).</p>
<h3 id="heading-dynamic-memory-allocation-new-and-delete">Dynamic Memory Allocation (new and delete)</h3>
<p>C++ provides operators <code>new</code> and <code>delete</code> for dynamic memory allocation. Unlike stack memory (local variables), dynamic memory is allocated on the heap, and its lifespan is determined by the programmer.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span>* arr = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">5</span>]; <span class="hljs-comment">// Dynamically allocate an integer array of size 5</span>

    <span class="hljs-comment">// Initialize the array elements</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; ++i) {
        arr[i] = i + <span class="hljs-number">1</span>;
    }

    <span class="hljs-comment">// Output the array elements</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; ++i) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; arr[i] &lt;&lt; <span class="hljs-string">" "</span>;
    }

    <span class="hljs-comment">// Don't forget to deallocate the memory to avoid memory leaks</span>
    <span class="hljs-keyword">delete</span>[] arr;

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In this example, we use <code>new</code> to allocate memory for an integer array of size 5. We then initialize and output the array elements. After using the array, it is crucial to deallocate the memory using <code>delete[]</code> to prevent memory leaks.</p>
<h3 id="heading-memory-leaks-and-how-to-avoid-them">Memory Leaks and How to Avoid Them</h3>
<p>Memory leaks occur when allocated memory is not deallocated, leading to a waste of memory over time. It is essential to be cautious when using dynamic memory.</p>
<p>Consider the following code snippet:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span>* num = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>; <span class="hljs-comment">// Allocate memory for a single integer</span>

    <span class="hljs-comment">// Perform some operations with 'num'</span>
    *num = <span class="hljs-number">42</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of num: "</span> &lt;&lt; *num &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;

    <span class="hljs-comment">// Oops! Forgot to deallocate the memory.</span>
    <span class="hljs-comment">// delete num; // Uncomment this line to fix the memory leak</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In this example, we allocate memory for a single integer using <code>new</code>. However, we forget to deallocate the memory using <code>delete</code>. This results in a memory leak.</p>
<p>To avoid memory leaks, always ensure that you release the allocated memory using <code>delete</code> (or <code>delete[]</code> for arrays) when you are done using it.</p>
<h3 id="heading-smart-pointers-in-c">Smart Pointers in C++</h3>
<p>Smart pointers are a valuable feature introduced in C++11 to simplify memory management and prevent memory leaks. They provide automatic memory deallocation when the smart pointer goes out of scope, eliminating the need for manual memory management using <code>delete</code>. There are three types of smart pointers in C++: <code>unique_ptr</code>, <code>shared_ptr</code>, and <code>weak_ptr</code>.</p>
<p><strong>unique_ptr:</strong>
<code>std::unique_ptr</code> provides exclusive ownership of the dynamically allocated memory. It ensures that only one <code>unique_ptr</code> can own the memory at a time, making it an excellent choice for cases where exclusive ownership is required.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;memory&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">unique_ptr</span>&lt;<span class="hljs-keyword">int</span>&gt; num = <span class="hljs-built_in">std</span>::make_unique&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">42</span>);

    <span class="hljs-comment">// Perform some operations with 'num'</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of num: "</span> &lt;&lt; *num &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;

    <span class="hljs-comment">// No need to delete explicitly; memory is automatically deallocated</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In this example, we create a <code>unique_ptr</code> named <code>num</code> that points to an integer with a value of <code>42</code>. The memory is deallocated automatically when <code>num</code> goes out of scope, ensuring proper cleanup.</p>
<p><strong>shared_ptr</strong>:
<code>std::shared_ptr</code> allows multiple smart pointers to share ownership of the same dynamically allocated object. It keeps track of the number of references to the object and automatically deallocates the memory when the last 'shared_ptr' that references it is destroyed.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;memory&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">shared_ptr</span>&lt;<span class="hljs-keyword">int</span>&gt; num1 = <span class="hljs-built_in">std</span>::make_shared&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">42</span>);
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">shared_ptr</span>&lt;<span class="hljs-keyword">int</span>&gt; num2 = num1;

    <span class="hljs-comment">// Perform operations with 'num1' and 'num2'</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of num1: "</span> &lt;&lt; *num1 &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of num2: "</span> &lt;&lt; *num2 &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;

    <span class="hljs-comment">// Memory is deallocated when all shared_ptrs referencing it are destroyed</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In this example, we create two <code>shared_ptr</code> instances, <code>num1</code> and <code>num2</code>, both pointing to the same integer object. The memory is deallocated automatically when both <code>num1</code> and <code>num2</code> go out of scope, ensuring proper cleanup.</p>
<p><strong>weak_ptr:</strong>
<code>std::weak_ptr</code> is a type of smart pointer that provides a non-owning reference to an object managed by <code>shared_ptr</code>. It allows you to observe or access the object without affecting its lifetime. A <code>weak_ptr</code> does not contribute to the reference count, and it is useful when you want to avoid cyclic references.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;memory&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">shared_ptr</span>&lt;<span class="hljs-keyword">int</span>&gt; sharedNum = <span class="hljs-built_in">std</span>::make_shared&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">42</span>);
    <span class="hljs-built_in">std</span>::weak_ptr&lt;<span class="hljs-keyword">int</span>&gt; weakNum = sharedNum;

    <span class="hljs-comment">// Check if the object still exists before accessing it</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">auto</span> lockedNum = weakNum.lock()) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Value of sharedNum through weakNum: "</span> &lt;&lt; *lockedNum &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Object has been destroyed."</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    }

    <span class="hljs-comment">// Memory is deallocated when all shared_ptrs referencing it are destroyed</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p> In this example, we create a <code>shared_ptr</code> named <code>sharedNum</code> and a <code>weak_ptr</code> named <code>weakNum</code> that refers to the same integer object. We use the <code>lock()</code> function to obtain a temporary <code>shared_ptr</code> from <code>weakNum</code> and check if the object is still valid before accessing it.</p>
<h2 id="heading-understanding-the-standard-template-library-stl">Understanding the Standard Template Library (STL)</h2>
<p>The Standard Template Library (STL) is an essential part of C++ that provides a collection of template classes and functions to simplify common programming tasks. In this article, we will explore the key components of the STL, including containers (vectors, lists, maps, etc.), iterators and algorithms, string manipulation, and input/output streams (iostream). We'll dive into code snippets to illustrate how to use these components effectively in your C++ programs.</p>
<h3 id="heading-overview-of-stl-containers">Overview of STL Containers</h3>
<p>The STL offers various container classes that provide data structures for holding and managing collections of elements efficiently. Some popular STL containers include:</p>
<p><strong>Vector:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>

<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>};
</code></pre>
<ul>
<li>Vectors are dynamic arrays that can grow or shrink in size automatically.</li>
<li>They provide random access to elements and support dynamic resizing with efficient memory management.</li>
</ul>
<p><strong>List:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;list&gt;</span></span>

<span class="hljs-built_in">std</span>::<span class="hljs-built_in">list</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>&gt; names = {<span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Charlie"</span>};
</code></pre>
<ul>
<li>Lists are doubly-linked lists that allow fast insertions and deletions from any position.</li>
<li>They do not support random access and indexing like vectors, but they are efficient for certain operations.</li>
</ul>
<p><strong>Map:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;map&gt;</span></span>

<span class="hljs-built_in">std</span>::<span class="hljs-built_in">map</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>, <span class="hljs-keyword">int</span>&gt; scores = {{<span class="hljs-string">"Alice"</span>, <span class="hljs-number">95</span>}, {<span class="hljs-string">"Bob"</span>, <span class="hljs-number">88</span>}, {<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">92</span>}};
</code></pre>
<ul>
<li>Maps are associative containers that store key-value pairs.</li>
<li>They are implemented as binary search trees, providing efficient key-based retrieval and insertion.</li>
</ul>
<h3 id="heading-iterators-and-algorithms"><strong>Iterators and Algorithms</strong></h3>
<p>STL iterators are objects that allow iterating over elements in containers without exposing the underlying data structure's details. Algorithms are functions that operate on container elements through iterators. Some commonly used algorithms include:</p>
<p><strong>Finding an element in a vector:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;algorithm&gt;</span></span>

<span class="hljs-keyword">auto</span> it = <span class="hljs-built_in">std</span>::find(numbers.begin(), numbers.end(), <span class="hljs-number">3</span>);
<span class="hljs-keyword">if</span> (it != numbers.end()) {
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Found element: "</span> &lt;&lt; *it &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Element not found."</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
}
</code></pre>
<ul>
<li>The <code>std::find</code> algorithm searches for the first occurrence of a value in a range.</li>
</ul>
<p><strong>Sorting a vector in ascending order:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;algorithm&gt;</span></span>

<span class="hljs-built_in">std</span>::sort(numbers.begin(), numbers.end());
</code></pre>
<ul>
<li>The <code>std::sort</code> algorithm arranges elements in ascending order using the <code>&lt;</code> operator by default.</li>
</ul>
<h3 id="heading-string-manipulation"><strong>String Manipulation:</strong></h3>
<p>The STL provides various functions for string manipulation, including concatenation, substring extraction, and searching. Some examples are:</p>
<p><strong>Concatenating strings:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> first_name = <span class="hljs-string">"John"</span>;
<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> last_name = <span class="hljs-string">"Doe"</span>;
<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> full_name = first_name + <span class="hljs-string">" "</span> + last_name;
</code></pre>
<ul>
<li>The <code>+</code> operator can be used to concatenate strings.</li>
</ul>
<p><strong>Extracting substrings:</strong></p>
<pre><code class="lang-cpp"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> sentence = <span class="hljs-string">"The quick brown fox"</span>;
<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> word = sentence.substr(<span class="hljs-number">4</span>, <span class="hljs-number">5</span>); <span class="hljs-comment">// Extract "quick"</span>
</code></pre>
<ul>
<li>The <code>substr</code> function extracts a substring from a given position with a specified length.</li>
</ul>
<p><strong>Input/Output Streams (iostream):</strong>
C++ uses the iostream library to perform input and output operations. It provides the <code>cin</code> and <code>cout</code> objects for reading from and writing to the standard input and output streams, respectively. Here's an example:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span> number;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Enter a number: "</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cin</span> &gt;&gt; number;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"You entered: "</span> &lt;&lt; number &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<ul>
<li>The <code>std::cin</code> object is used with the <code>&gt;&gt;</code> operator to read input from the user.</li>
<li>The <code>std::cout</code> object is used with the <code>&lt;&lt;</code> operator to print output to the console.</li>
</ul>
<h2 id="heading-exception-handling">Exception Handling</h2>
<p>Exception handling is a crucial aspect of C++ programming that allows us to gracefully handle errors and unexpected situations that may occur during program execution. In this article, we will explore how to handle errors and exceptions in C++ using try-catch blocks, learn about throwing and catching exceptions, and understand the importance of exception safety and resource management.</p>
<h3 id="heading-handling-errors-and-exceptions-in-c">Handling Errors and Exceptions in C++</h3>
<p>In C++, when an error occurs during program execution, it can lead to unexpected behavior or even program crashes. Exception handling provides a mechanism to handle these errors gracefully, ensuring that the program can recover from exceptional conditions.</p>
<p>An exception is an object that represents an exceptional condition, such as division by zero, file not found, or memory allocation failure. When an exception is thrown, the program searches for an appropriate exception handler to deal with the situation.</p>
<h3 id="heading-try-catch-blocks">try-catch Blocks</h3>
<p>C++ uses try-catch blocks to handle exceptions. The code inside the try block is monitored for exceptions. If an exception is thrown within the try block, the program immediately jumps to the corresponding catch block to handle the exception.</p>
<p>Syntax of a try-catch block:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Code that may throw an exception</span>
} <span class="hljs-keyword">catch</span> (ExceptionType1&amp; ex) {
    <span class="hljs-comment">// Handle ExceptionType1</span>
} <span class="hljs-keyword">catch</span> (ExceptionType2&amp; ex) {
    <span class="hljs-comment">// Handle ExceptionType2</span>
} <span class="hljs-comment">// ...</span>
</code></pre>
<p>The catch blocks are evaluated in the order they appear. The first catch block that matches the type of the thrown exception is executed.</p>
<h3 id="heading-throwing-and-catching-exceptions">Throwing and Catching Exceptions</h3>
<p>In C++, exceptions are thrown using the <code>throw</code> keyword, followed by an object representing the exception. The object can be of any type, but it is commonly an instance of a specific exception class derived from <code>std::exception</code>.</p>
<p>Example of throwing and catching an exception:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdexcept&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">divide</span><span class="hljs-params">(<span class="hljs-keyword">int</span> numerator, <span class="hljs-keyword">int</span> denominator)</span> </span>{
    <span class="hljs-keyword">if</span> (denominator == <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">throw</span> <span class="hljs-built_in">std</span>::runtime_error(<span class="hljs-string">"Division by zero is not allowed."</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">static_cast</span>&lt;<span class="hljs-keyword">double</span>&gt;(numerator) / denominator;
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">int</span> result = divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>);
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Result: "</span> &lt;&lt; result &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    } <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::exception&amp; ex) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Exception caught: "</span> &lt;&lt; ex.what() &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<h3 id="heading-exception-safety-and-resource-management">Exception Safety and Resource Management</h3>
<p>Exception safety is a critical concern when dealing with resource management in C++. When an exception is thrown, it's essential to ensure that resources (memory, file handles, etc.) are properly cleaned up to avoid leaks and maintain a consistent program state.</p>
<ul>
<li>Use Resource Managing Classes: To manage resources safely, use C++ classes such as smart pointers (<code>std::shared_ptr</code>, <code>std::unique_ptr</code>) for memory management and RAII (Resource Acquisition Is Initialization) for other resources like file handles.</li>
<li>Avoid Dynamic Memory Management: Whenever possible, prefer using containers and C++ Standard Library classes to manage data instead of manually allocating and deallocating memory.</li>
<li>Use the Copy-and-Swap Idiom: In situations where an object's state can change during an operation, use the Copy-and-Swap Idiom to ensure exception safety.</li>
</ul>
<h2 id="heading-best-practices-and-coding-guidelines">Best Practices and Coding Guidelines</h2>
<p>In the world of programming, adhering to best practices and coding guidelines is crucial for writing maintainable, efficient, and bug-free code. In this article, we will explore some essential best practices and coding guidelines specific to C++. By following these practices, you can enhance the readability, reliability, and performance of your C++ codebase.</p>
<h3 id="heading-naming-conventions-and-code-style">Naming Conventions and Code Style:</h3>
<ul>
<li>Consistent and meaningful naming conventions for variables, functions, classes, and constants.</li>
<li>Using descriptive names that reflect the purpose and functionality of the entities.</li>
<li>Following camel case, snake case, or any other agreed-upon convention for naming.</li>
<li>Avoiding single-letter or ambiguous names that can lead to confusion.</li>
</ul>
<p>Example:</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// Good naming convention for variables and functions</span>
<span class="hljs-keyword">int</span> numberOfStudents;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">calculateTotalScore</span><span class="hljs-params">()</span></span>;

<span class="hljs-comment">// Poor naming convention</span>
<span class="hljs-keyword">int</span> n;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">calc</span><span class="hljs-params">()</span></span>;
</code></pre>
<h3 id="heading-error-handling-and-exception-safety">Error Handling and Exception Safety:</h3>
<ul>
<li>Properly handling and reporting errors to maintain code stability and prevent unexpected behavior.</li>
<li>Using exceptions to handle exceptional situations, rather than relying solely on return codes or error flags.</li>
<li>Employing RAII (Resource Acquisition Is Initialization) principle to ensure proper cleanup and resource deallocation in case of exceptions.</li>
</ul>
<p>Example:</p>
<pre><code class="lang-cpp"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Code that may throw an exception</span>
} <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::exception&amp; e) {
    <span class="hljs-comment">// Handle the exception</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cerr</span> &lt;&lt; <span class="hljs-string">"An error occurred: "</span> &lt;&lt; e.what() &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
}
</code></pre>
<h3 id="heading-memory-management-and-resource-acquisition">Memory Management and Resource Acquisition:</h3>
<ul>
<li>Using smart pointers (e.g., <code>std::unique_ptr</code>, <code>std::shared_ptr</code>) to handle memory allocation and deallocation automatically.</li>
<li>Avoiding raw pointers whenever possible to minimize the risk of memory leaks and dangling pointers.</li>
<li>Following the principle of ownership to clearly define responsibility for resource allocation and deallocation.</li>
</ul>
<p>Example:</p>
<pre><code class="lang-cpp"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">unique_ptr</span>&lt;<span class="hljs-keyword">int</span>&gt; ptr = <span class="hljs-built_in">std</span>::make_unique&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">42</span>);
<span class="hljs-comment">// Automatically releases memory when ptr goes out of scope</span>
</code></pre>
<h3 id="heading-performance-considerations">Performance Considerations:</h3>
<ul>
<li>Avoiding unnecessary copies and expensive operations by using move semantics and rvalue references.</li>
<li>Utilizing algorithms and data structures from the Standard Template Library (STL) for efficient and optimized code.</li>
<li>Profiling and optimizing critical sections of the codebase based on performance analysis.</li>
</ul>
<p>Example:</p>
<pre><code class="lang-cpp"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> name = <span class="hljs-string">"John"</span>;
<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> lastName = <span class="hljs-built_in">std</span>::move(name);  <span class="hljs-comment">// Efficiently moves the content of name to lastName</span>
</code></pre>
<h3 id="heading-c-coding-standards">C++ Coding Standards:</h3>
<ul>
<li>Familiarizing yourself with established coding standards, such as the Google C++ Style Guide, to maintain a consistent code style across projects.</li>
<li>Adhering to guidelines for indentation, spacing, commenting, and other formatting conventions.</li>
<li>Using static code analysis tools (e.g., Clang-Tidy) to automatically enforce coding standards and detect potential issues.</li>
</ul>
<p>Example (Google C++ Style Guide):</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// Good code style with proper indentation and spacing</span>
<span class="hljs-keyword">if</span> (condition) {
    doSomething();
} <span class="hljs-keyword">else</span> {
    doSomethingElse();
}

<span class="hljs-comment">// Poor code style with inconsistent indentation and spacing</span>
<span class="hljs-keyword">if</span>(condition){
    doSomething();
}<span class="hljs-keyword">else</span>{
    doSomethingElse();
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this comprehensive introduction to C++, we have covered a wide range of topics to help you embark on your journey into the world of C++ programming. Starting from the setting up of the development environment, including installing a C++ compiler, choosing an Integrated Development Environment (IDE), and configuring the build system, we have ensured that you have a solid foundation to begin writing C++ code.</p>
<p>We then delved into best practices and coding guidelines specific to C++. By following these guidelines, you can write code that is not only readable and maintainable but also robust and efficient. We explored the importance of naming conventions and code style, emphasizing the significance of clear and descriptive names to enhance code clarity. Additionally, we discussed error handling and exception safety, emphasizing the use of exceptions for handling exceptional situations and the adoption of the RAII principle for resource management.</p>
<p>Memory management and resource acquisition were also key topics covered in this article. By utilizing smart pointers and following the principle of ownership, we can ensure proper memory allocation and deallocation, minimizing the risk of memory leaks and dangling pointers.</p>
<p>Performance considerations were not overlooked, as we discussed techniques such as move semantics and rvalue references to optimize code and avoid unnecessary copies. Leveraging the Standard Template Library (STL) and profiling critical code sections can lead to highly efficient and optimized C++ programs.</p>
<p>Lastly, we explored the importance of adhering to established coding standards, such as the Google C++ Style Guide. Following these standards ensures consistency in code style and readability across projects, and utilizing static code analysis tools can automatically enforce these guidelines.</p>
<p>Armed with this knowledge, you are now equipped to tackle C++ programming projects with confidence. Remember, practice and continuous learning are essential to master any programming language, and C++ is no exception. As you progress in your journey, dive deeper into advanced C++ features and explore additional resources, such as books, online tutorials, and the vibrant C++ community.</p>
<p>In conclusion, C++ is a powerful and versatile programming language widely used in various domains, ranging from systems programming to game development. By understanding the fundamentals, setting up your development environment, and following best practices and coding guidelines, you are well on your way to becoming a proficient C++ developer. So, roll up your sleeves, start coding, and embrace the endless possibilities that C++ has to offer.</p>
]]></content:encoded></item><item><title><![CDATA[Ultimate Redis Cheatsheet]]></title><description><![CDATA[What is Redis?
Redis, which stands for Remote Dictionary Server, is an open-source, in-memory data structure store that serves as a highly efficient and versatile database solution. Developed by Salvatore Sanfilippo, Redis is designed to offer lightn...]]></description><link>https://tanseersaji.com/ultimate-redis-cheatsheet</link><guid isPermaLink="true">https://tanseersaji.com/ultimate-redis-cheatsheet</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Wed, 21 Jun 2023 08:50:37 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-redis">What is Redis?</h2>
<p>Redis, which stands for Remote Dictionary Server, is an open-source, in-memory data structure store that serves as a highly efficient and versatile database solution. Developed by Salvatore Sanfilippo, Redis is designed to offer lightning-fast data access and retrieval by keeping all the data in memory rather than on disk, ensuring remarkable performance and responsiveness.</p>
<p>One of the key features that sets Redis apart is its support for various data structures, including strings, lists, sets, sorted sets, and hashes. This versatility enables Redis to serve multiple purposes, such as acting as a key-value store, a message broker, or a caching layer.</p>
<p>Redis utilizes an in-memory approach, making it exceptionally fast for read and write operations. With its optimized data structures and efficient algorithms, Redis can process data in sub-millisecond response times, making it an ideal choice for real-time applications and use cases that require high-performance data manipulation.</p>
<p>Furthermore, Redis offers persistence options, allowing users to store their data on disk periodically or whenever specific conditions are met. This feature ensures data durability and makes Redis suitable for applications that require both speed and data persistence.</p>
<p>In addition to its exceptional performance, Redis provides advanced features like pub/sub messaging, transactions, and Lua scripting, which empower developers to build complex applications and systems with ease.</p>
<p>Redis has become immensely popular due to its simplicity, versatility, and extensive support for multiple programming languages. It offers client libraries for various languages, making it accessible and easy to integrate into different software stacks.</p>
<p>Whether you need to cache frequently accessed data, build real-time applications, implement a messaging system, or store and process complex data structures, Redis provides a robust and efficient solution that continues to be widely adopted across industries.</p>
<p>In conclusion, Redis is a powerful and flexible database solution that excels in performance, versatility, and ease of use. Its in-memory nature, support for various data structures, and extensive feature set make it a go-to choice for developers looking to build high-performance applications and systems.</p>
<h2 id="heading-how-redis-is-different-from-other-databases">How Redis is different from other Databases?</h2>
<p>Redis differs from other databases in several key aspects:</p>
<ol>
<li><strong>In-Memory Data Storage</strong>: Redis primarily stores data in memory, allowing for extremely fast read and write operations. This design choice sets Redis apart from traditional disk-based databases that incur disk I/O overhead. By keeping data in memory, Redis can achieve high throughput and low latency, making it well-suited for applications that require real-time data processing and high-performance caching.</li>
<li><strong>Data Structures</strong>: Redis supports a wide range of data structures, including strings, lists, sets, hashes, and sorted sets. This flexibility allows developers to model complex data scenarios efficiently. Unlike many other databases that offer a fixed schema, Redis provides dynamic and versatile data structures that can be manipulated and combined to suit specific application needs.</li>
<li><strong>Built-in Caching Mechanisms</strong>: Redis has native support for caching, making it an excellent choice for scenarios that require frequent access to frequently accessed data. With features like key expiration and eviction policies, Redis can efficiently manage cache storage and ensure that the most relevant data remains readily available.</li>
<li><strong>Pub/Sub Messaging</strong>: Redis includes built-in publish/subscribe messaging capabilities. This feature allows applications to implement real-time messaging and event-driven architectures. Publishers can send messages to specific channels, and subscribers receive messages from those channels in real-time. This makes Redis a suitable choice for building chat systems, real-time analytics, and other applications that require event-based communication.</li>
<li><strong>Lua Scripting</strong>: Redis supports Lua scripting, which enables developers to execute server-side scripts directly within the database. This allows for complex operations and transactional logic to be performed within Redis, reducing the need for round-trips between the application and the database. Lua scripting enhances Redis's flexibility and extensibility by enabling custom behaviour and complex data manipulations.</li>
<li><strong>Replication and Persistence</strong>: Redis provides built-in replication mechanisms for creating multiple copies of the database. This replication ensures high availability and fault tolerance by propagating changes from a master node to one or more slave nodes. Redis also offers persistence options through snapshotting and append-only file (AOF) logging, allowing data to be saved to disk for recovery in the event of a system failure.</li>
<li><strong>Simplicity and Performance</strong>: Redis is known for its simplicity and performance. It offers a straightforward set of commands that are easy to understand and use. The focus on in-memory storage and the absence of complex query languages or indexing mechanisms simplify the database's design and contribute to its exceptional performance.</li>
</ol>
<p>Overall, Redis stands out among other databases due to its in-memory storage, versatile data structures, caching capabilities, pub/sub messaging, Lua scripting, replication, and performance-oriented design. These features make Redis a popular choice for applications that require speed, flexibility, and real-time data processing.</p>
<h2 id="heading-installing-redis-and-redis-cli">Installing Redis and Redis CLI</h2>
<p>Here are the steps to install Redis on Linux, macOS, and Windows:</p>
<p><strong>Linux:</strong></p>
<ol>
<li>Open a terminal window.</li>
<li><p>Update the package manager:</p>
<pre><code class="lang-bash"> sudo apt update
</code></pre>
</li>
<li><p>Install Redis:</p>
<pre><code class="lang-bash"> sudo apt install redis-server
</code></pre>
</li>
<li><p>Start the Redis service:</p>
<pre><code class="lang-bash"> sudo systemctl start redis-server
</code></pre>
</li>
<li><p>To access the Redis command-line interface (redis-cli):</p>
<pre><code class="lang-bash"> redis-cli
</code></pre>
</li>
</ol>
<p><strong>macOS:</strong></p>
<ol>
<li>Open a terminal window.</li>
<li><p>Install Homebrew (if not already installed):</p>
<pre><code class="lang-bash"> /bin/bash -c <span class="hljs-string">"<span class="hljs-subst">$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)</span>"</span>
</code></pre>
</li>
<li><p>Install Redis using Homebrew:</p>
<pre><code class="lang-bash"> brew install redis
</code></pre>
</li>
<li><p>Start the Redis service:</p>
<pre><code class="lang-bash"> brew services start redis
</code></pre>
</li>
<li><p>To access the Redis command-line interface (redis-cli):</p>
<pre><code class="lang-bash"> redis-cli
</code></pre>
</li>
</ol>
<p><strong>Windows:</strong></p>
<ol>
<li>Download the latest Redis for Windows from the Microsoft Open Tech GitHub repository: <strong><a target="_blank" href="https://github.com/microsoftarchive/redis/releases">https://github.com/microsoftarchive/redis/releases</a></strong></li>
<li>Extract the downloaded archive to a directory of your choice, e.g., <strong><code>C:\Redis</code></strong>.</li>
<li>Open a Command Prompt window.</li>
<li><p>Navigate to the Redis installation directory:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> C:\Redis
</code></pre>
</li>
<li><p>Start the Redis server:</p>
<pre><code class="lang-bash"> redis-server.exe
</code></pre>
</li>
<li><p>Open another Command Prompt window to access the Redis command-line interface (redis-cli):</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> C:\Redis
 redis-cli.exe
</code></pre>
</li>
</ol>
<p>Please note that for Linux and macOS, the installation steps assume the usage of package managers like <strong><code>apt</code></strong> and Homebrew, respectively. If you are using a different package manager or distribution, you may need to adjust the installation commands accordingly.</p>
<h2 id="heading-commands">Commands</h2>
<h3 id="heading-set-manipulation">SET manipulation</h3>
<ol>
<li><p><strong>SET</strong></p>
<ul>
<li>Command: <strong><code>SET</code></strong></li>
<li>Syntax: <strong><code>SET key value</code></strong></li>
<li>Usage: <strong><code>SET myset "Hello Redis"</code></strong></li>
<li>Description: Sets the value of a key with the provided string value. If the key already exists, it overwrites the existing value. This command is also used to create a new key-value pair if the key doesn't exist.</li>
</ul>
</li>
<li><p><strong>GET</strong></p>
<ul>
<li>Command: <strong><code>GET</code></strong></li>
<li>Syntax: <strong><code>GET key</code></strong></li>
<li>Usage: <strong><code>GET myset</code></strong></li>
<li>Description: Retrieves the value associated with the specified key. If the key exists, the command returns the value; otherwise, it returns <strong><code>nil</code></strong>.</li>
</ul>
</li>
<li><p><strong>SADD</strong></p>
<ul>
<li>Command: <strong><code>SADD</code></strong></li>
<li>Syntax: <strong><code>SADD key member [member ...]</code></strong></li>
<li>Usage: <strong><code>SADD myset "value1" "value2"</code></strong></li>
<li>Description: Adds one or more members to a set. If the members already exist, they are ignored. If the key doesn't exist, a new set is created with the specified members.</li>
</ul>
</li>
<li><p><strong>SMEMBERS</strong></p>
<ul>
<li>Command: <strong><code>SMEMBERS</code></strong></li>
<li>Syntax: <strong><code>SMEMBERS key</code></strong></li>
<li>Usage: <strong><code>SMEMBERS myset</code></strong></li>
<li>Description: Returns all the members of a set. If the key doesn't exist, an empty set is returned.</li>
</ul>
</li>
<li><p><strong>SISMEMBER</strong></p>
<ul>
<li>Command: <strong><code>SISMEMBER</code></strong></li>
<li>Syntax: <strong><code>SISMEMBER key member</code></strong></li>
<li>Usage: <strong><code>SISMEMBER myset "value1"</code></strong></li>
<li>Description: Checks if a member exists in a set. Returns <strong><code>1</code></strong> if the member is present; otherwise, returns <strong><code>0</code></strong>.</li>
</ul>
</li>
<li><p><strong>SREM</strong></p>
<ul>
<li>Command: <strong><code>SREM</code></strong></li>
<li>Syntax: <strong><code>SREM key member [member ...]</code></strong></li>
<li>Usage: <strong><code>SREM myset "value1" "value2"</code></strong></li>
<li>Description: Removes one or more members from a set. If the members don't exist, they are ignored. If the key becomes empty after removing members, the key is also removed.</li>
</ul>
</li>
<li><p><strong>SCARD</strong></p>
<ul>
<li>Command: <strong><code>SCARD</code></strong></li>
<li>Syntax: <strong><code>SCARD key</code></strong></li>
<li>Usage: <strong><code>SCARD myset</code></strong></li>
<li>Description: Returns the cardinality (number of members) of a set. If the key doesn't exist, <strong><code>0</code></strong> is returned.</li>
</ul>
</li>
<li><p><strong>SINTER</strong></p>
<ul>
<li>Command: <strong><code>SINTER</code></strong></li>
<li>Syntax: <strong><code>SINTER key [key ...]</code></strong></li>
<li>Usage: <strong><code>SINTER myset1 myset2</code></strong></li>
<li>Description: Returns the intersection of multiple sets. Only the members that exist in all the specified sets are included in the result set.</li>
</ul>
</li>
<li><p><strong>SUNION</strong></p>
<ul>
<li>Command: <strong><code>SUNION</code></strong></li>
<li>Syntax: <strong><code>SUNION key [key ...]</code></strong></li>
<li>Usage: <strong><code>SUNION myset1 myset2</code></strong></li>
<li>Description: Returns the union of multiple sets. All the members from the specified sets are included in the result set.</li>
</ul>
</li>
<li><p><strong>SDIFF</strong></p>
<ul>
<li>Command: <strong><code>SDIFF</code></strong></li>
<li>Syntax: <strong><code>SDIFF key [key ...]</code></strong></li>
<li>Usage: <strong><code>SDIFF myset1 myset2</code></strong></li>
<li>Description: Returns the difference between two sets. The members that exist in the first set but not in any other specified sets are included in the result set.</li>
</ul>
</li>
</ol>
<h3 id="heading-sorted-sets-manipulation"><strong>Sorted Sets manipulation</strong></h3>
<ol>
<li><p><strong>ZADD</strong></p>
<ul>
<li>Command: <strong><code>ZADD</code></strong></li>
<li>Syntax: <strong><code>ZADD key [NX|XX] [CH] [INCR] score member [score member ...]</code></strong></li>
<li>Usage: <strong><code>ZADD mysortedset 1 "value1" 2 "value2"</code></strong></li>
<li>Description: Adds one or more members with scores to a sorted set. If a member already exists, its score is updated. Additional options like <strong><code>NX</code></strong> (only add new elements), <strong><code>XX</code></strong> (only update existing elements), <strong><code>CH</code></strong> (return the number of changed elements), and <strong><code>INCR</code></strong> (increment the score of existing member) can be specified.</li>
</ul>
</li>
<li><p><strong>ZSCORE</strong></p>
<ul>
<li>Command: <strong><code>ZSCORE</code></strong></li>
<li>Syntax: <strong><code>ZSCORE key member</code></strong></li>
<li>Usage: <strong><code>ZSCORE mysortedset "value1"</code></strong></li>
<li>Description: Returns the score of a member in a sorted set. If the member doesn't exist, <strong><code>nil</code></strong> is returned.</li>
</ul>
</li>
<li><p><strong>ZRANGE</strong></p>
<ul>
<li>Command: <strong><code>ZRANGE</code></strong></li>
<li>Syntax: <strong><code>ZRANGE key start stop [WITHSCORES]</code></strong></li>
<li>Usage: <strong><code>ZRANGE mysortedset 0 -1</code></strong></li>
<li>Description: Returns a range of members from a sorted set based on their position. The <strong><code>start</code></strong> and <strong><code>stop</code></strong> arguments specify the inclusive range of positions. The optional <strong><code>WITHSCORES</code></strong> flag includes the scores in the result.</li>
</ul>
</li>
<li><p><strong>ZREVRANGE</strong></p>
<ul>
<li>Command: <strong><code>ZREVRANGE</code></strong></li>
<li>Syntax: <strong><code>ZREVRANGE key start stop [WITHSCORES]</code></strong></li>
<li>Usage: <strong><code>ZREVRANGE mysortedset 0 -1 WITHSCORES</code></strong></li>
<li>Description: Returns a range of members from a sorted set in reverse order based on their position. The <strong><code>start</code></strong> and <strong><code>stop</code></strong> arguments specify the inclusive range of positions. The optional <strong><code>WITHSCORES</code></strong> flag includes the scores in the result.</li>
</ul>
</li>
<li><p><strong>ZREM</strong></p>
<ul>
<li>Command: <strong><code>ZREM</code></strong></li>
<li>Syntax: <strong><code>ZREM key member [member ...]</code></strong></li>
<li>Usage: <strong><code>ZREM mysortedset "value1" "value2"</code></strong></li>
<li>Description: Removes one or more members from a sorted set. If a member doesn't exist, it is ignored. If the key becomes empty after removing members, the key is also removed.</li>
</ul>
</li>
<li><p><strong>ZCARD</strong></p>
<ul>
<li>Command: <strong><code>ZCARD</code></strong></li>
<li>Syntax: <strong><code>ZCARD key</code></strong></li>
<li>Usage: <strong><code>ZCARD mysortedset</code></strong></li>
<li>Description: Returns the cardinality (number of members) of a sorted set. If the key doesn't exist, <strong><code>0</code></strong> is returned.</li>
</ul>
</li>
<li><p><strong>ZCOUNT</strong></p>
<ul>
<li>Command: <strong><code>ZCOUNT</code></strong></li>
<li>Syntax: <strong><code>ZCOUNT key min max</code></strong></li>
<li>Usage: <strong><code>ZCOUNT mysortedset 1 10</code></strong></li>
<li>Description: Returns the count of members in a sorted set within the specified score range (<strong><code>min</code></strong> and <strong><code>max</code></strong> inclusive).</li>
</ul>
</li>
<li><p><strong>ZRANK</strong></p>
<ul>
<li>Command: <strong><code>ZRANK</code></strong></li>
<li>Syntax: <strong><code>ZRANK key member</code></strong></li>
<li>Usage: <strong><code>ZRANK mysortedset "value1"</code></strong></li>
<li>Description: Returns the position (rank) of a member in a sorted set when sorted in ascending order. The lowest rank is <strong><code>0</code></strong>. If the member doesn't exist, <strong><code>nil</code></strong> is returned.</li>
</ul>
</li>
<li><p><strong>ZREVRANK</strong></p>
<ul>
<li>Command: <strong><code>ZREVRANK</code></strong></li>
<li>Syntax: <strong><code>ZREVRANK key member</code></strong></li>
<li>Usage: <strong><code>ZREVRANK mysortedset "value1"</code></strong></li>
<li>Description: Returns the position (rank) of a member in a sorted set when sorted in descending order. The highest rank is <strong><code>0</code></strong>. If the member doesn't exist, <strong><code>nil</code></strong> is returned.</li>
</ul>
</li>
<li><p><strong>ZINCRBY</strong></p>
<ul>
<li>Command: <strong><code>ZINCRBY</code></strong></li>
<li>Syntax: <strong><code>ZINCRBY key increment member</code></strong></li>
<li>Usage: <strong><code>ZINCRBY mysortedset 5 "value1"</code></strong></li>
<li>Description: Increments the score of a member in a sorted set by the specified increment. If the member doesn't exist, it is added with the initial score as the increment value.</li>
</ul>
</li>
</ol>
<h3 id="heading-string-number-and-bit-manipulation">String, Number and Bit Manipulation</h3>
<ol>
<li><p><strong>APPEND</strong></p>
<ul>
<li>Command: <strong><code>APPEND</code></strong></li>
<li>Syntax: <strong><code>APPEND key value</code></strong></li>
<li>Usage: <strong><code>APPEND mykey "world"</code></strong></li>
<li>Description: Appends the specified value to the string value already stored at the key. If the key doesn't exist, a new key is created with the specified value.</li>
</ul>
</li>
<li><p><strong>BITCOUNT</strong></p>
<ul>
<li>Command: <strong><code>BITCOUNT</code></strong></li>
<li>Syntax: <strong><code>BITCOUNT key [start end]</code></strong></li>
<li>Usage: <strong><code>BITCOUNT mykey</code></strong></li>
<li>Description: Counts the number of set bits (1s) in a string value. Optionally, a range can be specified to count the bits within that range.</li>
</ul>
</li>
<li><p><strong>BITOP</strong></p>
<ul>
<li>Command: <strong><code>BITOP</code></strong></li>
<li>Syntax: <strong><code>BITOP operation destkey key [key ...]</code></strong></li>
<li>Usage: <strong><code>BITOP AND destkey key1 key2</code></strong></li>
<li>Description: Performs a bitwise operation (AND, OR, XOR, NOT) between multiple keys and stores the result in the destination key.</li>
</ul>
</li>
<li><p><strong>BITPOS</strong></p>
<ul>
<li>Command: <strong><code>BITPOS</code></strong></li>
<li>Syntax: <strong><code>BITPOS key bit [start] [end]</code></strong></li>
<li>Usage: <strong><code>BITPOS mykey 1 0 10</code></strong></li>
<li>Description: Finds the position of the first set bit (1) or clear bit (0) in a string value. Optionally, a range can be specified to search for the bit within that range.</li>
</ul>
</li>
<li><p><strong>DECR</strong></p>
<ul>
<li>Command: <strong><code>DECR</code></strong></li>
<li>Syntax: <strong><code>DECR key</code></strong></li>
<li>Usage: <strong><code>DECR mykey</code></strong></li>
<li>Description: Decrements the value of the key by 1. If the key doesn't exist, it is initialized with the value of 0 before decrementing.</li>
</ul>
</li>
<li><p><strong>DECRBY</strong></p>
<ul>
<li>Command: <strong><code>DECRBY</code></strong></li>
<li>Syntax: <strong><code>DECRBY key decrement</code></strong></li>
<li>Usage: <strong><code>DECRBY mykey 5</code></strong></li>
<li>Description: Decrements the value of the key by the specified decrement. If the key doesn't exist, it is initialized with the value of 0 before decrementing.</li>
</ul>
</li>
<li><p><strong>GET</strong></p>
<ul>
<li>Command: <strong><code>GET</code></strong></li>
<li>Syntax: <strong><code>GET key</code></strong></li>
<li>Usage: <strong><code>GET mykey</code></strong></li>
<li>Description: Retrieves the value associated with the specified key. If the key exists, the command returns the value; otherwise, it returns <strong><code>nil</code></strong>.</li>
</ul>
</li>
<li><p><strong>GETBIT</strong></p>
<ul>
<li>Command: <strong><code>GETBIT</code></strong></li>
<li>Syntax: <strong><code>GETBIT key offset</code></strong></li>
<li>Usage: <strong><code>GETBIT mykey 5</code></strong></li>
<li>Description: Returns the bit value at the specified offset in a string value. The offset is zero-based.</li>
</ul>
</li>
<li><p><strong>GETRANGE</strong></p>
<ul>
<li>Command: <strong><code>GETRANGE</code></strong></li>
<li>Syntax: <strong><code>GETRANGE key start end</code></strong></li>
<li>Usage: <strong><code>GETRANGE mykey 0 3</code></strong></li>
<li>Description: Retrieves a substring of the string value stored at the key, starting from the specified start index to the end index (inclusive).</li>
</ul>
</li>
<li><p><strong>GETSET</strong></p>
<ul>
<li>Command: <strong><code>GETSET</code></strong></li>
<li>Syntax: <strong><code>GETSET key value</code></strong></li>
<li>Usage: <strong><code>GETSET mykey "newvalue"</code></strong></li>
<li>Description: Sets the value of the key with the provided string value and returns the old value. If the key doesn't exist, it is initialized with the specified value.</li>
</ul>
</li>
<li><p><strong>INCR</strong></p>
<ul>
<li>Command: <strong><code>INCR</code></strong></li>
<li>Syntax: <strong><code>INCR key</code></strong></li>
<li>Usage: <strong><code>INCR mykey</code></strong></li>
<li>Description: Increments the value of the key by 1. If the key doesn't exist, it is initialized with the value of 0 before incrementing.</li>
</ul>
</li>
<li><p><strong>INCRBY</strong></p>
<ul>
<li>Command: <strong><code>INCRBY</code></strong></li>
<li>Syntax: <strong><code>INCRBY key increment</code></strong></li>
<li>Usage: <strong><code>INCRBY mykey 5</code></strong></li>
<li>Description: Increments the value of the key by the specified increment. If the key doesn't exist, it is initialized with the value of 0 before incrementing.</li>
</ul>
</li>
<li><p><strong>INCRBYFLOAT</strong></p>
<ul>
<li>Command: <strong><code>INCRBYFLOAT</code></strong></li>
<li>Syntax: <strong><code>INCRBYFLOAT key increment</code></strong></li>
<li>Usage: <strong><code>INCRBYFLOAT mykey 2.5</code></strong></li>
<li>Description: Increments the value of the key by the specified float increment. If the key doesn't exist, it is initialized with the value of 0 before incrementing.</li>
</ul>
</li>
<li><p><strong>MGET</strong></p>
<ul>
<li>Command: <strong><code>MGET</code></strong></li>
<li>Syntax: <strong><code>MGET key [key ...]</code></strong></li>
<li>Usage: <strong><code>MGET key1 key2 key3</code></strong></li>
<li>Description: Retrieves the values associated with multiple keys. It returns an array of values corresponding to the provided keys.</li>
</ul>
</li>
<li><p><strong>MSET</strong></p>
<ul>
<li>Command: <strong><code>MSET</code></strong></li>
<li>Syntax: <strong><code>MSET key value [key value ...]</code></strong></li>
<li>Usage: <strong><code>MSET key1 "value1" key2 "value2"</code></strong></li>
<li>Description: Sets multiple keys to their respective values. It allows setting multiple key-value pairs in a single command.</li>
</ul>
</li>
<li><p><strong>MSETNX</strong></p>
<ul>
<li>Command: <strong><code>MSETNX</code></strong></li>
<li>Syntax: <strong><code>MSETNX key value [key value ...]</code></strong></li>
<li>Usage: <strong><code>MSETNX key1 "value1" key2 "value2"</code></strong></li>
<li>Description: Sets multiple keys to their respective values, only if none of the keys already exist. It allows atomic setting of multiple keys.</li>
</ul>
</li>
<li><p><strong>PSETEX</strong></p>
<ul>
<li>Command: <strong><code>PSETEX</code></strong></li>
<li>Syntax: <strong><code>PSETEX key milliseconds value</code></strong></li>
<li>Usage: <strong><code>PSETEX mykey 1000 "Hello"</code></strong></li>
<li>Description: Sets the value of the key with the provided string value and a specified expiration time in milliseconds.</li>
</ul>
</li>
<li><p><strong>SET</strong></p>
<ul>
<li>Command: <strong><code>SET</code></strong></li>
<li>Syntax: <strong><code>SET key value [EX seconds|PX milliseconds] [NX|XX]</code></strong></li>
<li>Usage: <strong><code>SET mykey "Hello" EX 60 NX</code></strong></li>
<li>Description: Sets the value of a key with the provided string value. Additional options like expiration time, conditional set (<strong><code>NX</code></strong> - only if the key doesn't exist, <strong><code>XX</code></strong> - only if the key exists) can be specified.</li>
</ul>
</li>
<li><p><strong>SETBIT</strong></p>
<ul>
<li>Command: <strong><code>SETBIT</code></strong></li>
<li>Syntax: <strong><code>SETBIT key offset value</code></strong></li>
<li>Usage: <strong><code>SETBIT mykey 5 1</code></strong></li>
<li>Description: Sets the bit at the specified offset in a string value to either 0 or 1.</li>
</ul>
</li>
<li><p><strong>SETEX</strong></p>
<ul>
<li>Command: <strong><code>SETEX</code></strong></li>
<li>Syntax: <strong><code>SETEX key seconds value</code></strong></li>
<li>Usage: <strong><code>SETEX mykey 60 "Hello"</code></strong></li>
<li>Description: Sets the value of the key with the provided string value and a specified expiration time in seconds.</li>
</ul>
</li>
<li><p><strong>SETNX</strong></p>
<ul>
<li>Command: <strong><code>SETNX</code></strong></li>
<li>Syntax: <strong><code>SETNX key value</code></strong></li>
<li>Usage: <strong><code>SETNX mykey "Hello"</code></strong></li>
<li>Description: Sets the value of a key with the provided string value, only if the key doesn't exist.</li>
</ul>
</li>
<li><p><strong>SETRANGE</strong></p>
<ul>
<li>Command: <strong><code>SETRANGE</code></strong></li>
<li>Syntax: <strong><code>SETRANGE key offset value</code></strong></li>
<li>Usage: <strong><code>SETRANGE mykey 5 "Redis"</code></strong></li>
<li>Description: Overwrites a substring of the string value stored at the key, starting from the specified offset with the provided value.</li>
</ul>
</li>
<li><p><strong>STRLEN</strong></p>
<ul>
<li>Command: <strong><code>STRLEN</code></strong></li>
<li>Syntax: <strong><code>STRLEN key</code></strong></li>
<li>Usage: <strong><code>STRLEN mykey</code></strong></li>
<li>Description: Returns length</li>
</ul>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, we have discussed Redis, a popular in-memory data structure store, and explored its unique characteristics that set it apart from other databases. Redis offers exceptional performance and versatility, making it suitable for various use cases, such as caching, real-time analytics, messaging systems, and more.</p>
<p>We have also covered the installation process of Redis on Linux, macOS, and Windows, including how to access the Redis command-line interface (redis-cli) for interacting with the database.</p>
<p>Furthermore, we have delved into the major commands related to set manipulation, providing syntax, usage examples, and descriptions for each command. These commands enable users to perform various operations like adding, retrieving, modifying, and removing elements from sets in Redis.</p>
<p>Additionally, we have explored the major commands related to sorted set manipulation, including operations such as adding members with scores, retrieving ranges, finding positions, incrementing scores, and more. Sorted sets in Redis provide an ordered collection of unique elements, allowing efficient operations based on both element values and scores.</p>
<p>Redis commands like APPEND, GET, SET, INCR, and many others offer powerful functionality for string manipulation, bit operations, and key-value management.</p>
<p>Redis, with its versatility, performance, and rich set of commands, continues to be a preferred choice for developers and architects when it comes to handling data-intensive applications and solving various data storage and retrieval challenges.</p>
]]></content:encoded></item><item><title><![CDATA[Google I/O 2023: The Year of AI]]></title><description><![CDATA[Google I/O 2023 was a major event for the company, and it showcased Google's commitment to innovation. The announcements at I/O 2023 will have a significant impact on the tech industry, and they will help Google to continue to grow its business in th...]]></description><link>https://tanseersaji.com/google-io-2023-the-year-of-ai</link><guid isPermaLink="true">https://tanseersaji.com/google-io-2023-the-year-of-ai</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Sat, 13 May 2023 07:26:34 GMT</pubDate><content:encoded><![CDATA[<p>Google I/O 2023 was a major event for the company, and it showcased Google's commitment to innovation. The announcements at I/O 2023 will have a significant impact on the tech industry, and they will help Google to continue to grow its business in the years to come.</p>
<p>In this article, we will take a look at the major announcements made at Google I/O 2023. We will discuss the new hardware products, software features, and cloud computing services that were announced. We will also discuss the potential benefits of these new technologies.</p>
<h2 id="heading-ai-updates">AI Updates</h2>
<p>Google also announced a number of new AI and machine learning features. These include a new AI language model called PaLM 2, which is capable of generating text, translating languages, and writing different kinds of creative content. Google also announced a new AI-powered search feature called Search Generative Experience, which allows users to generate different creative text formats of text content, like poems, code, scripts, musical pieces, email, letters, etc.</p>
<h3 id="heading-palm2">PaLM2</h3>
<p>PaLM 2 is a new AI language model that is built on top of Google's Pathways system. Pathways is a new AI architecture that is designed to be more efficient and scalable than previous AI architectures. PaLM 2 is trained on a massive dataset of text and code, and it can generate text, translate languages, and write different kinds of creative content.</p>
<h3 id="heading-search-generative-experience">Search Generative Experience</h3>
<p>Search Generative Experience is a new AI-powered search feature that allows users to generate different creative text formats of text content, like poems, code, scripts, musical pieces, email, letters, etc. Search Generative Experience uses PaLM 2 to generate text content based on a user's query. For example, if a user searches for "poem about love," Search Generative Experience will generate a poem about love.</p>


<p>The new AI and machine learning features announced at I/O 2023 show that Google is continuing to invest heavily in these technologies. These new features have the potential to revolutionize the way we interact with computers and the way we access information.</p>
<p>Here are some of the potential benefits of the new AI and machine learning features announced at I/O 2023:</p>
<ul>
<li><p>More personalized experiences: AI and machine learning can be used to personalize experiences for users. For example, Search Generative Experience can generate text content that is tailored to a user's interests.</p>
</li>
<li><p>More efficient workflows: AI and machine learning can be used to automate tasks and make workflows more efficient. For example, PaLM 2 can be used to generate code, which can save developers time and effort.</p>
</li>
<li><p>New creative possibilities: AI and machine learning can be used to create new creative possibilities. For example, Search Generative Experience can be used to generate poems, code, scripts, musical pieces, email, letters, etc.</p>
</li>
</ul>


<h3 id="heading-project-tailwind">Project Tailwind</h3>
<p>Google's Project Tailwind is an AI-powered notebook that learns from your documents. It can summarize your notes, generate a study guide, and answer natural language questions. Tailwind is still in development, but it has the potential to be a powerful tool for students, writers, and anyone who deals with a lot of text in their life.</p>
<p>To use Tailwind, you first need to pick files from your Google Drive. Tailwind then creates a private AI model with expertise in that information. You can then ask Tailwind questions about your notes, and it will provide answers based on its model. Tailwind can also summarize your notes, generate a study guide, and answer natural language questions.</p>
<p>Tailwind is currently in beta and is only available in the United States. You can join the waitlist to try it out here: https://thoughtful.withgoogle.com/about</p>


<h2 id="heading-cloud-computing-updates">Cloud Computing Updates</h2>
<p>Google also announced a number of new cloud computing features. These include a new A3 supercomputer virtual machine, which is designed for resource-intensive workloads. Google also announced a number of new features for Google Cloud Platform, such as a new machine learning API and a new container orchestration service.</p>
<h3 id="heading-a3-supercomputer-virtual-machine">A3 Supercomputer Virtual Machine</h3>
<p>The A3 supercomputer virtual machine is a new Google Cloud Platform offering that is designed for resource-intensive workloads. The A3 VM is powered by Nvidia A100 GPUs, and it offers up to 480GB of memory and 1.6TB of storage. The A3 VM is ideal for workloads such as machine learning, artificial intelligence, and high-performance computing.</p>
<h3 id="heading-new-machine-learning-api">New Machine Learning API</h3>
<p>Google announced new generative AI cloud capabilities that open the door for developers with all different skill levels to build enterprise-ready applications. These capabilities include Imagen, a new image generation and customization model; Codey, a new code generation model; and Chirp, a universal speech model that brings speech-to-text accuracy to 100+ languages.</p>
<p><strong>Duet AI for Google Cloud</strong>: Google also announced Duet AI for Google Cloud, an AI-powered collaborator that helps with contextual code completion, generates functions in real time, offers suggestions tuned to your code base, assists with code reviews and more.</p>
<p><strong>New Safe Browsing API</strong>: Google announced a new Safe Browsing API that uses AI to identify and alert you to dangerous sites and files, stopping scams before they happen.</p>
<p><strong>Expanded spam protections in Google Drive</strong>: Google is expanding spam protections in Google Drive with a new view that makes it easier to review files and decide what you might view as spam.</p>
<p><strong>Expanded access to dark web report</strong>: Google is expanding access to its dark web report over the next few weeks so anyone with a Gmail account in the U.S. can scan to see if their Gmail address appears on the dark web.</p>


<h3 id="heading-new-container-orchestration-service">New Container Orchestration Service</h3>
<p>Google also announced a new container orchestration service at I/O 2023. The new service makes it easier for developers to deploy and manage containers. The service offers a number of features, such as automatic scaling, load balancing, and fault tolerance.</p>
<p>The new cloud computing features announced at I/O 2023 show that Google is continuing to invest heavily in cloud computing. These new features make it easier for developers to build and deploy applications that are scalable, reliable, and secure.</p>
<p>Here are some of the potential benefits of the new cloud computing features announced at I/O 2023:</p>
<ul>
<li><p>Increased scalability: The new A3 supercomputer virtual machine can handle even the most resource-intensive workloads.</p>
</li>
<li><p>Improved reliability: The new container orchestration service makes it easier to deploy and manage containers, which can help to improve the reliability of applications.</p>
</li>
<li><p>Enhanced security: The new machine learning API can help to improve the security of applications by making it easier to identify and prevent attacks.</p>
</li>
</ul>
<h2 id="heading-new-software">New Software</h2>
<p>Google also announced a number of new software features. These include Android 14, Google Maps Immersive View, and Google Assistant improvements.</p>
<h3 id="heading-android-14">Android 14</h3>
<p>Android 14 is the next major version of Android, and it includes a number of new features, such as a new design, privacy improvements, and new productivity features.</p>
<p>The new design for Android 14 is based on Material You, and it includes a number of new features, such as new colors, new widgets, and new animations.</p>
<p>The privacy improvements in Android 14 include a new privacy dashboard, which allows users to see how their data is being used by apps. Android 14 also includes a new feature called "privacy indicators," which shows users when an app is accessing their microphone or camera.</p>
<p>The productivity features in Android 14 include a new multitasking menu, which makes it easier for users to switch between apps. Android 14 also includes a new feature called "desk clock," which allows users to use their phone as a second monitor.</p>


<h3 id="heading-google-maps-immersive-view">Google Maps Immersive View</h3>
<p>Google Maps Immersive View is a new feature that allows users to see a more realistic view of a location before they visit it. Immersive View uses 3D imagery and artificial intelligence to create a realistic representation of a location. This can be helpful for users who are planning a trip or who are trying to decide where to eat.</p>


<h3 id="heading-google-assistant-improvements">Google Assistant Improvements</h3>
<p>Google Assistant is getting a number of new features, such as the ability to translate languages in real time and the ability to control smart home devices with your voice.</p>
<p>The ability to translate languages in real time is a major new feature for Google Assistant. This will allow users to have conversations with people who speak other languages. The ability to control smart home devices with your voice is another major new feature for Google Assistant. This will allow users to control their smart home devices without having to touch their phone or tablet.</p>
<h2 id="heading-new-hardware">New hardware</h2>
<p>In addition to announcing new software products at I/O 2023, Google announced a number of new hardware products at I/O 2023, including the Pixel Fold, the Pixel Tablet, and the Pixel 7A. The Pixel Fold is Google's first foldable phone, and it features a 7.6-inch OLED display when unfolded. The Pixel Tablet is Google's first tablet in years, and it will run on Android 13. The Pixel 7A is a budget-friendly phone that will be available later this year.</p>
<h3 id="heading-the-pixel-fold">The Pixel Fold</h3>
<p>The Pixel Fold is Google's first foldable phone, and it features a 7.6-inch OLED display when unfolded. The phone is powered by Google's Tensor G2 chip and has a triple-lens rear camera system. The Pixel Fold is expected to be available later this year.</p>


<h3 id="heading-the-pixel-tablet">The Pixel Tablet</h3>
<p>The Pixel Tablet is Google's first tablet in years, and it will run on Android 13. The tablet has a 10.95-inch display and is powered by Google's Tensor G2 chip. The Pixel Tablet is expected to be available later this year.</p>



<h3 id="heading-the-pixel-7a">The Pixel 7A</h3>
<p>The Pixel 7A is a budget-friendly phone that will be available later this year. The phone has a 6.1-inch OLED display and is powered by Google's Tensor G2 chip. The Pixel 7A also has a dual-lens rear camera system.</p>
<p>The new hardware products announced at I/O 2023 show that Google is continuing to innovate and expand its product portfolio. The Pixel Fold and the Pixel Tablet are both new and exciting devices that offer a unique experience. The Pixel 7A is a great option for budget-minded consumers.</p>



<h2 id="heading-conclusion">Conclusion</h2>
<p>Google I/O 2023 was a major event for the tech industry, and it showcased Google's commitment to innovation. The announcements at I/O 2023 will have a significant impact on the way we interact with computers and the way we access information.</p>
<p>The new hardware products, software features, and cloud computing services announced at I/O 2023 have the potential to make our lives easier, more efficient, and more creative. They also have the potential to revolutionize the way we do business and the way we learn.</p>
<p>Google is a company that is constantly pushing the boundaries of what is possible. With its continued investment in innovation, Google is sure to continue to shape the future of technology.</p>


]]></content:encoded></item><item><title><![CDATA[Hitchhiker's Guide to mastering ChatGPT]]></title><description><![CDATA[Prompt Engineering
In this blog post, we will discuss the concept of prompt engineering and how it can be used in AI applications. Prompt engineering is a technique that allows AI systems to automatically generate descriptions of tasks they are asked...]]></description><link>https://tanseersaji.com/hitchhikers-guide-to-mastering-chatgpt</link><guid isPermaLink="true">https://tanseersaji.com/hitchhikers-guide-to-mastering-chatgpt</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Fri, 05 May 2023 16:27:15 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-prompt-engineering">Prompt Engineering</h2>
<p>In this blog post, we will discuss the concept of prompt engineering and how it can be used in AI applications. Prompt engineering is a technique that allows AI systems to automatically generate descriptions of tasks they are asked to perform. This can be useful for tasks such as understanding natural language or performing automated reasoning.</p>
<p>Prompts can come in many forms, including questions posed by humans or data sets provided by other machines. In general, prompts should be easy for the AI system to understand and answer correctly. Additionally, prompts should provide enough information so that the AI system knows what task it needs to complete in order to satisfy the user's request.</p>
<p>Prompt engineering is a relatively new field of research, but it has already been used in several applications. For example, Google's search engine uses prompts to help users find information on the web. In this case, the prompt is a question posed by the user and the search engine's response is a list of relevant web pages.
Another example of prompt engineering is when you use ChatGPT to find answers to your questions. In this case, the prompt is a question posed by the user and ChatGPT's response is an answer to that question.</p>
<h2 id="heading-large-language-models-llm">Large Language Models (LLM)</h2>
<p>Large language models are a type of machine learning model that is used to learn how to generate text from data. They are often used for tasks such as predicting the next word in a sentence or understanding the meaning of a document.</p>
<p>A large language model can be thought of as an artificial neural network that is designed to handle large amounts of data. This allows it to learn how to generate text from scratch, rather than just using pre-existing examples.</p>
<p>This type of model has been shown to be more effective than traditional machine learning models when it comes to dealing with complex texts and languages.</p>
<h3 id="heading-types-of-llm">Types of LLM</h3>
<ol>
<li><p>Base LLM: Base LLM does text continuation based on its knowledge of the language and the knowledge base provided. Examples of Base LLM include auto-completion.</p>
</li>
<li><p>Instruction-Tuned LLM: Instruction-Tuned LLM reads the prompt, understands it, and gives an appropriate response. An example of an Instruction-Tuned LLM is ChatGPT.</p>
</li>
</ol>
<h2 id="heading-principles-of-prompt-engineering">Principles of Prompt Engineering</h2>
<h3 id="heading-be-clear-and-specific">Be clear and specific.</h3>
<p>When it comes to prompt engineering, it's crucial to ensure that the prompts used are specific and tailored to the task at hand. Specific prompts provide clear direction and guidance to the model, increasing the chances of generating high-quality responses.</p>
<p>To illustrate, a specific prompt for a language translation task might be: "Translate the following sentence from English to Spanish: 'The quick brown fox jumped over the lazy dog.'" This prompt provides the model with a clear objective and specific input to work with, resulting in a more accurate translation.</p>
<p>On the other hand, a non-specific prompt for the same task might be: "Translate some English sentences to Spanish." This prompt is vague and lacks direction, which can lead to a lower-quality output from the model.</p>
<p>In summary, specific prompts are essential in prompt engineering as they provide a clear objective and input for the model to work with, resulting in higher-quality output. Non-specific prompts can lead to ambiguity and lower-quality output.</p>
<h3 id="heading-ask-to-answer-in-a-specific-format">Ask to answer in a specific format</h3>
<p>Asking for the output in a specific format is a great way to ensure that the LLM's response is compatible with the systems and software being used. Here are some examples of specific prompts that request the output in different formats:</p>
<ol>
<li><p>JSON: "Provide a JSON object with the following fields: 'name', 'age', and 'email', and their respective values." This prompt would instruct the LLM to generate a JSON object that includes the specified fields and values.</p>
</li>
<li><p>XML: "Create an XML document that includes a root element called 'books' and child elements for 'title', 'author', and 'published_date'." This prompt would direct the LLM to generate an XML document that follows the specified structure and contains the specified elements.</p>
</li>
<li><p>HTML: "Generate an HTML table that displays the following data: 'Product Name', 'Price', and 'In Stock'." This prompt would instruct the LLM to create an HTML table that displays the specified data, likely for use on a website or in an email.</p>
</li>
</ol>
<p>By requesting specific formats like these, you can ensure that the LLM's response is easily integrated with other systems or software, saving time and effort in post-processing.</p>
<h3 id="heading-give-context-or-additional-information">Give context or additional information</h3>
<p>Providing context or information about the question being asked is a helpful way to improve the accuracy of the LLM's response. Here are some examples of how context or information about the question can be provided:</p>
<ol>
<li><p>Context: "In the context of a financial report, can you provide the revenue figures for the last quarter?" By specifying the context of the question, the LLM can better understand the purpose and scope of the request, leading to a more accurate response.</p>
</li>
<li><p>Information about the question: "Can you provide me with the definition of 'epistemology'?" By providing information about the kind of question being asked, the LLM can better understand the type of information being sought, and provide a more relevant and accurate response.</p>
</li>
<li><p>Clarification: "I'm looking for a hotel in New York City that is within walking distance of Times Square. Can you suggest any options?" By providing clarification about the request, the LLM can better understand the specific criteria being used to evaluate options, leading to a more accurate and relevant response.
In summary, providing context or information about the question being asked is a useful way to improve the accuracy of the LLM's response, by helping the model understand the purpose, scope, and criteria of the request.</p>
</li>
</ol>
<h3 id="heading-reframe-the-question-prompt">Reframe the question (prompt)</h3>
<p>If the LLM is not giving the desired output, providing additional information or reframing the question can often help improve the quality of the response. Here are some examples of how this can be done:</p>
<ol>
<li><p>Providing additional information: "Can you recommend a good restaurant in the downtown area of San Francisco?" If the LLM's initial response is not helpful, providing additional information such as the type of cuisine or price range you are looking for can help the model better understand your preferences and provide a more relevant recommendation.</p>
</li>
<li><p>Reframing the question: "What is the best way to approach a difficult conversation with a colleague?" If the LLM's initial response is not helpful, reframing the question to provide more specific or actionable information can help the model provide a more useful response.</p>
</li>
<li><p>Asking follow-up questions: "Can you explain more about what you mean by 'successful marketing campaign'?" If the LLM's initial response is vague or unclear, asking follow-up questions can help clarify the request and improve the quality of the response.</p>
</li>
</ol>
<p>By providing additional information, reframing the question, or asking follow-up questions, you can help the LLM better understand your needs and provide a more accurate and relevant response.</p>
<h2 id="heading-limitation">Limitation</h2>
<p>One of the known limitations of language models, including LLMs, is that they may generate responses that contain inaccuracies or make up information if the question asked is beyond their knowledge base or the data they were trained on. This is because LLMs rely on statistical patterns in the data they have been trained on to generate responses, and if the input is outside their training data, they may not have enough information to provide a meaningful or accurate response.</p>
<p>Furthermore, all language models, including LLMs, are limited by the quality and quantity of data they were trained on. If the training data is biased, incomplete, or inaccurate, the LLM's responses may also be biased, incomplete, or inaccurate. Additionally, if the training data is limited in scope, the LLM may not be able to generate responses that are relevant or useful for a wide range of tasks or applications.</p>
<p>To address these limitations, it's important to carefully evaluate the accuracy and relevance of the LLM's responses and to continue to train and refine the model using high-quality data that reflects a diverse range of perspectives and use cases. By doing so, we can continue to improve the accuracy and usefulness of LLMs and other language models.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, Language Models, especially the recently popular LLMs, have the potential to revolutionise the way we interact with natural language. However, like any other technology, they also have their limitations. To make the most of these models, it's important to understand their strengths and limitations and to use them in conjunction with other tools and methods to achieve optimal results.</p>
<p>Some ways to optimize the use of LLMs include providing specific and relevant prompts, providing context or information about the question or task, and reframing the question or asking follow-up questions if the initial response is not helpful. Additionally, it's important to be aware of the limitations of these models, such as their tendency to generate inaccurate responses if the input is beyond their knowledge base, or if the training data is biased or incomplete.</p>
<p>To overcome these limitations, we need to continue to train and refine LLMs using high-quality data that reflects a diverse range of perspectives and use cases. With careful use and continued refinement, LLMs have the potential to improve many areas of our lives, including communication, education, and research.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Three js - Hello World]]></title><description><![CDATA[For the past few years there is a boom in new kind of websites that incorporate 3D elements right into your browser with flawless rendering frame rates. No, I'm not talking about CSS 3D transformations, I'm talking about 3D graphics created in softwa...]]></description><link>https://tanseersaji.com/introduction-to-three-js-hello-world</link><guid isPermaLink="true">https://tanseersaji.com/introduction-to-three-js-hello-world</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Fri, 09 Jul 2021 04:22:00 GMT</pubDate><content:encoded><![CDATA[<p>For the past few years there is a boom in new kind of websites that incorporate 3D elements right into your browser with flawless rendering frame rates. No, I'm not talking about CSS 3D transformations, I'm talking about 3D graphics created in software like Blender or Maya embedded in your website. This is possible due to WebGL, a Javascript API to OpenGL which lets us run website elements directly on the client's Graphics Processing Unit. I'm not specifically refering to graphic cards because this will also run on the Graphics embedding on a CPU.</p>
<p>But coding directly in WebGL is nothing less than doing self-harm. That's where <a target="_blank" href="https://threejs.org/">Three JS</a> comes into play. This Javascript library takes care of all the painful elements of WebGL and provides an abstracted syntactic sugar for us to work with. We will see in later posts, how we can make custom functions in WebGL and append that to Three js to extend its functionalities.</p>
<p>Before we begin, take a look at some of these amazing websites built using Three.js</p>
<ol>
<li><a target="_blank" href="https://github.com/home">Github Homepage</a></li>
<li><a target="_blank" href="https://bruno-simon.com/">Bruno Simon Portfolio</a></li>
<li><a target="_blank" href="https://lusion.co/">Lusion Co</a></li>
<li><a target="_blank" href="https://particle-love.com/">Particle Love by Edan Kwan</a></li>
</ol>
<p>You can see a lot more of these real world usage of Three js over at <a target="_blank" href="https://threejs.org/">Three JS Website</a></p>
<h2 id="heading-initial-setup">Initial Setup</h2>
<p>There are three ways to embed Three.js to your website. (Coincidence)</p>
<h3 id="heading-option-1-cloning-three-js-github-repository">Option 1 - Cloning Three js Github Repository</h3>
<p>Before doing this, I recommend you to create a folder structure for all your projects. Otherwise, it will be hard for you to find something in the future. Once that is done. Simply clone the repository to  your desired folder.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/mrdoob/three.js.git three
</code></pre>
<h3 id="heading-option-2-three-js-cdn">Option 2 - Three js CDN</h3>
<p>This would be the easiest way to start, just embed this script to your webpage</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/three.js/r126/three.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha512-n8IpKWzDnBOcBhRlHirMZOUvEq2bLRMuJGjuVqbzUJwtTsgwOgK5aS0c1JA647XWYfqvXve8k3PtZdzpipFjgg=="</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>But as you will see later, the core Three js library only include simple shapes, textures and materials. If you want to add an external model or do something that is not included in this js file then you need to import those specific files too. And in a real world project, by using this method you will end up importing way too much files that you won't even fully utilize.</p>
<h3 id="heading-option-3-three-js-project-starter-kit">Option 3 - Three js Project Starter Kit</h3>
<p>My Three js sensei, <a target="_blank" href="https://bruno-simon.com/">Bruno Simon</a>, provided us a starter pack that uses webpack to assemble all packages. I took that as base and created a three js starter kit for myself so that I don't have to write the boilerplate code everytime. You can use this kit by using the following git command.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/Idiomatic-Programmers/threejs_starter_kit.git &lt;YOUR_PROJECT_NAME&gt;
</code></pre>
<p>Don't forget to replace  with something meaningful to your project.</p>
<p>If you haven't already, you need to install Node.js and NPM for this to work. Checkout <a target="_blank" href="https://nodejs.org/en/">Node JS Documentation</a> for more information.</p>
<h2 id="heading-setting-up-your-first-project">Setting up your first project</h2>
<p>For demonstration purpose, I am going to name our project "Hello World"</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/Idiomatic-Programmers/threejs_starter_kit.git hello_world
</code></pre>
<p>This will create a folder called hello_world inside which you will find all the starter code already written.</p>
<blockquote>
<p>FYI - If you want to learn and master Three js and can afford to buy a $95 course, checkout <a target="_blank" href="https://threejs-journey.xyz/?ref=idiomaticprogrammer.com">Bruno Simon's Three JS Journey</a>, it pretty great, very in-depth, and easy to follow along. Plus, you get access to a private Discord server where you can meet thousands of amazing developers and you can clear your doubts directly from Bruno. But if you can't afford it, then follow along. I will try my best to share the knowledge I gained from this course.</p>
</blockquote>
<p>Open the <strong>hello_world</strong> folder in your favourite code editor and navigate to <strong>script.js</strong> file located in src folder. Now select everything and just delete it because we will be coding just that.</p>
<p>Before we continue, don't forget to install the packages we need by doing.</p>
<pre><code class="lang-bash">npm install
</code></pre>
<p>The beauty of webpack is that we can do most of our things using Javascript without ever touching the HTML file. I'm assuming you have deleted everything from script.js file.</p>
<p>So in the very first line, import our css file</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> <span class="hljs-string">'./style.css'</span>
</code></pre>
<p>Then obviously we need to import our three js library.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> THREE <span class="hljs-keyword">from</span> <span class="hljs-string">'three'</span>
</code></pre>
<p>Before we write our next line of JS, let's understand the HTML structure of our project. If you open <strong>index.html</strong> in the src folder, you will find there's standard HTML boilerplate with a canvas element in the body. This canvas will render everything we do in three js, which means we must have a reference to this canvas element in out js file.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> webGLCanvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'webgl'</span>)
</code></pre>
<p>With these three lines in our js file, we can officially start writing our three js code. But first, let's learn some theory.</p>
<h2 id="heading-fundamental-elements-in-three-js">Fundamental Elements in Three JS</h2>
<p>Every three js project will contain these three elements.</p>
<h3 id="heading-a-scene">a. Scene</h3>
<p>In the genre of Film Making, a <strong>scene</strong> is a place or setting where the action takes place. A scene holds everything a movie needs. If you take an example from this amazing Steven Spielberg movie Catch me if you can.</p>


<p>This particular scene contains everything that is required to move the story forward.</p>
<p>Much like that, a scene in Three js will hold everything that is required to tell our story, cars, trains, builings, or even wierd 3D figures, everything that you need to show will be included in a scene.</p>
<h3 id="heading-b-camera">b. Camera</h3>
<p>Again taking the example of the aforementioned movie, a camera will only show a particular section of a scene that is required to tell the story.</p>
<p>In Three JS, there are two main types of camera,</p>
<ol>
<li><p><a target="_blank" href="https://threejs.org/docs/index.html?q=camera#api/en/cameras/PerspectiveCamera">Perspective Camera</a></p>
<p> A Perspective camera in three js is a Frustum Shape (3D Trapezoid) and the user will only be able to see what's inside this frustum. You can adjust the size of this Frustum to get the best results. And everything in the shape is <strong>Perspective Projected</strong> meaning farther objects appear smaller than nearer objects.</p>
<p> This camera simulates real world so we will be using this camera a lot in coming posts.</p>
<p> <img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925579/Perspective_Camera_Shape_m5fe90.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074683693/abe1d059-7c7d-454b-bab3-803362da4446.jpeg" /></p>
</li>
<li><p><a target="_blank" href="https://threejs.org/docs/index.html?q=camera#api/en/cameras/OrthographicCamera">Orthographic Camera</a></p>
<p> An Orthographic camera in Three js is a Box instead of a Frusturm like in Perspective Camera and it uses an Orthogonal Projection which means the size of the object remains same regardless of their distance from the camera. These type of cameras are useful to design maps of the environment.</p>
<p> <img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925666/Orthogonal_Camera_Shape_1_a2i5sb.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074685063/0fc553c8-e7f8-4108-80ae-4c08e799f07c.jpeg" /></p>
</li>
</ol>
<p>There are other type of cameras in three js but we won't be using them. But if you would still like to learn about them here's a list of all cameras linked to their documentation.</p>
<ol>
<li><a target="_blank" href="https://threejs.org/docs/api/en/cameras/ArrayCamera.html">ArrayCamera</a></li>
<li><a target="_blank" href="https://threejs.org/docs/api/en/cameras/CubeCamera.html">CubeCamera</a></li>
<li><a target="_blank" href="https://threejs.org/docs/index.html?q=camera#api/en/cameras/OrthographicCamera">OrthographicCamera</a></li>
<li><a target="_blank" href="https://threejs.org/docs/api/en/cameras/PerspectiveCamera.html">PerspectiveCamera</a></li>
<li><a target="_blank" href="https://threejs.org/docs/api/en/cameras/StereoCamera.html">StereoCamera</a></li>
</ol>
<h3 id="heading-c-renderer">c. Renderer</h3>
<p>A renderer is an element that displays whatever the camera sees onto a canvas. It is a screen on which the 3D scene is projected. And that is the only thing we need to know about this.</p>
<h2 id="heading-create-your-first-3d-environment">Create your first 3D environment</h2>
<p>Coming back to script.js file, we have three lines which imports everything we need.</p>
<p>Next we will proceed to define the three fundamental elements in three js.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> scene = <span class="hljs-keyword">new</span> THREE.Scene()
</code></pre>
<p>This will initiate an empty scene on our project, next we need a camera to see what's in a scene. We will be using Perspective Camera which takes in four main parameters.</p>
<ol>
<li><strong>Field of View (fov)</strong>:  This specifies how wide your camera can see, in degrees.</li>
<li><strong>Aspect Ratio (aspect):</strong>  As the name suggests, this specifies the aspect ratio of your scene. is it 16:9, 16:10, 4:3 etc. If you would like to find out more about aspect ratios, check <a target="_blank" href="https://support.squarespace.com/hc/en-us/articles/115008538927-Understanding-aspect-ratios#:~:text=An%20aspect%20ratio%20is%20a,and%20width%20are%20the%20same.">this article</a></li>
<li><strong>Near Distance (near) and Far Distance (far):</strong> These two parameters will specify the boundaries of the Frustum. You can only see those objects that are between the near and far values of the camera.</li>
</ol>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> sizes = {
    <span class="hljs-attr">width</span>: <span class="hljs-built_in">window</span>.innerWidth,
    <span class="hljs-attr">height</span>: <span class="hljs-built_in">window</span>.innerHeight
}
</code></pre>
<p>We will define an object that will contain the height and width of the renderer. Everything the camera sees in 3D will be projected to this 2D plane. In our case, the renderer will take up our entire screen.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> camera = <span class="hljs-keyword">new</span> THREE.PerspectiveCamera(<span class="hljs-number">75</span>, sizes.width / sizes.height, <span class="hljs-number">0.1</span>, <span class="hljs-number">1000</span>)
</code></pre>
<p>Notice for aspect ratio, we have set the ratio between renderer width and height. This is because we have no control over the aspect ratio of user device. If you are 100% sure that only people with devices that has a 16 by 9 ratio, then you simply write <strong>16 / 9</strong> instead of <strong>sizes.width / sizes.height</strong>  and you can experiment with the near and far values that work best for you. You can copy what I have written it doesn't matter, atleast for what we are doing.</p>
<p>Finally, we need a renderer. Three js provides many renderers, but we are only interested in one of them called WebGLRenderer which takes an object as a parameter that has many attributes that you can look at in <a target="_blank" href="https://threejs.org/docs/index.html?q=rend#api/en/renderers/WebGLRenderer">the documentation</a></p>
<p>For now, we will be passing one attribute called <strong>canvas</strong> which you guessed it, takes the reference to our canvas.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> renderer = <span class="hljs-keyword">new</span> THREE.WebGLRenderer({
    <span class="hljs-attr">canvas</span>: webGLCanvas
})
</code></pre>
<p>We also need to set the size of this renderer.</p>
<pre><code class="lang-jsx">renderer.setSize(sizes.width, sizes.height)
</code></pre>
<p>Alright, that's it. Let run our code. Run this code in your terminal</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925765/Untitled_ihcaiy.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074687066/6ad21a36-c68e-433e-b331-9f24cdbd975f.png" /></p>
<p>Wait, what? We only see a blank black screen? Let me check it there is any error in Inspect Element Console.</p>
<p>And my right click isn't working? What's happening?</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925796/pc8sZUC_b73ihw.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074688932/23796d4f-3085-4911-9eed-5f4cbe1a3e83.jpeg" /></p>
<p>I lied, we need to do a bit more work.</p>
<p>We need to add our camera into the scene.</p>
<pre><code class="lang-jsx">scene.add(camera)
</code></pre>
<p>and actually render the scene. You can do this by calling the render method of renderer and pass the scene and camera into it.</p>
<pre><code class="lang-jsx">renderer.render(scene, camera)
</code></pre>
<p>Now save and refresh the page. Still a black screen? It's completely normal. Remember the scene currently contains a camera and we can only see what the camera see and there's nothing else to see.</p>
<p>If you don't like this black screen then you can change the background colour of the scene like this.</p>
<pre><code class="lang-jsx">scene.background = <span class="hljs-keyword">new</span> THREE.Color(<span class="hljs-string">"#f7f7f7"</span>)
</code></pre>
<p>You cannot directly pass the hex code, you need to wrap it around a THREE.Color object.</p>
<p>If you refresh your page now, you can see the background has been changed to nice light greyish colour.</p>
<p>Now let's create a Sphere.</p>
<p>You need three things to create any object in Three js.</p>
<ol>
<li><strong>Geometry:</strong> This holds a general shape of the object</li>
<li><strong>Material:</strong> This hold information about the texture, color, opacity, etc.</li>
<li><p><strong>Mesh:</strong> This combines the Geometry and Material into an object.</p>
<p>Three js provides Geometry for almost all basic shapes like sphere, box, torus, etc. For making a sphere, there is something called SphereBufferGeometry that takes three parameters.</p>
</li>
<li><p><strong>Radius:</strong> The radius of the sphere</p>
</li>
<li><strong>Width Segments</strong></li>
<li><strong>Height Segments</strong></li>
</ol>
<p>Don't worry about Width and Height segments now, I will show you once we built our Sphere.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> sphereGeometry = <span class="hljs-keyword">new</span> THREE.SphereBufferGeometry(<span class="hljs-number">1</span>, <span class="hljs-number">32</span>, <span class="hljs-number">32</span>)
</code></pre>
<p>We have a radius of 1 units and 32 Width and Height segments.</p>
<p>In three JS, it'd better to decide what a unit is. For me 1 unit is 1 meter.</p>
<p>Then we need a Material, we will see different type of materials provide by Three JS and also you can create your own material using a laguage called GLSL (OpenGL Shading Language). But for now, we'll use MeshStandardMaterial</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> sphereMaterial = <span class="hljs-keyword">new</span> THREE.MeshStandardMaterial()
sphereMaterial.color = <span class="hljs-keyword">new</span> THREE.Color(<span class="hljs-string">"#ffffff"</span>)
</code></pre>
<p>We can set the colour of this material by updating the color attribute. Also, remember we need to pass color as a THREE.Color object.</p>
<p>Finally, we will create a mesh using THREE.Mesh and pass in our geometry and material.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> sphere = <span class="hljs-keyword">new</span> THREE.Mesh(sphereGeometry, sphereMaterial)
</code></pre>
<p>And don't forget to add the sphere to scene.</p>
<pre><code class="lang-jsx">scene.add(sphere)
</code></pre>
<p>One last thing, you should always render the scene at the end of the script, so move this line to the end.</p>
<pre><code class="lang-jsx">renderer.render(scene, camera)
</code></pre>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925850/Untitled_1_zxdkbt.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074690225/ada525e2-a674-4f15-b91a-61b35cd00125.png" /></p>
<p>Nothing? Don't worry. Right now your camera is inside the Sphere.</p>
<p>Three js calulates the distance between a vertex and the camera, if that distance is less that near or far parameters of the camera then that object will not be shown. In this case, the distance between Sphere and Camera is 0 and since it is smaller than the near parameter which is 0.1, the sphere will not be shown.</p>
<p>We can move back our camera by moving it few units towards positive z direction.</p>
<pre><code class="lang-jsx">camera.position.z = <span class="hljs-number">5</span>
</code></pre>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925879/Untitled_2_pbcmjx.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074691515/533e23f6-0b8b-4512-bf67-f356aa416088.png" /></p>
<p>Now you can see a Black circle. But why is it black? We did set the color as White (#ffffff).</p>
<p>Some of you might have guessed it. We have no light </p>
<p>Three js actually has this amazing method called letThereBeLight(), which automatically adds all the light we want.</p>
<p>Just Kidding, life isn't that simple, let us actually add some light to our scene.</p>
<p>We will see all kind of light throughout this series, but for now we will look at a light called Directional Light, which gives parallel rays of light just like our Sun.</p>
<p>The DirectionalLight takes two parameters, the color of the light, which will be a Hex code and the intensity of the light.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> directionalLight = <span class="hljs-keyword">new</span> THREE.DirectionalLight(<span class="hljs-string">"#ffffff"</span>, <span class="hljs-number">0.5</span>)
scene.add(directionalLight)
</code></pre>
<p>Always remember to add your objects to scene.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925901/Untitled_3_d05oi9.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074692682/19092386-e89a-4e4d-ac27-dcb17e66d86e.png" /></p>
<p>We can see some light at the top, but actually the light is inside the sphere. Let's move it using position method of the object.</p>
<p>For any object in three js, you can move it using one of two ways</p>
<ol>
<li>Changing the x, y, z positions one by one</li>
</ol>
<pre><code class="lang-jsx">directionalLight.position.x = <span class="hljs-number">30.25</span>
directionalLight.position.y = <span class="hljs-number">30</span>
directionalLight.position.z = <span class="hljs-number">30</span>
</code></pre>
<ol start="2">
<li>Using set() method:</li>
</ol>
<pre><code class="lang-jsx">directionalLight.position.set(<span class="hljs-number">30.25</span>, <span class="hljs-number">30</span>, <span class="hljs-number">30</span>)
</code></pre>
<p>You can use whatever method, which you feel is right.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925929/Untitled_4_r8q6tf.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074694503/77f5b793-1356-4030-9ab6-618ca00f552f.png" /></p>
<p>This is better. But there is very harsh shadow. Let's introduce a new kind of light to fix this issue called Ambient Light.</p>
<p>Ambient Light adds the same amount of light everywhere in the scene, and it does not cast any shadow. Using AmbientLight is similar to Directional light, the only difference is that you don't have to move it around.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> ambientLight = <span class="hljs-keyword">new</span> THREE.AmbientLight(<span class="hljs-string">"#ffffff"</span>, <span class="hljs-number">0.5</span>)
scene.add(ambientLight)
</code></pre>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616925950/Untitled_5_j5chyt.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074696507/c1af7f66-043a-4524-a5a0-9b05506a15d7.png" /></p>
<p>And there it is, a beautiful Sphere suspended in our scene.</p>
<h2 id="heading-resizing">Resizing</h2>
<p>If we resize the window, you'll notice that the canvas is not changing it's size. We need to do bit of work to fix that.</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'resize'</span>, <span class="hljs-function">() =&gt;</span>
{
    <span class="hljs-comment">// Update sizes</span>
    sizes.width = <span class="hljs-built_in">window</span>.innerWidth
    sizes.height = <span class="hljs-built_in">window</span>.innerHeight

    <span class="hljs-comment">// Update camera</span>
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()

    <span class="hljs-comment">// Update renderer</span>
    renderer.setSize(sizes.width, sizes.height)
})
</code></pre>
<p>We have created a resize event listener and just updated the aspect ratio and renderer size. We also need to tell the camera to recalculate its projections, which is done by the updateProjectionMatrix() method.</p>
<h1 id="heading-animation">Animation</h1>
<p>It wouldn't be fun if we don't animate our sphere. Let's create a function called animate() and inside that call the renderer.render method. Make sure that you are writing this code at the end of your script.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> animate = <span class="hljs-function">() =&gt;</span> {
    renderer.render(scene, camera)
}

animate()
</code></pre>
<p>This is not enough, We need to tell our browser that we wish to animate our scene. Which can be done by calling the window.requestAnimationFrame method and pass it reference to our animate function.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> animate = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">window</span>.requestAnimationFrame(animate)
    renderer.render(scene, camera)
}

animate()
</code></pre>
<p>Animating our scene isn't that simple as calling requestAnimationFrame. We need to figure our some math for that.</p>
<p>For our scene, I'm thinking to animate Sphere up and down in a smooth motion. This can be done by using the <strong>sine function</strong> in trigonometry. But before that, we need some way to tell the passage of time. Conveniently, Three js provides a class for that called Clock.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> clock = <span class="hljs-keyword">new</span> THREE.Clock()
</code></pre>
<p>We can get the elapsed time by calling the getElapsedTime method of the clock object.</p>
<p>Write this code in our animate function.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> elapsedTime = clock.getElapsedTime()

sphere.position.y = <span class="hljs-built_in">Math</span>.sin(elapsedTime * <span class="hljs-number">150</span> * <span class="hljs-built_in">Math</span>.PI / <span class="hljs-number">180</span>) * <span class="hljs-number">0.125</span>
</code></pre>
<p>Save this and view the page, your sphere will be moving Up and Down smoothly.</p>


<p>You can play with the math and change the axis, and see what happens.</p>
<p>Before we leave, take a look at what we will be building throughout this series.</p>
<p>You can check out the <a target="_blank" href="https://webglaudiodemo.netlify.app/">live demo website</a></p>


<p>That is all for this post, in the next post we will explore some few more shapes, materials, cameras and lights. If you have any query be sure to comment below, we will get back at you as soon as possible,</p>
]]></content:encoded></item><item><title><![CDATA[How to download Pandas Dataframe as Excel or CSV in Django?]]></title><description><![CDATA[Introduction
Pandas is an essential tool used by Python developers used for data analysis purposes, but what is the point of the analysis if we are not able to provide that insight to the end user. When Django and Pandas are used in conjunction we ca...]]></description><link>https://tanseersaji.com/how-to-download-pandas-dataframe-as-excel-or-csv-in-django</link><guid isPermaLink="true">https://tanseersaji.com/how-to-download-pandas-dataframe-as-excel-or-csv-in-django</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Sat, 27 Mar 2021 03:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Pandas is an essential tool used by Python developers used for data analysis purposes, but what is the point of the analysis if we are not able to provide that insight to the end user. When Django and Pandas are used in conjunction we can create applications that are not only developed faster, but are also smart in utilizing the data that is collected from the user. I recently stumbled on one such use case, where the user interacts with the frontend and turns some filters and then the backend processes that data, and then provide the aggregated data as an Excel or CSV file to the user. I will be describing how I went about doing that below.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>In order to follow along this article, I am assuming you already have a Django project that is using Pandas library ready.</p>
<ol>
<li><a target="_blank" href="https://www.djangoproject.com/start/">Django Documentation</a></li>
<li><a target="_blank" href="https://pandas.pydata.org/docs/">Pandas Documentation</a></li>
</ol>
<h2 id="heading-requirements">Requirements</h2>
<p>In addition to Django and Pandas project ready, you would need to install Openpyxl.</p>
<h3 id="heading-openpyxl">Openpyxl</h3>
<p><a target="_blank" href="https://openpyxl.readthedocs.io/en/stable/">Openpyxl</a> is a tool that allows to read and write Open Office XML formats such as Excel 2010 xlsx/xlsm/xltx/xltm files.</p>
<pre><code class="lang-bash">pip install openpyxl
</code></pre>
<p>Once installed, you can create Excel files natively from Python using a simple code like this.</p>
<pre><code class="lang-bash">from openpyxl import Workbook

workbook = Workbook()
sheet = workbook.active

sheet[<span class="hljs-string">"A1"</span>] = <span class="hljs-string">"ID"</span>
sheet[<span class="hljs-string">"B1"</span>] = <span class="hljs-string">"Key"</span>

sheet[<span class="hljs-string">"A2"</span>] = 1
sheet[<span class="hljs-string">"B2"</span>] = <span class="hljs-string">"Test Key"</span>

workbook.save(filename=<span class="hljs-string">"test.xlsx"</span>)
</code></pre>
<p>This will create a file called <strong>"test.xlsx".</strong> Try it out yourself.</p>
<h2 id="heading-http-response">HTTP Response</h2>
<p>As you know, Django uses HTTP Request and Response to communicate with the client. Therefore all data must be converted to Byte String before sending it over to the client.</p>
<p>A Typical HTTP Response looks something like this.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1616226497/httpmsgstructure2_htshjp.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074537827/5e3645e8-4992-4125-a57c-bf032645926b.png" />
For more information, checkout this article by Mozilla about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages">HTTP Messages</a>.</p>
<p>As you can see in the above picture, every HTTP response has a body section which is a Byte Array and a Header called <strong>Content-Type</strong> specifies what type of content it is and which character set the browser should use in order to decode the bytes. In the above case, the server is sending a text/html data and the browser need to use iso-8859-1 charset.</p>
<p>In our case, we are sending bytes that are related to Excel spreadsheets. So googling for a bit I found the content-type header for that is this. Source: Mozilla article about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types">Common MIME Types</a></p>
<pre><code>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
</code></pre><h3 id="heading-what-are-mime-types"><strong>What are MIME Types?</strong></h3>
<p>MIME is short for <strong>Multipurpose Internet Mail Extensions</strong> which is a standard that indicates the nature and format of a document sent via the Internet.</p>
<blockquote>
<p><strong>Important</strong>: Browsers use the MIME type, not the file extension, to determine how to process a URL, so it's important that web servers send the correct MIME type in the response's <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type">Content-Type header</a>. If this is not correctly configured, browsers are likely to misinterpret the contents of files and sites will not work correctly, and downloaded files may be mishandled.</p>
</blockquote>
<p>For more information, checkout MDN Article about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME Types</a></p>
<p>The structure of a MIME Type is according to <a target="_blank" href="https://www.iana.org/">IANA (Internet Assigned Numbers Authority)</a> is like this.</p>
<pre><code>type/subtype
</code></pre><p>Therefore, in the MIME Type for Excel files, the type is "<strong>application",</strong> which belongs to any kind of binary data that cannot be directly decoded to a human-readable form (text, HTML, etc.). Files with type application require some sort of external or third party software to decode and read such as PDFs, Zip files, Excel files, etc.</p>
<h2 id="heading-download-excel-files-using-django-and-pandas">Download Excel Files using Django and Pandas</h2>
<p>Finally, we will see how we can send the Pandas dataframe to client as an excel file.</p>
<p>I am assuming that you already have the code for pandas so I will do some abstraction in a variable called data.</p>
<p>First we will import to the inbuilt library, <a target="_blank" href="https://docs.python.org/3/library/io.html#binary-i-o">BytesIO</a> so that we can write the excel file as a Byte array.</p>
<p>BytesIO is a library using which we can write data onto system memory instead of writing them as a file.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO
</code></pre>
<p>Then we will use Python <a target="_blank" href="https://book.pythontips.com/en/latest/context_managers.html">context manager</a> to open a Byte buffer on which we can write the excel file. Context Managers allow you to allocate and release memory precisely when you want it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> BytesIO() <span class="hljs-keyword">as</span> b
    <span class="hljs-keyword">with</span> pd.ExcelWriter(b) <span class="hljs-keyword">as</span> writer:
        <span class="hljs-comment"># You can add multiple Dataframes to an excel file</span>
        <span class="hljs-comment"># Using the sheet_name attribute</span>
      data1.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 1"</span>, index=<span class="hljs-literal">False</span>)
        data2.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 2"</span>, index=<span class="hljs-literal">False</span>)

    filename = <span class="hljs-string">"analytics_data.xlsx"</span>

    <span class="hljs-comment"># imported from django.http</span>
    res = HttpResponse(
        b.getvalue(), <span class="hljs-comment"># Gives the Byte string of the Byte Buffer object</span>
        content_type=<span class="hljs-string">'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'</span>
    )
    res[<span class="hljs-string">'Content-Disposition'</span>] = <span class="hljs-string">f'attachment; filename=<span class="hljs-subst">{filename}</span>'</span>
    <span class="hljs-keyword">return</span> res
</code></pre>
<p>We will be using context managers to open and close files because that's more efficient than manually closing and releasing the memory after use. If you already know how to <a target="_blank" href="https://pandas.pydata.org/docs/reference/api/pandas.ExcelWriter.html">export a set of data frames as an excel file</a>, that code should look like this.</p>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> pd.ExcelWriter(<span class="hljs-string">'data.xlsx'</span>) <span class="hljs-keyword">as</span> writer:
    data1.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 1"</span>, index=<span class="hljs-literal">False</span>)
    data2.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 2"</span>, index=<span class="hljs-literal">False</span>)
</code></pre>
<p>We will simply take this code and wrap it around a BytesIO context manager which gives us a memory buffer <code>b</code> as a file to work with. We will simply take that memory buffer and pass it to <code>pd.ExcelWriter()</code> class and the rest of the code will be the same this that context manager.</p>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> BytesIO() <span class="hljs-keyword">as</span> b
    <span class="hljs-keyword">with</span> pd.ExcelWriter(b) <span class="hljs-keyword">as</span> writer:
      data1.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 1"</span>, index=<span class="hljs-literal">False</span>)
        data2.to_excel(writer, sheet_name=<span class="hljs-string">"DATA 2"</span>, index=<span class="hljs-literal">False</span>)
</code></pre>
<p>Now that we have our Excel data written in a memory buffer, we can simply convert that to ByteArray using the method <code>b.getvalue()</code> which we will pass as a parameter in Django <code>HttpResponse</code> with appropriate <code>content_type</code> that we discussed earlier. </p>
<pre><code class="lang-python">filename = <span class="hljs-string">"analytics_data.xlsx"</span>

<span class="hljs-comment"># imported from django.http</span>
res = HttpResponse(
  b.getvalue(), <span class="hljs-comment"># Gives the Byte string of the Byte Buffer object</span>
  content_type=<span class="hljs-string">'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'</span>
)
</code></pre>
<p>In addition to the Content-Type  header, we also need to provide another header called <strong><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition">Content-Disposition</a></strong> that tells the browser if we want to show the data in the browser download and save it as a local file as an attachment. We can also pass a filename with this header.</p>
<pre><code class="lang-python">res[<span class="hljs-string">'Content-Disposition'</span>] = <span class="hljs-string">f'attachment; filename=<span class="hljs-subst">{filename}</span>'</span>
<span class="hljs-keyword">return</span> res
</code></pre>
<p>Here is the complete code snippet for Django view to download the excel file.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_analytics_endpoint</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">with</span> BytesIO() <span class="hljs-keyword">as</span> b:
        data = get_analytics_data()

        <span class="hljs-keyword">with</span> pd.ExcelWriter(b) <span class="hljs-keyword">as</span> writer:
            data.to_excel(writer, sheet_name=<span class="hljs-string">"Data"</span>, index=<span class="hljs-literal">False</span>)

        filename = <span class="hljs-string">f"analytics_data.xlsx"</span>
        res = HttpResponse(
            b.getvalue(),
            content_type=<span class="hljs-string">'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'</span>
        )
        res[<span class="hljs-string">'Content-Disposition'</span>] = <span class="hljs-string">f'attachment; filename=<span class="hljs-subst">{filename}</span>'</span>
        <span class="hljs-keyword">return</span> res
</code></pre>
<p>That is all, now you just have to create a Django URL for this function and you can download any file you want, just convert that file to a Byte string and use the correct Content-Type header.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding and Implementing UNet using Pytorch]]></title><description><![CDATA[From segmenting molecules on biomedical images to creating green screen videos to self-driving cars, UNet Architecture has a wide range of applications.
UNets are mainly used in segmentation, such as in Self Driving cars, the model takes the camera f...]]></description><link>https://tanseersaji.com/understanding-and-implementing-unet-using-pytorch</link><guid isPermaLink="true">https://tanseersaji.com/understanding-and-implementing-unet-using-pytorch</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Fri, 26 Feb 2021 20:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074674715/a41a7f57-6f6e-4817-a66e-10ee53fe5b1b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>From segmenting molecules on biomedical images to creating green screen videos to self-driving cars, UNet Architecture has a wide range of applications.</p>
<p>UNets are mainly used in segmentation, such as in Self Driving cars, the model takes the camera footage and segments them into classes like Road, Lane, Traffic lights, person, etc. In Cinematography, UNets can be used to create a mask around an object or a person that can then be edited to fine-tune. In the Biomedical industry, UNets can be trained to take in images from a microscope and segment different parts it sees. This could help scientists to uncover things that could not be seen with the naked eye. It can also be used in Satellite Imagery or in military drones. So, the possibilities are endless.</p>
<p>In this post, we will develop a model using UNet architecture to mask out the birds from a given image. First, let's talk about the dataset we will be using.</p>
<h2 id="heading-dataset">Dataset</h2>
<p>We will be using the Caltech-UCSD Birds-200-2011 dataset released by Caltech, it contains around 11,700 images of birds belonging to 200 species along with their masked images.</p>
<p>You can download the image dataset and the segmentations from this <a target="_blank" href="http://www.vision.caltech.edu/visipedia/CUB-200-2011.html">link</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074666151/21aa48c7-70b3-4c64-9206-2a9c264ee3b7.png" alt />
In the above screenshot, you can see the image of the bird and its mask pair.</p>
<p>Before starting building the model, let's implement the data pipeline from which we get appropriate input for our model.</p>
<h2 id="heading-building-data-pipeline">Building Data Pipeline</h2>
<p>We will be using Pytorch and Torchvision for the purposes of this blog.</p>
<p>Let's look at some metadata we got and deduced by looking at the downloaded dataset folders.</p>
<ol>
<li><p>The Bird images and their corresponding mask has the same name but the image is in jpg format and the mask is in png format.</p>
</li>
<li><p>Each species is separated into its respective folders, but Caltech researchers were kind enough to provide a text file that contains a list of paths to all the images.</p>
</li>
<li><p>There are other metadata such as bounding boxes and classes but we do not need those data to build this model.</p>
</li>
<li><p>The Bird images (1.1 GB) and their segmentations (37 MB) comes in two separate archive files, so I extracted them and place them in a single folder.</p>
</li>
</ol>
<p>This is how the final folder structure looks like.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074667758/6b765eff-e388-4892-b353-96b39ea4d8e3.png" alt />We only care about the <strong>images</strong> folder, <strong>segmentations</strong> folder and <strong>images.txt</strong> file.</p>
<p>First, let's create a file called dataset.py and import the necessary libraries.</p>
<pre><code class="lang-python">    <span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> Dataset
    <span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image
    <span class="hljs-keyword">import</span> os
</code></pre>
<p>Then create a class "BirdDataset" which extends the Pytorch's Dataset class.</p>
<p>In its init method, we will bring in <strong>image_paths</strong> which is the path to images.txt file that contains all the path to bird images, <strong>image_dir</strong> and <strong>segmentation_dir</strong> we need this because images.txt file does not have paths with root folders, so we need to join them accordingly.</p>
<p>Finally, we will need the image and mask transforms to apply the resize and normalise transformations.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BirdDataset</span>(<span class="hljs-params">Dataset</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span>(<span class="hljs-params">self, index</span>):</span>
        image_name = <span class="hljs-string">"."</span>.join(self.images_paths[index].split(<span class="hljs-string">'.'</span>)[:<span class="hljs-number">-1</span>])

        image = Image.open(os.path.join(self.image_dir, <span class="hljs-string">f"<span class="hljs-subst">{image_name}</span>.jpg"</span>)).convert(<span class="hljs-string">"RGB"</span>)
        seg = Image.open(os.path.join(self.segmentation_dir, <span class="hljs-string">f"<span class="hljs-subst">{image_name}</span>.png"</span>)).convert(<span class="hljs-string">"L"</span>)

        image = self.transform_image(image)
        seg = self.transform_mask(seg)

        <span class="hljs-keyword">return</span> image, seg

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, image_paths, image_dir, segmentation_dir, transform_image, transform_mask</span>):</span>
        super(BirdDataset, self).__init__()
        self.image_dir = image_dir
        self.segmentation_dir = segmentation_dir
        self.transform_image = transform_image
        self.transform_mask = transform_mask
        <span class="hljs-keyword">with</span> open(image_paths, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
            self.images_paths = [line.split(<span class="hljs-string">" "</span>)[<span class="hljs-number">-1</span>] <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f.readlines()]

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> len(self.images_paths)
</code></pre>
<p>As you can see in the init method, we are reading the paths, line by line and create a list out of them. For the len method, we simply return the length of image paths and in the get item method, we first extracted the name of the file so that we can append the extension as needed (jpg for images and png for masks) then opened them using PIL, applied transformations and return those as a tuple.</p>
<p>Next, we need to create a function that will take this dataset and split them into training and validation set and supply them in batches.</p>
<pre><code class="lang-python"><span class="hljs-comment"># utils.py file</span>

<span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> DataLoader
<span class="hljs-keyword">from</span> dataset <span class="hljs-keyword">import</span> BirdDataset
<span class="hljs-keyword">import</span> torch


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_data_set</span>(<span class="hljs-params">image_paths, image_dir, segmentation_dir, transforms, batch_size=<span class="hljs-number">8</span>, shuffle=True</span>):</span>
    dataset = BirdDataset(image_paths,
                          image_dir,
                          segmentation_dir,
                          transform_image=transforms[<span class="hljs-number">0</span>],
                          transform_mask=transforms[<span class="hljs-number">1</span>])

    train_dataset, val_dataset = torch.utils.data.random_split(dataset, [<span class="hljs-number">11772</span>, <span class="hljs-number">16</span>])

    <span class="hljs-keyword">return</span> DataLoader(
        train_dataset,
        batch_size=batch_size,
        shuffle=shuffle
    ), DataLoader(
            val_dataset,
            batch_size=batch_size,
            shuffle=shuffle
        )
</code></pre>
<p>Pytorch's DataLoader class helps us to create batches and randomly shuffle the data.</p>
<h2 id="heading-building-unet-architecture">Building UNet Architecture</h2>
<blockquote>
<p>TL;DR Scroll down to the section that says "Complete Code" to copy the entire model architecture.</p>
</blockquote>
<p>Finally, we can proceed to build the UNet architecture but before that, let's write a quick test that will ensure our future model returns the output with expected dimensions.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test</span>():</span>
    image = torch.randn((<span class="hljs-number">32</span>, <span class="hljs-number">3</span>, <span class="hljs-number">161</span>, <span class="hljs-number">161</span>))
    model = UNet(in_channels=<span class="hljs-number">3</span>)
    out = model(image)
    print(image.shape, out.shape)
    <span class="hljs-keyword">assert</span> out.shape == (<span class="hljs-number">32</span>, <span class="hljs-number">1</span>, <span class="hljs-number">161</span>, <span class="hljs-number">161</span>)
</code></pre>
<p>We will be building a model that takes an RGB image and returns a Black and White mask image of the same height and width, exactly like it is in the dataset.</p>
<p>We will follow this digram of UNet architecture.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074669056/cd65d2f5-710c-4711-b56c-7c6b22a175d5.png" alt /> You can see why this network got this name, it is kind of shaped like the letter "U".</p>
<p>If you look closely, this network can be split in 3 parts, Down layes (Blue), Up Layers (Red) and a Bottleneck (Green). <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074670353/1dcc9fd0-9198-4cc3-abd1-ca9082227b4e.jpeg" alt /></p>
<p>We will deal with them one by one, but before that, you can notice that each layer has one thing in common, there is an input layer that is followed by two same convolution layers, which means that the convolution does not change the height and width of the image only the number of channel is changed. So, we will implement that double convolution module.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DoubleConv</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, in_channels, out_channels, kernal_size, strides, padding</span>):</span>
        super(DoubleConv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernal_size, strides, padding, bias=<span class="hljs-literal">False</span>),
            nn.BatchNorm2d(num_features=out_channels),
            nn.ReLU(inplace=<span class="hljs-literal">True</span>),
            nn.Conv2d(out_channels, out_channels, kernal_size, strides, padding),
            nn.BatchNorm2d(num_features=out_channels),
            nn.ReLU(inplace=<span class="hljs-literal">True</span>)
        )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">forward</span>(<span class="hljs-params">self, x</span>):</span>
        <span class="hljs-keyword">return</span> self.conv(x)
</code></pre>
<p>This module is built in a general pattern so that I can copy this module while building some other architecture. As you can see, we have a normal Convolution layer with bias disabled because different from the original paper we will be adding a BatchNorm layer so this will cancel out the bias anyway.</p>
<p>After that, we added the second conv layer with ReLU activation and batchnorm.</p>
<p>Next, we create the class UNet that will contain our crazy-looking Network. in the init method we take in the in_channels which will be 3 in our case. And then we need the number of segmentation (which is 1) and a list of features in each layer of ups and downs.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UNet</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, in_channels, num_segmentations=<span class="hljs-number">1</span>, features=[<span class="hljs-number">64</span>, <span class="hljs-number">128</span>, <span class="hljs-number">256</span>, <span class="hljs-number">512</span>]</span>):</span>
        super(UNet, self).__init__()
</code></pre>
<p>Next, we declare the module list that will hold the down layers and up layers, ModuleList can be indexed like a regular Python list, but modules it contains are properly registered and will be visible by all Module methods. (Source: https://pytorch.org/docs/stable/generated/torch.nn.ModuleList.html)</p>
<pre><code class="lang-python">self.ups = nn.ModuleList()
self.downs = nn.ModuleList()
</code></pre>
<p>Let's also define other layers, bottleneck, max pool and output layer before we start populating the ups and downs list.</p>
<pre><code class="lang-python">self.bottleneck = DoubleConv(
  in_channels=features[<span class="hljs-number">-1</span>],
  out_channels=features[<span class="hljs-number">-1</span>]*<span class="hljs-number">2</span>,
  kernal_size=<span class="hljs-number">3</span>,
  strides=<span class="hljs-number">1</span>,
  padding=<span class="hljs-number">1</span>
)
self.output = nn.Conv2d(
  in_channels=features[<span class="hljs-number">0</span>],
  out_channels=num_segmentations,
  kernel_size=<span class="hljs-number">1</span>
)
self.pool = nn.MaxPool2d(kernel_size=<span class="hljs-number">2</span>, stride=<span class="hljs-number">2</span>)
</code></pre>
<p>By looking at the diagram, we can deduce a general pattern that we can implement in a loop.</p>
<p>For the downward layers, you can just loop through the features and append our DoubleConv module because the first layer will come from the input image or from the previous max pool layer.</p>
<pre><code class="lang-python">in_channels_iter = in_channels
<span class="hljs-keyword">for</span> feature <span class="hljs-keyword">in</span> features:
    self.downs.append(DoubleConv(
            in_channels=in_channels_iter,
            out_channels=feature,
            kernal_size=<span class="hljs-number">3</span>,
            strides=<span class="hljs-number">1</span>,
            padding=<span class="hljs-number">1</span>
        ))
    in_channels_iter = feature
</code></pre>
<p>As for the up layers, we will be using a Transpose Convolution layer to upsample the tensors and after that, we will add the DoubleConv layer. But in this case, we have to loop through the feature in reverse order.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> feature <span class="hljs-keyword">in</span> reversed(features):
    up = nn.Sequential(
        nn.ConvTranspose2d(
            in_channels=feature*<span class="hljs-number">2</span>,
            out_channels=feature,
            kernel_size=<span class="hljs-number">2</span>,
            stride=<span class="hljs-number">2</span>,
            padding=<span class="hljs-number">0</span>
        ),
        DoubleConv(
            in_channels=feature*<span class="hljs-number">2</span>,
            out_channels=feature,
            kernal_size=<span class="hljs-number">3</span>,
            padding=<span class="hljs-number">1</span>,
            strides=<span class="hljs-number">1</span>
        )
    )

    self.ups.append(up)
</code></pre>
<p>Notice that if you run this sequential layer it will not run and raises an error that input_channels does not match the expected input_channels. This is because we need to do an intermediate step in the forward method which is represented by those grey arrows in the diagram.</p>
<p>Now let's write the forward method.</p>
<p>First, we send the image down the UNet through Downward layers and we saved the output of DoubleConv before applying the max pool.</p>
<pre><code class="lang-python">skip_connections = []
<span class="hljs-keyword">for</span> down <span class="hljs-keyword">in</span> self.downs:
    x = down(x)
    skip_connections.append(x)
    x = self.pool(x)
</code></pre>
<p>After that, we send in the tensor through the bottleneck layer and prepare the skip_connections to be concatenated with the up layers by reversing it.</p>
<pre><code class="lang-python">x = self.bottleneck(x)
skip_connections = skip_connections[::<span class="hljs-number">-1</span>]
</code></pre>
<p>As discussed earlier, we need to do some additional operations to the output of ConvTranspose before we passed it through the DoubleConv layers.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(self.ups)):
    x = self.ups[i][<span class="hljs-number">0</span>](x) <span class="hljs-comment"># Pass through ConvTranspose first</span>

    skip_connection = skip_connections[i]

    <span class="hljs-comment"># If the height and width of output tensor and skip connection</span>
    <span class="hljs-comment"># is not same then resize the tensor</span>
    <span class="hljs-keyword">if</span> x.shape != skip_connection.shape:
                <span class="hljs-comment"># TF =&gt; import torchvision.transforms.functional as TF</span>
        x = TF.resize(x, size=skip_connection.shape[<span class="hljs-number">2</span>:])

    <span class="hljs-comment"># Concat the output tensor with skip connection</span>
    concat_x = torch.cat((skip_connection, x), dim=<span class="hljs-number">1</span>)

    <span class="hljs-comment"># Pass the concatinated tensor through DoubleCOnv</span>
    x = self.ups[i][<span class="hljs-number">1</span>](concat_x)
</code></pre>
<p>Then why we used the Sequential layer, we could have just appended them separately. Yes, we could, the reason I did it that way because I didn't want to deal with skipping every other layer in the for a loop. I think this is much cleaner.</p>
<p>And finally, we just pass it through the output layer.</p>
<pre><code class="lang-python"><span class="hljs-keyword">return</span> self.output(x)
</code></pre>
<h3 id="heading-complete-code-unet-architecture">Complete Code (UNet Architecture)</h3>
<pre><code class="lang-python"><span class="hljs-comment"># unet.py file</span>

<span class="hljs-keyword">from</span> torch <span class="hljs-keyword">import</span> nn
<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> torchvision.transforms.functional <span class="hljs-keyword">as</span> TF


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DoubleConv</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, in_channels, out_channels, kernal_size, strides, padding</span>):</span>
        super(DoubleConv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernal_size, strides, padding, bias=<span class="hljs-literal">False</span>),
            nn.BatchNorm2d(num_features=out_channels),
            nn.ReLU(inplace=<span class="hljs-literal">True</span>),
            nn.Conv2d(out_channels, out_channels, kernal_size, strides, padding, bias=<span class="hljs-literal">False</span>),
            nn.BatchNorm2d(num_features=out_channels),
            nn.ReLU(inplace=<span class="hljs-literal">True</span>)
        )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">forward</span>(<span class="hljs-params">self, x</span>):</span>
        <span class="hljs-keyword">return</span> self.conv(x)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UNet</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, in_channels, num_segmentations=<span class="hljs-number">1</span>, features=[<span class="hljs-number">64</span>, <span class="hljs-number">128</span>, <span class="hljs-number">256</span>, <span class="hljs-number">512</span>]</span>):</span>
        super(UNet, self).__init__()
        self.ups = nn.ModuleList()
        self.downs = nn.ModuleList()
        self.bottleneck = DoubleConv(
            in_channels=features[<span class="hljs-number">-1</span>],
            out_channels=features[<span class="hljs-number">-1</span>]*<span class="hljs-number">2</span>,
            kernal_size=<span class="hljs-number">3</span>,
            strides=<span class="hljs-number">1</span>,
            padding=<span class="hljs-number">1</span>
        )
        self.output = nn.Conv2d(
            in_channels=features[<span class="hljs-number">0</span>],
            out_channels=num_segmentations,
            kernel_size=<span class="hljs-number">1</span>
        )
        self.pool = nn.MaxPool2d(kernel_size=<span class="hljs-number">2</span>, stride=<span class="hljs-number">2</span>)

        in_channels_iter = in_channels
        <span class="hljs-keyword">for</span> feature <span class="hljs-keyword">in</span> features:
            self.downs.append(DoubleConv(
                    in_channels=in_channels_iter,
                    out_channels=feature,
                    kernal_size=<span class="hljs-number">3</span>,
                    strides=<span class="hljs-number">1</span>,
                    padding=<span class="hljs-number">1</span>
                ))
            in_channels_iter = feature

        <span class="hljs-keyword">for</span> feature <span class="hljs-keyword">in</span> reversed(features):
            up = nn.Sequential(
                nn.ConvTranspose2d(
                    in_channels=feature*<span class="hljs-number">2</span>,
                    out_channels=feature,
                    kernel_size=<span class="hljs-number">2</span>,
                    stride=<span class="hljs-number">2</span>,
                    padding=<span class="hljs-number">0</span>
                ),
                DoubleConv(
                    in_channels=feature*<span class="hljs-number">2</span>,
                    out_channels=feature,
                    kernal_size=<span class="hljs-number">3</span>,
                    padding=<span class="hljs-number">1</span>,
                    strides=<span class="hljs-number">1</span>
                )
            )

            self.ups.append(up)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">forward</span>(<span class="hljs-params">self, x</span>):</span>
        skip_connections = []
        <span class="hljs-keyword">for</span> down <span class="hljs-keyword">in</span> self.downs:
            x = down(x)
            skip_connections.append(x)
            x = self.pool(x)

        x = self.bottleneck(x)
        skip_connections = skip_connections[::<span class="hljs-number">-1</span>]

        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(self.ups)):
            x = self.ups[i][<span class="hljs-number">0</span>](x) <span class="hljs-comment"># Pass through ConvTranspose first</span>

            skip_connection = skip_connections[i]

            <span class="hljs-comment"># If the height and width of output tensor and skip connection</span>
            <span class="hljs-comment"># is not same then resize the tensor</span>
            <span class="hljs-keyword">if</span> x.shape != skip_connection.shape:
                x = TF.resize(x, size=skip_connection.shape[<span class="hljs-number">2</span>:])

            <span class="hljs-comment"># Concat the output tensor with skip connection</span>
            concat_x = torch.cat((skip_connection, x), dim=<span class="hljs-number">1</span>)

            <span class="hljs-comment"># Pass the concatinated tensor through DoubleCOnv</span>
            x = self.ups[i][<span class="hljs-number">1</span>](concat_x)

        <span class="hljs-keyword">return</span> self.output(x)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test</span>():</span>
    image = torch.randn((<span class="hljs-number">32</span>, <span class="hljs-number">3</span>, <span class="hljs-number">161</span>, <span class="hljs-number">161</span>))
    model = UNet(in_channels=<span class="hljs-number">3</span>)
    out = model(image)
    print(image.shape, out.shape)
    <span class="hljs-keyword">assert</span> out.shape == (<span class="hljs-number">32</span>, <span class="hljs-number">1</span>, <span class="hljs-number">161</span>, <span class="hljs-number">161</span>)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    test()
</code></pre>
<h2 id="heading-training-step">Training Step</h2>
<p>Create a file called train.py and import the necessary libraries.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">from</span> unet <span class="hljs-keyword">import</span> UNet
<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> load_data_set
<span class="hljs-keyword">from</span> torchvision.transforms <span class="hljs-keyword">import</span> transforms
<span class="hljs-keyword">from</span> tqdm <span class="hljs-keyword">import</span> tqdm
<span class="hljs-keyword">import</span> torchvision
</code></pre>
<p>Next, we'll define the Hyperparameters and configs</p>
<pre><code class="lang-python">config = {
    <span class="hljs-string">"lr"</span>: <span class="hljs-number">1e-3</span>,
    <span class="hljs-string">"batch_size"</span>: <span class="hljs-number">16</span>,
    <span class="hljs-string">"image_dir"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/images"</span>,
    <span class="hljs-string">"segmentation_dir"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/segmentations"</span>,
    <span class="hljs-string">"image_paths"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/images.txt"</span>,
    <span class="hljs-string">"epochs"</span>: <span class="hljs-number">10</span>,
    <span class="hljs-string">"checkpoint"</span>: <span class="hljs-string">"checkpoint/bird_segmentation_v1.pth"</span>,
    <span class="hljs-string">"optimiser"</span>: <span class="hljs-string">"checkpoint/bird_segmentation_v1_optim.pth"</span>,
    <span class="hljs-string">"continue_train"</span>: <span class="hljs-literal">False</span>,
    <span class="hljs-string">"device"</span>: <span class="hljs-string">"cuda"</span> <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">"cpu"</span>
}
</code></pre>
<p>I'm going with a learning rate of 0.001 and 10 epochs, trained on an RTX 2080 Super 8GB VRAM.</p>
<pre><code class="lang-python">transforms_image = transforms.Compose([
    transforms.Resize((<span class="hljs-number">256</span>, <span class="hljs-number">256</span>)),
    transforms.ToTensor(),
    transforms.Normalize((<span class="hljs-number">0.</span>, <span class="hljs-number">0.</span>, <span class="hljs-number">0.</span>), (<span class="hljs-number">1.</span>, <span class="hljs-number">1.</span>, <span class="hljs-number">1.</span>))
])

transforms_mask = transforms.Compose([
    transforms.Resize((<span class="hljs-number">256</span>, <span class="hljs-number">256</span>)),
    transforms.ToTensor(),
    transforms.Normalize((<span class="hljs-number">0.</span>,), (<span class="hljs-number">1.</span>,))
])
</code></pre>
<p>I am also resizing all images to 256px by 256px and training with a batch size of 16.</p>
<p>Next, we will load the data using a helper function I wrote earlier called load_data_set.</p>
<pre><code class="lang-python">train_dataset, val_dataset = load_data_set(
    config[<span class="hljs-string">'image_paths'</span>],
    config[<span class="hljs-string">'image_dir'</span>],
    config[<span class="hljs-string">'segmentation_dir'</span>],
    transforms=[transforms_image, transforms_mask],
    batch_size=config[<span class="hljs-string">'batch_size'</span>]
)

print(<span class="hljs-string">"loaded"</span>, len(train_dataset), <span class="hljs-string">"batches"</span>)
</code></pre>
<p>Now, let's define the model object and Adam optimiser.</p>
<pre><code class="lang-python">model = UNet(<span class="hljs-number">3</span>).to(config[<span class="hljs-string">'device'</span>])
optimiser = torch.optim.Adam(params=model.parameters(), lr=config[<span class="hljs-string">'lr'</span>])
</code></pre>
<p>If you want to import a pre-trained model then for that the below snippet of code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> config[<span class="hljs-string">'continue_train'</span>]:
    state_dict = torch.load(config[<span class="hljs-string">'checkpoint'</span>])
    optimiser_state = torch.load(config[<span class="hljs-string">'optimiser'</span>])
    model.load_state_dict(state_dict)
    optimiser.load_state_dict(optimiser_state)
</code></pre>
<p>We will be using the Binary Crossentropy loss because we are dealing with binary segmentation here. And also, we will be using Pytorch's Automated Mixed Precision library to automatically set the precision of the gradients. This will reduce the VRAM consumed and also sped up the learning process.</p>
<p>We need to use BCE with Logits instead of normal BCE error because we are not using a sigmoid in the model architecture. BCE with Logits will pass the tensor through a sigmoid function before calculating the loss.</p>
<p>In case you want to segment more than one items like in a photo you want to segment people, cars, trees, sky, etc. then you can simply change the num_segmentations parameter in the UNet class and change the loss function to Cross-Entropy Loss <strong>torch.nn.CrossEntropyLoss.</strong></p>
<pre><code class="lang-python">loss_fn = torch.nn.BCEWithLogitsLoss()
scaler = torch.cuda.amp.GradScaler()

model.train()
</code></pre>
<p>The train function is pretty straight forward, we create two loops on for epochs and the other for the batches. We use the autocast wrapper to automatically cast the gradients to float16 or float32 as required and we just update the weights using Pytorch abstraction.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">train</span>():</span>
    <span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> range(config[<span class="hljs-string">'epochs'</span>]):
        loop = tqdm(train_dataset)
        <span class="hljs-keyword">for</span> image, seg <span class="hljs-keyword">in</span> loop:
            image = image.to(config[<span class="hljs-string">'device'</span>])
            seg = seg.float().to(config[<span class="hljs-string">'device'</span>])

            <span class="hljs-keyword">with</span> torch.cuda.amp.autocast():
                pred = model(image)
                loss = loss_fn(pred, seg)

            optimiser.zero_grad()
            scaler.scale(loss).backward()
            scaler.step(optimiser)
            scaler.update()

            loop.set_postfix(loss=loss.item())
        check_accuracy_and_save(model, optimiser, epoch)
</code></pre>
<p>check_accuracy_and_save is a helper function that will check the accuracy of the model against the validation set after every epoch and saves the states of the model and optimiser.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_accuracy_and_save</span>(<span class="hljs-params">model, optimiser, epoch</span>):</span>
    torch.save(model.state_dict(), config[<span class="hljs-string">'checkpoint'</span>])
    torch.save(optimiser.state_dict(), config[<span class="hljs-string">'optimiser'</span>])

    dice_score = <span class="hljs-number">0</span>

    model.eval()
    <span class="hljs-keyword">with</span> torch.no_grad():
        <span class="hljs-keyword">for</span> x, y <span class="hljs-keyword">in</span> val_dataset:
            x = x.to(config[<span class="hljs-string">'device'</span>])
            y = y.to(config[<span class="hljs-string">'device'</span>])

            preds = torch.sigmoid(model(x))
            preds = (preds &gt; <span class="hljs-number">0.5</span>).float()
            dice_score += (<span class="hljs-number">2</span> * (preds * y).sum()) / (
                (preds + y).sum() + <span class="hljs-number">1e-8</span>
            )

            torchvision.utils.save_image(preds, <span class="hljs-string">f"test/pred/<span class="hljs-subst">{epoch}</span>.png"</span>)
            torchvision.utils.save_image(y, <span class="hljs-string">f"test/true/<span class="hljs-subst">{epoch}</span>.png"</span>)

    print(
        <span class="hljs-string">f"Dice Score = <span class="hljs-subst">{dice_score/len(val_dataset)}</span>"</span>
    )
    model.train()
</code></pre>
<p>For a measure of accuracy we will be using Dice Score also know as F1 Score because if we use normal pixel accuracy since 80% of the mask image is black, the model can get an accuracy of 80% just by generating a black screen every time.</p>
<blockquote>
<p>The Dice score is not only a measure of how many positives you find, but it also penalizes for the false positives that the method finds, similar to precision. so it is more similar to precision than accuracy. The only difference is the denominator, where you have the total number of positives instead of only the positives that the method finds. So the Dice score is also penalizing for the positives that your algorithm/method could not find.</p>
</blockquote>
<p>Source: <a target="_blank" href="https://stats.stackexchange.com/a/195037">https://stats.stackexchange.com/a/195037</a></p>
<h3 id="heading-complete-code-training-step">Complete Code (Training Step)</h3>
<pre><code class="lang-python"><span class="hljs-comment"># train.py file</span>

<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">from</span> unet <span class="hljs-keyword">import</span> UNet
<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> load_data_set
<span class="hljs-keyword">from</span> torchvision.transforms <span class="hljs-keyword">import</span> transforms
<span class="hljs-keyword">from</span> tqdm <span class="hljs-keyword">import</span> tqdm
<span class="hljs-keyword">import</span> torchvision

config = {
    <span class="hljs-string">"lr"</span>: <span class="hljs-number">1e-3</span>,
    <span class="hljs-string">"batch_size"</span>: <span class="hljs-number">16</span>,
    <span class="hljs-string">"image_dir"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/images"</span>,
    <span class="hljs-string">"segmentation_dir"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/segmentations"</span>,
    <span class="hljs-string">"image_paths"</span>: <span class="hljs-string">"CUB_200_2011/CUB_200_2011/images.txt"</span>,
    <span class="hljs-string">"epochs"</span>: <span class="hljs-number">10</span>,
    <span class="hljs-string">"checkpoint"</span>: <span class="hljs-string">"checkpoint/bird_segmentation_v1.pth"</span>,
    <span class="hljs-string">"optimiser"</span>: <span class="hljs-string">"checkpoint/bird_segmentation_v1_optim.pth"</span>,
    <span class="hljs-string">"continue_train"</span>: <span class="hljs-literal">False</span>,
    <span class="hljs-string">"device"</span>: <span class="hljs-string">"cuda"</span> <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">"cpu"</span>
}

print(<span class="hljs-string">f"Training using <span class="hljs-subst">{config[<span class="hljs-string">'device'</span>]}</span>"</span>)

transforms_image = transforms.Compose([
    transforms.Resize((<span class="hljs-number">256</span>, <span class="hljs-number">256</span>)),
    transforms.ToTensor(),
    transforms.Normalize((<span class="hljs-number">0.</span>, <span class="hljs-number">0.</span>, <span class="hljs-number">0.</span>), (<span class="hljs-number">1.</span>, <span class="hljs-number">1.</span>, <span class="hljs-number">1.</span>))
])

transforms_mask = transforms.Compose([
    transforms.Resize((<span class="hljs-number">256</span>, <span class="hljs-number">256</span>)),
    transforms.ToTensor(),
    transforms.Normalize((<span class="hljs-number">0.</span>,), (<span class="hljs-number">1.</span>,))
])

train_dataset, val_dataset = load_data_set(
    config[<span class="hljs-string">'image_paths'</span>],
    config[<span class="hljs-string">'image_dir'</span>],
    config[<span class="hljs-string">'segmentation_dir'</span>],
    transforms=[transforms_image, transforms_mask],
    batch_size=config[<span class="hljs-string">'batch_size'</span>]
)

print(<span class="hljs-string">"loaded"</span>, len(train_dataset), <span class="hljs-string">"batches"</span>)

model = UNet(<span class="hljs-number">3</span>).to(config[<span class="hljs-string">'device'</span>])
optimiser = torch.optim.Adam(params=model.parameters(), lr=config[<span class="hljs-string">'lr'</span>])

<span class="hljs-keyword">if</span> config[<span class="hljs-string">'continue_train'</span>]:
    state_dict = torch.load(config[<span class="hljs-string">'checkpoint'</span>])
    optimiser_state = torch.load(config[<span class="hljs-string">'optimiser'</span>])
    model.load_state_dict(state_dict)
    optimiser.load_state_dict(optimiser_state)

loss_fn = torch.nn.BCEWithLogitsLoss()
scaler = torch.cuda.amp.GradScaler()

model.train()


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_accuracy_and_save</span>(<span class="hljs-params">model, optimiser, epoch</span>):</span>
    torch.save(model.state_dict(), config[<span class="hljs-string">'checkpoint'</span>])
    torch.save(optimiser.state_dict(), config[<span class="hljs-string">'optimiser'</span>])

    num_correct = <span class="hljs-number">0</span>
    num_pixel = <span class="hljs-number">0</span>
    dice_score = <span class="hljs-number">0</span>

    model.eval()
    <span class="hljs-keyword">with</span> torch.no_grad():
        <span class="hljs-keyword">for</span> x, y <span class="hljs-keyword">in</span> val_dataset:
            x = x.to(config[<span class="hljs-string">'device'</span>])
            y = y.to(config[<span class="hljs-string">'device'</span>])

            preds = torch.sigmoid(model(x))
            preds = (preds &gt; <span class="hljs-number">0.5</span>).float()
            num_correct += (preds == y).sum()
            num_pixel += torch.numel(preds)
            dice_score += (<span class="hljs-number">2</span> * (preds * y).sum()) / (
                (preds + y).sum() + <span class="hljs-number">1e-8</span>
            )

            torchvision.utils.save_image(preds, <span class="hljs-string">f"test/pred/<span class="hljs-subst">{epoch}</span>.png"</span>)
            torchvision.utils.save_image(y, <span class="hljs-string">f"test/true/<span class="hljs-subst">{epoch}</span>.png"</span>)

    print(
        <span class="hljs-string">f"Dice Score = <span class="hljs-subst">{dice_score/len(val_dataset)}</span>"</span>
    )
    model.train()


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">train</span>():</span>
    step = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> range(config[<span class="hljs-string">'epochs'</span>]):
        loop = tqdm(train_dataset)
        <span class="hljs-keyword">for</span> image, seg <span class="hljs-keyword">in</span> loop:
            image = image.to(config[<span class="hljs-string">'device'</span>])
            seg = seg.float().to(config[<span class="hljs-string">'device'</span>])

            <span class="hljs-keyword">with</span> torch.cuda.amp.autocast():
                pred = model(image)
                loss = loss_fn(pred, seg)

            optimiser.zero_grad()
            scaler.scale(loss).backward()
            scaler.step(optimiser)
            scaler.update()

            loop.set_postfix(loss=loss.item())
            step += <span class="hljs-number">1</span>
        check_accuracy_and_save(model, optimiser, epoch)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    train()
</code></pre>
<p>After training for just two epoch the model was able to produce pretty promising results. <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074671607/e9674405-dcf3-44c0-9794-8776633e542f.png" alt="Predicted Masks" /> <strong>Predicted Masks</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074672952/5df7da38-95c2-43d5-9332-e34869b37d8c.png" alt="Ground Truth" /> <strong>Ground Truth</strong></p>
<p>This post is inspired by this video.</p>


<p>With this, we have implemented the UNet architecture to generate masks for bird images. You can find the complete code in this <a target="_blank" href="https://github.com/Idiomatic-Programmers/UNet">Github repo</a>.</p>
<p>Leave a comment if you have any concerns or query, I will get back to you as soon as possible.</p>
]]></content:encoded></item><item><title><![CDATA[Generative Adversarial Networks]]></title><description><![CDATA[In 2014, Ian Goodfellow, who is currently working as Director of Machine Learning for Apple, published a paper called "Generative Adversarial Networks" or GAN for short. Which basically talked about a system of two neural networks, Generator and Disc...]]></description><link>https://tanseersaji.com/generative-adversarial-networks</link><guid isPermaLink="true">https://tanseersaji.com/generative-adversarial-networks</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Thu, 11 Feb 2021 08:56:15 GMT</pubDate><content:encoded><![CDATA[<p>In 2014, Ian Goodfellow, who is currently working as Director of Machine Learning for Apple, published a paper called "Generative Adversarial Networks" or GAN for short. Which basically talked about a system of two neural networks, Generator and Discriminator, that can generate images or any data that is similar to provided datasets from essentially random noise.</p>
<p>The diagram below shows the basic architecture of a GAN.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1613042386/gan_diagram_jhuerz.svg" alt="https://res.cloudinary.com/idiomprog/image/upload/v1613042386/gan_diagram_jhuerz.svg" /></p>
<p>Source: <a target="_blank" href="https://developers.google.com/">https://developers.google.com/</a></p>
<p>Generative Network takes some random noise and outputs some random noise. This output noise is passed to a discriminator along with the real image or data as a ground truth based on that both Discriminator and Generator is trained.</p>
<p>As you can see, the concept of GAN is very simple. When I started learning about GANs I thought I can easily implement one of those. But boy I was wrong. In reality training a GAN is extremely hard both Generator and Discriminator must be trained side by side if one overpowers the other it won't work, we will talk about all the problems you might face while training a GAN. But now let's look at a simple GAN in Pytorch. We will be using the MNIST Dataset[^1] for this post.</p>
<h2 id="heading-understanding-the-dataset">Understanding the Dataset</h2>
<p>The MNIST dataset is a huge database of handwritten numbers from 0 to 9 used for Optical Character Recognition or reading numbers from an image.</p>
<p>This dataset consists of 28x28 images of handwritten numbers where each pixel contains either a zero or a one.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1613042427/687474703a2f2f692e7974696d672e636f6d2f76692f3051493378675875422d512f687164656661756c742e6a7067_rx3nur.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074622456/e673f9a5-41c7-447d-84af-d804406084ca.jpeg" /></p>
<p>The computer vision extension of PyTorch, Torchvision, provides this dataset which we can download using the following code snippet.</p>
<pre><code class="lang-python">mnist = datasets.MNIST(root=<span class="hljs-string">'datasets'</span>, train=<span class="hljs-literal">True</span>, transform=transformations, download=<span class="hljs-literal">True</span>)
</code></pre>
<p>But before we can run this code, we need to import some libraries.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> torchvision.datasets <span class="hljs-keyword">as</span> datasets
<span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> DataLoader
<span class="hljs-keyword">import</span> torchvision.transforms <span class="hljs-keyword">as</span> transforms
</code></pre>
<p>You can install the torchvision library using this pip command.</p>
<pre><code class="lang-bash">pip install torchvision
</code></pre>
<p>The <strong>DataLoader</strong> class is used to load the data to memory in batches, this prevents your system from running out of memory while training.</p>
<p><strong>Transforms</strong> class is used to make random augmentations to the image such as random rotation, resize, crop, etc. but for now we will only normalise the images to range from -1 to 1.</p>
<p>The entire function that you can copy paste is this.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_dataset</span>():</span>
    transformations = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((<span class="hljs-number">0.5</span>, ), (<span class="hljs-number">0.5</span>, ))
    ])
    mnist = datasets.MNIST(root=<span class="hljs-string">'datasets'</span>, train=<span class="hljs-literal">True</span>, transform=transformations, download=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> DataLoader(mnist, batch_size=<span class="hljs-number">32</span>, shuffle=<span class="hljs-literal">True</span>)
</code></pre>
<h2 id="heading-implementing-the-generator">Implementing the Generator</h2>
<p>In this section, we will implement a generator network which will take a random noise vector of size 100 and convert it into a vector of size 784 which we will then convert to 28x28</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Generator</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        super().__init__()
        self.gen = nn.Sequential(
            nn.Linear(<span class="hljs-number">100</span>, <span class="hljs-number">256</span>),
            nn.LeakyReLU(<span class="hljs-number">0.01</span>),
            nn.Linear(<span class="hljs-number">256</span>, <span class="hljs-number">784</span>),
            nn.Tanh(),  <span class="hljs-comment"># make outputs [-1, 1]</span>
        )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">forward</span>(<span class="hljs-params">self, x</span>):</span>
        <span class="hljs-keyword">return</span> self.gen(x)
</code></pre>
<p>We will be implementing the original GAN created by Ian Goodfellow in this paper [^2]</p>
<h2 id="heading-implemeting-the-discriminator">Implemeting the Discriminator</h2>
<p>Next, we will implement a discriminator that will take the vector of size 784 that may be generated or from a real image.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Discriminator</span>(<span class="hljs-params">nn.Module</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        super().__init__()
        self.disc = nn.Sequential(
            nn.Linear(<span class="hljs-number">784</span>, <span class="hljs-number">128</span>),
            nn.LeakyReLU(<span class="hljs-number">0.01</span>),
            nn.Linear(<span class="hljs-number">128</span>, <span class="hljs-number">1</span>),
            nn.Sigmoid(), <span class="hljs-comment"># make outputs [0, 1]</span>
        )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">forward</span>(<span class="hljs-params">self, x</span>):</span>
        <span class="hljs-keyword">return</span> self.disc(x)
</code></pre>
<h2 id="heading-hyperparameters">Hyperparameters</h2>
<p>As I mentioned earlier, GANs are extremely hard to train, one of the reasons is that a GAN is very sensitive to the initial values or hyperparameters. You have to follow the original papers to get the training right. Otherwise, you might have to spend many days optimizing the hyperparameters.</p>
<pre><code class="lang-python">config = {
    <span class="hljs-string">'device'</span>: <span class="hljs-string">"cuda"</span> <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> <span class="hljs-string">"cpu"</span>,
    <span class="hljs-string">'lr'</span>: <span class="hljs-number">3e-4</span>,
    <span class="hljs-string">'epochs'</span>: <span class="hljs-number">50</span>,
        <span class="hljs-string">'batch_size'</span>: <span class="hljs-number">32</span>
}
</code></pre>
<p>In our case, we will be using the same parameters as it was said in the paper, that is, a learning rate of 0.0003 and 50 epochs.</p>
<p><strong>What is a learning rate?</strong></p>
<p>Simple answer, it's the rate at which a machine learning model learns. Smaller the number, the slower it learns and higher the number the faster it learns. For more info, check out our post about <a target="_blank" href="/post/perceptrons/#perceptron-algorithm">Perceptrons</a>.</p>
<h2 id="heading-training-time">Training Time</h2>
<p>Finally, it's time to actually generate some handwritten numbers, that is, train our GAN. First let's create the objects for Generator, Discriminator, and their optimizers, we will be using the Adam optimizers.</p>
<p><strong>ADAM</strong> or <strong>ADA</strong>ptive <strong>M</strong>oment optimiser is an algorithm[^3] used to update the weights such that the overall error goes down.</p>
<pre><code class="lang-python">disc = Discriminator().to(config[<span class="hljs-string">'device'</span>])
gen = Generator().to(config[<span class="hljs-string">'device'</span>])

optimiser_g = optim.Adam(params=gen.parameters(), lr=config[<span class="hljs-string">'lr'</span>])
optimiser_d = optim.Adam(params=disc.parameters(), lr=config[<span class="hljs-string">'lr'</span>])
</code></pre>
<p>We also need to define a loss function before we train, we will be using the Binary Cross Entropy loss[^4]  function to calculate the error of our model.</p>
<p><strong>Binary Cross Entropy (BCE) Loss</strong></p>
<p>This loss formula is used to calculate the distance between two probability distributions.</p>
<p>$BCE = ℓ(x,y)=L=(l_1​,…,l_N​), l_n​=−w_n​[y_n​⋅logx_n​+(1−y_n​)⋅log(1−x_n​)]$</p>
<pre><code class="lang-python">loss_fn = nn.BCELoss()
</code></pre>
<p>Now we will write our training step which is one cycle of generating and discriminating a handwritten number compare with an original number and update the models.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> range(config[<span class="hljs-string">'epoch'</span>]):
    <span class="hljs-keyword">for</span> batch_idx, (real, label) <span class="hljs-keyword">in</span> enumerate(train_data):

        noise = torch.randn(config[<span class="hljs-string">'batch_size'</span>], <span class="hljs-number">100</span>).to(config[<span class="hljs-string">'device'</span>]) <span class="hljs-comment"># Create a random probability distribution</span>
        fake = gen(noise) <span class="hljs-comment"># Generate a fake number</span>
        disc_real = disc(real).view(<span class="hljs-number">-1</span>) <span class="hljs-comment"># pass the real number through the discriminator</span>
        lossD_real = loss_fn(disc_real, torch.ones_like(disc_real)) <span class="hljs-comment"># calculate the loss for real image</span>
        disc_fake = disc(fake).view(<span class="hljs-number">-1</span>) <span class="hljs-comment"># pass the fake number through the discriminator</span>
        lossD_fake = loss_fn(disc_fake, torch.zeros_like(disc_fake)) <span class="hljs-comment"># calculate the loss for fake image</span>
        lossD = (lossD_real + lossD_fake) / <span class="hljs-number">2</span> <span class="hljs-comment"># calculate the average loss</span>

        <span class="hljs-comment"># update the weights for the discriminator</span>
        disc.zero_grad()
        lossD.backward(retain_graph=<span class="hljs-literal">True</span>)
        optimiser_d.step()

        output = disc(fake).view(<span class="hljs-number">-1</span>)
        lossG = loss_fn(output, torch.ones_like(output)) <span class="hljs-comment"># calculate the error between the fake image and the true image</span>

        <span class="hljs-comment"># update the weights for the generator</span>
        gen.zero_grad()
        lossG.backward()
        optimiser_g.step()
</code></pre>
<p>This code is heavily inspired by a youtube video by Aladdin Persson.</p>


<p>Find the complete code at our <a target="_blank" href="https://github.com/Idiomatic-Programmers/SimpleGAN">Github Repo</a></p>
<p>If you have any questions, feel free to comment below.</p>
<h4 id="heading-footnotes">Footnotes</h4>
<p>[^1]: <strong>MNIST Database</strong> - “THE MNIST DATABASE.” MNIST Handwritten Digit Database, Yann LeCun, Corinna Cortes and Chris Burges, <a target="_blank" href="http://yann.lecun.com/exdb/mnist/">yann.lecun.com/exdb/mnist/</a>.
[^2]: <strong>Paper by Ian Goodfellow</strong> - Goodfellow , Ian J., et al. “Generative Adversarial Networks.” <a target="_blank" href="http://arxiv.org/">ArXiv.org</a>, 10 June 2014, <a target="_blank" href="http://arxiv.org/abs/1406.2661v1">arxiv.org/abs/1406.2661v1</a>.
[^3]: <strong>Adam: A Method for Stochastic Optimization</strong> - Kingma, Diederik P., and Jimmy Ba. “Adam: A Method for Stochastic Optimization.” <a target="_blank" href="http://arxiv.org/">ArXiv.org</a>, 30 Jan. 2017, <a target="_blank" href="http://arxiv.org/abs/1412.6980">arxiv.org/abs/1412.6980</a>.
[^4]: <strong>Binary Cross-Entropy Loss</strong> - Understanding Categorical Cross-Entropy Loss, Binary Cross-Entropy Loss, Softmax Loss, Logistic Loss, Focal Loss and All Those Confusing Names, <a target="_blank" href="http://gombru.github.io/2018/05/23/cross_entropy_loss/">gombru.github.io/2018/05/23/cross_entropy_loss/</a></p>
]]></content:encoded></item><item><title><![CDATA[How ISP blocks (throttles) VPN?]]></title><description><![CDATA[Today I wanna talk about something, without the invention of which you wouldn't be reading this article, yes I'm talking about the internet, the thing that we have started taking for granted now, and it's time we start paying attention to it, because...]]></description><link>https://tanseersaji.com/how-isp-blocks-throttles-vpn</link><guid isPermaLink="true">https://tanseersaji.com/how-isp-blocks-throttles-vpn</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Mon, 30 Nov 2020 17:24:30 GMT</pubDate><content:encoded><![CDATA[<p>Today I wanna talk about something, without the invention of which you wouldn't be reading this article, yes I'm talking about the internet, the thing that we have started taking for granted now, and it's time we start paying attention to it, because soon, the way we use the internet is about to change. With the rapidly increasing number of internet users, Governments around the world are scrambling to gain more control over it and they are trying to regulate what you do over it. </p>
<p>Social Networking Websites are being asked to make their moderation policies more stringent and expressing your opinions freely on the internet without any repercussions will soon become next to impossible.  Even now, anyone can take down a post or video. Talking from a developer's perspective, you wouldn't ever think about an open source project being taken down, but we all saw recently that youtube-dl got taken down because of a DMCA notice.</p>
<p>We get our internet connection at the merci of our Government even though we as a consumer pay a premium to use this luxury that is now a necessity, the government has the ultimate power to block and ban anything from the internet at least in their country.</p>
<p>You all know that China heavily censors their internet to protect their communist beliefs and to shut anyone who criticises the president and the government. Ok but that's China.</p>
<p>It's not just China. India for example, the largest democracy in the world, banned more than 150 apps and websites including PubG, Alibaba and Ali Express just because they were created by Chinese companies. You might say, that's politics.</p>
<p>It's not just politics, a few years ago India banned all Adult content from the Internet just because some politician didn't like that. A massive corporate entity persuaded the government to ban two music videos just because they didn't like the criticism in the lyrics.</p>
<h2 id="heading-how-the-government-can-block-a-website-or-content">How the government can block a website or content?</h2>
<p>There are several ways a government entity can ban/block a website, app or any content on the internet.</p>
<ol>
<li><p><strong>Issuing a court order</strong> - The government can ask the judicial system to issue a court order to the company that owns the website or content and the company have to remove such content as long as they are operating in the country.</p>
</li>
<li><p><strong>DNS Lookup Blocks</strong> - I will deep dive into this topic later in the post, but in simple terms, the government can ask the DNS providers to not resolve requests for a set of domains if the request is coming from their country. This has loopholes like the DNS Provider can decline the request if the company that owns the DNS Servers does not belongs to the country. These types of blocks can be bypassed by using a custom DNS like 1.1.1.1</p>
</li>
<li><p><strong>ISP Blocks</strong> - The Internet Service Provider has the ability to not serve certain requests that are coming from or going to a banned IP address. I will talk about this later in the post.</p>
</li>
</ol>
<p>But for all these bans can be bypassed by using a VPN.</p>
<p>There are some countries, where using VPN is banned and the ISP and the government can track and fine VPN users even though they are using an end to end encrypted network. </p>
<p>I happened to live in one of these countries, where using VPN is not illegal but using a VPN to bypass blocked content is illegal. (the only thing I need a VPM for)</p>
<p>This is when my curiosity peeked. How is my ISP able to detect that I am using a VPN and flag accordingly even though I'm using an end to end encrypted connection that too over HTTPS?</p>
<h2 id="heading-bandwidth-throttling">Bandwidth Throttling</h2>
<p>You might have noticed in the title, I've written "throttles" in parenthesis instead of just blocks. That is because, in this country's laws, using VPN is not illegal. But using a VPN to bypass blocked websites and content is (basically only reason, I use VPN for)</p>
<p>Because of this reason, the ISP never completely blocks a VPN but throttles it. Now what does that mean?</p>
<blockquote>
<p>Bandwidth throttling is the intentional slowing or speeding of an internet service by an Internet service provider (ISP)</p>
</blockquote>
<p>This is exactly what I was experiencing. If you're not living in any of the European Union, your ISP most likely has two or even more that two network channels, a fast channel where you get very fast internet speed like 4G or 5G, and a slow channel where you get only a fraction of the internet speed you are paying for.</p>
<p>In my research, I speculate that my particular ISP has a third channel where there is next to nothing speed maybe like 20 or 30 bytes per second. And whenever they detect that I am using a VPN, they will flag that and put my connections on the third lane.</p>
<h2 id="heading-how-a-normal-internet-connection-works">How a normal internet connection works?</h2>
<p>Let's say that you want to connect to some website, <a target="_blank" href="https://idiomaticprogrammers.com">idiomaticprogrammers.com</a>, you will type idiomaticprogrammers.com onto your browser and it parses and detects that it is a website url.</p>
<p>Then the browser creates a packet that in simple terms looks like this.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606802017/192.168.1.27_43244_gczts7.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074566458/61ad2c5a-2109-4804-aedb-2e615e7e0e2d.jpeg" /></p>
<p>This application, let's say Chrome, wants to get the webpage in <a target="_blank" href="https://idiomaticprogrammers.com">idiomaticprogrammers.com</a> and send this packet to the router. There are many layers to this process which is not relevant in this post I will talk about them in detail in a future post.</p>
<p>You router looks at this packet and adds a record to its entry and replaces the local IP address with the router's IP which is actually connected to the internet.</p>
<p>After that, the router searches for the IP Address to where you want to send this packet to. But only information we've provided is the domain name idiomaticprogrammers.com, so the router first prepares a different packet which looks something like this.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606802515/routerIP_u8hqpx.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074567583/cea3b558-74c7-4053-bd16-14da328cda70.jpeg" /></p>
<p>This Router want to do a DNS lookup for <a target="_blank" href="https://idiomaticprogrammers.com">idiomaticprogrammers.com</a> and send it to a Domain Name Server. Which usually is your ISP but your can manually set the IP Address of the DNS in your router like 1.1.1.1 is Cloudflare's DNS and 8.8.8.8 is Google's DNS (I personally use 1.1.1.1)</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606802351/dns_tzvsmk.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074568937/33425a72-c1e2-489c-b2ce-9f84626ecd44.jpeg" /></p>
<p>What is DNS Lookup? It is a process of asking what is the IP address associated by this domain name.</p>
<p>Once the router knows the IP address for the domain name it simply replaces the domain name with the IP address and sends the request to the ISP.</p>
<p>Then the ISP looks at the packet can see that you want to go to this IP so it sends the request to that IP and then returns whatever information the web server provides back to the client.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606802648/get_cs2wni.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074570499/53edd5b1-10cb-4428-b5e6-03abb51c1c38.jpeg" /></p>
<p>Note that, if a website is using HTTPS, that is you can see a secured lock in front of the URL, there is no way for the ISP to know what information is returned by the website. Everything is encrypted end to end. I will be making an entire post about how this works in the future. But for now, this is a basic idea of how things work on the internet.</p>
<h2 id="heading-how-isp-blocks-a-particular-domain">How ISP blocks a particular domain?</h2>
<p>Remember how a router sends a DNS Lookup request to the Domain Name Server? No matter what DNS you are using either you ISP or some custom one. This request has to pass via your ISP because they are the ones who controls your internet and responsible for movement of data to and from your computer.</p>
<p>Every ISP has a long list domain provided by the government that they decided to block. Whenever you send a DNS Lookup request, the ISP checks if this domain is in that list. If it is, the it will be flagged and you will see a message like this domain does not exist or a page by the ISP saying this domain is blocked in this country.</p>
<p>Now you may ask, what if I entered the IP address directly? That might be possible, provided two conditions, 1. This IP address is not in the blacklist of the ISP and 2. The web server is configured to receive requests from the bare IP address. Believe it or not, we backend engineers do a lot of heavy lifting for you frontend devs.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606802933/Screen_Shot_2020-12-01_at_10.08.34_AM_iujag0.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074571842/71478771-8bda-4ad7-b484-f386b0de54f2.png" /></p>
<h2 id="heading-how-vpn-works">How VPN works?</h2>
<p>Going forward with the same example, let's say (god forbid) <a target="_blank" href="https://idiomaticprogrammers.com">idiomaticprogrammers.com</a> is banned in your country but you want to read that latest article we've posted. You connect to a VPN paid or free doesn't matter, at a network level the following is happening.</p>
<p>Your local IP is let's say 192.168.1.27 and somewhere on the planet there exist a server that has it's own private IP let's say 10.0.0.2. </p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606803494/vpn_qvkdbt.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074573402/1a0d7c6d-1a0f-4c57-8d4c-eae9051c3437.jpeg" /></p>
<p>Note the word private, meaning you have no way to connect to the server with private IP 10.0.0.1. What VPN does is this.</p>
<p>As you can see in my diagram, the VPN treats your computer as if it's a part of their network hence the word "Virtual" Private Network.</p>
<p><img src="https://res.cloudinary.com/idiomprog/image/upload/v1606803841/vpn-connected_gtu329.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074574857/0e729472-ed6b-40d4-a7ca-b63518f6f44e.jpeg" /></p>
<p>Now if you connect to <a target="_blank" href="https://idiomaticprogrammers.com">idiomaticprogrammers.com</a> your computer will make a packet like this, compare this with the packet the computer creates when it's not connected to any VPN.</p>
<p>There are extra information and this time it's going straight to the public IP address of the VPN, The VPN software you're. using crypts this packet and makes a new packet which essentially says, 192.168.1.27 wants to send this encrypted message to this public address let's say 123.66.6.234. The router will make this entry and forward this to the ISP</p>
<p>ISP looks at the packet, and just forward it this IP and it does as instructed.</p>
<p>The VPN server looks at the packet, decrypts it and because there are protocols, forwards it to 10.0.0.2 which then does all other processes like DNS Lookup and GET request to the website, encrypts whatever data it gets and simply forwards them back to us.</p>
<p>Now for idiomaticprogrammers.com, that VPN server makes all the requests and no one but the VPN and ISP knows our identity and that is what these VPN companies say "Anonymous", I say not really.</p>
<h2 id="heading-how-isp-throttles-vpn">How ISP throttles VPN?</h2>
<p>In the last part you've seen that those encrypted VPN connections pass through ISP. So theoretically, an ISP and make a list of all the VPN servers and whenever some data comes from these Public IP addresses it just says, "You might be a VPN, we have this special channel for you sir" and simply place our connection in a low bandwidth channel where the Internet speed is barely 20 or 30 bytes per second.</p>
<p>The same happens when you connect via TOR Protocol.</p>
<p>If you find some inconsistencies or theoretical error in this post please leave a comment below and I will correct myself as soon as possible.</p>
]]></content:encoded></item><item><title><![CDATA[Road to Machine Learning Engineer]]></title><description><![CDATA[What is Deep Learning?
In simple terms, Deep Learning is a subfield of Artificial Intelligence that tries to imitate the workings of a biological brain. Similar to a brain, in Deep Learning agent or the "brain" contains a nucleus also known as a Deep...]]></description><link>https://tanseersaji.com/road-to-machine-learning-engineer</link><guid isPermaLink="true">https://tanseersaji.com/road-to-machine-learning-engineer</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Thu, 29 Oct 2020 20:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074493325/150d8e51-a235-4ff4-afac-0acd541fa4a2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-deep-learning">What is Deep Learning?</h2>
<p>In simple terms, Deep Learning is a subfield of Artificial Intelligence that tries to imitate the workings of a biological brain. Similar to a brain, in Deep Learning agent or the "brain" contains a nucleus also known as a Deep Learning node, which is connected (theoretically) by Axons, notice that in the parenthesis, I've written "Theoretically", this is because when you write the code for this "Brain", the Axons are represented by multiplying the value in the Nucleus (mostly some floating-point number) by some random number called Weights, the "Learning" portion of Deep Learning consists of finding those values of Weights at which the Inputs can be transformed to the desired output.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074487960/44ad82fa-379c-4a8b-badb-8d24287ac358.png" alt /></p>
<p>These multiple neurons working together make a layer and when we add multiple layers then we can approximate any mathematical model given enough data and learning time. When a code contains 2 or more layers, then that is Deep Learning.</p>
<p>Deep Learning is a special case of Machine Learning. The logic used in Machine Learning is kinda like a regular program which is a way to get computers to complete a specific task.</p>
<p>Normally, it's easy for programmers to write each case and tell the computer what to do. But in the case of Machine Learning, we don't really know what to expect, the number of variables can be, in some cases, be more than a million. Hence, it doesn't make any sense to write millions of if-else block just to determine if a given photo is of a cat or a dog.</p>
<h2 id="heading-neural-networks">Neural Networks</h2>
<p>A Neural Network is like any function, which takes some input X and returns some output Y but the actual in that function is just take the input, multiply that with some number (called weights) and then pass it through some mathematical function that gives of results that is similar to Y.</p>
<h3 id="heading-weights-and-biases">Weights and Biases</h3>
<p>The basic idea of Weights and Biases comes from the mathematical equation</p>
<p>$$
y = mx + c
$$</p><p>where <strong>x</strong> is the input such as images of cats, <strong>y</strong> is the predicted output such as if a given image is a cat or not. Until now, it's pretty straight forward, in order to understand the role of <strong>m</strong> and <strong>c</strong>, that is, the slope and the y-intercept, in the learning process, we have to go all the way back to the era where the future prediction was done using statistical methods such as Linear Regression or Logistic Regression.</p>
<p>Let's say you need to predict a person's Weight using that person's BMI (Body Mass Index) then you might plot the data in a graph and draw a line through it such that the error is minimum. Which looks like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074489685/66dbfbcb-a5b3-4854-ba63-9e64b3fafe88.png" alt /></p>
<p>As you can see this line has some slope, m and some y-intercept, c. This logic applied to neural networks where the input vector is multiplied with some Weight vector (slope) then the Bias vector (y-intercept) is added to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074490590/763ba7d3-0601-4114-a733-0209cfe7b098.png" alt /></p>
<h3 id="heading-activation-function">Activation Function</h3>
<p>In the above image, you can see the after Input is combined with Weights and Bias, the result goes into an activation function. Now, what is an Activation Function?</p>
<p>In simple terms, it's just some function that converts the predicted output (<strong><em>XW + B</em></strong>) to a format that we need. Such is "Yes, this is a cat" or "No, it's not a cat"</p>
<p>There are 2 kinds of Activation function that you need to use according to the use case.</p>
<ol>
<li><p><strong>Linear Activation Function</strong>
It takes the form <strong><em>A = MX</em></strong> and produces outputs that are proportional to the input.</p>
</li>
<li><p><strong>Non-Linear Activation Functions</strong>
Modern neural network models use non-linear activation functions. They allow the model to create complex mappings between the network’s inputs and outputs, which are essential for learning and modelling complex data, such as images, video, audio, and data sets which are non-linear or have high dimensionality.</p>
</li>
</ol>
<h3 id="heading-loss-function">Loss Function</h3>
<p>The Loss Function is one of the important components of Neural Networks. Loss is nothing but a prediction error of Neural Net. And the method to calculate the loss is called Loss Function. In simple words, the Loss is used to calculate the gradients. And gradients are used to update the weights of the Neural Net.</p>
<h2 id="heading-limitations-of-machine-learning-and-deep-learning">Limitations of Machine Learning and Deep Learning</h2>
<p>Contrary to the popular belief that the AI will soon take over humanity, there is some limitation to the current technology of Artificial Intelligence.</p>
<ol>
<li><p>A model cannot be created without data</p>
</li>
<li><p>The model can only learn to operate on the patterns seen in the input data used to train it.</p>
</li>
<li><p>This learning approach only creates predictions and not 100% accurate future</p>
</li>
<li><p>The input data may be affected by human biases thus the trained model will also contain those biases.</p>
</li>
</ol>
<h2 id="heading-how-a-model-interacts-with-its-environment">How a model interacts with its environment?</h2>
<p>Any machine learning model learns through a feedback loop from the environment, Let's say that you created an AI that plays the game Super Mario Bros. The only thing you programmed was to press A and D key to move left or right and SPACE button to jump. Then you set up two reward system. 1) Your score in the game, which will be a positive reinforcement meaning you need to maximise the score and 2) how many times you get game over screen, which will be negative reinforcement so the AI needs to minimise the number of times it dies.</p>
<p>After that, you just leave the AI to play the game. The model will fist press the buttons randomly and slowly it starts to get feedback from the reward system and the model will eventually learn that Mushrooms in-game is good and Turtles are bad.</p>
<p>One limitation with this learning with feedback loop is that it might magnify the human biases which will then makes News Headlines such as this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074491924/40e20021-971a-4ce5-af8b-bfb10f86163e.png" alt /></p>
<p>As a Machine Learning Engineer, we need to be careful about how we choose our input data.</p>
<p>That is it for this lesson.</p>
<h2 id="heading-further-readings">Further Readings</h2>
<ol>
<li><a target="_blank" href="/post/machine-learning-in-a-nutshell/">Machine Learning in a Nutshell</a></li>
<li><a target="_blank" href="/post/perceptrons/">Perceptrons</a></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Create a Machine Learning Pipeline - Lesson 2]]></title><description><![CDATA[What is a Machine Learning Pipeline?
Data Preprocessing
Acquire Raw Data
Extract knowledge from Data
Prepare the data for the Neural Network
Build your first Neural Network
Training and Validation
Finalise the pipeline]]></description><link>https://tanseersaji.com/create-a-machine-learning-pipeline-lesson-2</link><guid isPermaLink="true">https://tanseersaji.com/create-a-machine-learning-pipeline-lesson-2</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Thu, 29 Oct 2020 20:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-a-machine-learning-pipeline">What is a Machine Learning Pipeline?</h2>
<h2 id="heading-data-preprocessing">Data Preprocessing</h2>
<h3 id="heading-acquire-raw-data">Acquire Raw Data</h3>
<h3 id="heading-extract-knowledge-from-data">Extract knowledge from Data</h3>
<h3 id="heading-prepare-the-data-for-the-neural-network">Prepare the data for the Neural Network</h3>
<h2 id="heading-build-your-first-neural-network">Build your first Neural Network</h2>
<h2 id="heading-training-and-validation">Training and Validation</h2>
<h2 id="heading-finalise-the-pipeline">Finalise the pipeline</h2>
]]></content:encoded></item><item><title><![CDATA[Build a Blog in x mins using Nuxt Content]]></title><description><![CDATA[Introduction
Nuxt.js is a framework for building Vue.js apps, Nuxt basically gives you everything out of the box that Vue does not. Features such as faster page loads, SEO Optimisation, Standardised folder structure, Modular architecture, etc.
You ca...]]></description><link>https://tanseersaji.com/build-a-blog-in-x-mins-using-nuxt-content</link><guid isPermaLink="true">https://tanseersaji.com/build-a-blog-in-x-mins-using-nuxt-content</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Sat, 19 Sep 2020 20:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Nuxt.js is a framework for building Vue.js apps, Nuxt basically gives you everything out of the box that Vue does not. Features such as faster page loads, SEO Optimisation, Standardised folder structure, Modular architecture, etc.</p>
<p>You can find a plugin for almost anything you want to add in your site. You can convert your application into a PWA in just 1 line of code.</p>
<p>In addition to that, Nuxt provides you with the feature to make your site completely static meaning you can prerender all the HTML, CSS and JS files required to run your site/application. And nuxt has relatively fasted build time compared to Angular or React and has a pretty smooth learning curve.</p>
<h2 id="heading-installation">Installation</h2>
<p>Nuxt provides a simple npx module to create the initial folder structure. Just write the following on a terminal or command prompt</p>
<pre><code class="lang-bash">npx create-nuxt-app MyBlog
</code></pre>
<p>Here "MyBlog" is the name of our blog that we are going to build. Feel free to be creative and name something amazing for your blog.</p>
<p>This step will ask you questions such as Project Name, If you will be using Javascript or Typescript (I am going to use Javascript), Will you use NPM or Yarn to install dependencies (I'll use NPM), What CSS framework you will be using (I'm going to import Bootstrap using CDN because that's easier for me, so I selected None)</p>
<p>After selecting the UI (CSS) Framework, it will ask you which Plugins to include. I'm going to include Content only for now and manually add rest of the plugins as I require to complete the project.</p>
<p>Then it will ask you to select the Linting Tool, It's always ESLint for me. After that, the setup will ask you to set up a testing framework. Since this is not a huge project, I wouldn't recommend that. So I'll select None.</p>
<p>Is your page is a Single Page App (SPA) or will it contain routing? We are building a blog so obviously there will be routing. So, go ahead and select Universal</p>
<p>Next question is very crucial, In this post, we will be building a completely static website. Therefore you will select Static in this stage.</p>
<p>Next is Development tools, don't worry about this, and select jsconfig.json, Then I will ask if you have a git version control system (In my case, I have a git where you can find all the code to this project) But you can select None if you want.</p>
<p>Once this step is completed, change directory into that folder. In my case, it's MyBlog</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> MyBlog
</code></pre>
<p>At this stage, you have created a nuxt.js application. You can see this by writing the following code in your terminal.</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Usually, it will run your website on [localhost port 3000](http://localhost:3000 "Localhost 3000"). You can see that in your terminal.</p>
<p>![Default NUXT.js Screen](https://res.cloudinary.com/idiomprog/image/upload/v1600600339/2020-09-20_15-10_dfl7cv.png "Default NUXT.js Screen")</p>
<p>This is just the beginning, we will create a functioning blog from here.</p>
<h2 id="heading-folder-structure">Folder Structure</h2>
<p>When you open the newly created folder in your text editor, you'll see something like this. Most of these folders are not that important for this project. Let me explain the ones that you'll use.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074642171/388b957c-a5a1-4bfe-9bad-6a06081dddf4.png" alt /></p>
<ol>
<li><strong>Assets:</strong> This folder will </li>
</ol>
<h2 id="heading-markdown-frontmatter">Markdown Frontmatter</h2>
<h2 id="heading-fetching-articles">Fetching Articles</h2>
<h2 id="heading-code-formatting">Code Formatting</h2>
<h2 id="heading-latex-support">Latex Support</h2>
<h2 id="heading-date-formatting-amp-read-time">Date Formatting &amp; Read Time</h2>
<h2 id="heading-add-image-support">Add Image Support</h2>
<h2 id="heading-youtube-embed">Youtube Embed</h2>
<h2 id="heading-generate-rss">Generate RSS</h2>
<h2 id="heading-generate-sitemap">Generate Sitemap</h2>
]]></content:encoded></item><item><title><![CDATA[5 techniques to Idiomatic Python (Loops)]]></title><description><![CDATA[Python is, in my opinion, one of the easiest and most versatile languages in computer science. If you write python code correctly, it is difficult to differentiate a python code from pseudo-code. But sometimes, in the process of writing the most beau...]]></description><link>https://tanseersaji.com/5-techniques-to-idiomatic-python-loops</link><guid isPermaLink="true">https://tanseersaji.com/5-techniques-to-idiomatic-python-loops</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Fri, 21 Aug 2020 06:44:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074558811/0c514600-4b09-46b3-92ae-4a8833257b02.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python is, in my opinion, one of the easiest and most versatile languages in computer science. If you write python code correctly, it is difficult to differentiate a python code from pseudo-code. But sometimes, in the process of writing the most beautiful python code, most developers forget one thing: the execution speed of the code.</p>
<p>You can write code that is so readable and a layman can confuse it as English written by someone with bad grammar skills, yet it is understandable. But that code takes more than 300ms to run. That might not be that much of a delay but in the programming world, it is a serious problem.</p>
<p>On the other hand, one can write the same code in a different idiom that it takes less than 10ms to run. But, even expert python developers undergo a hard time understanding it.</p>
<p>It is thus very imported, for a developer to strike a balance between these two extremes. These kinds of code are known as Idiomatic Code in the industry.</p>
<p>Idiomatic Code, by definition, is a code that does a common task in a common way for your language. In other words, idiomatic code is any code that is easy to read and at the same time, is extremely efficient.</p>
<p>I follow Raymond Hettinger (<a target="_blank" href="https://twitter.com/raymondh">@raymondh</a>) a lot on twitter, he is one of the core developers in the Python community and he has contributed a lot of code in the Python repository to make the python language more idiomatic.</p>
<p>In this blog, I will go through some of the techniques that will help you improve your python code. Starting with:</p>
<h3 id="heading-a-range">a. range()</h3>
<p>Let's start from the obvious, say you need to iterate from 2 to 10. So if you're like an absolute beginner you might write something like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>]:
    print(i)
</code></pre>
<p>Something like this works and is very understandable, it is not a scalable approach. What if you want to loop through 2 to 2 million.</p>
<p>In situations like this, you can use the <code>range(stop)</code> or <code>range(start, stop, [step,])</code> built-in function.</p>
<p>the <em>range</em> function automatically generates the list for you. For example, you can rewrite the above code as:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, <span class="hljs-number">11</span>):
    print(i)
</code></pre>
<p>Notice how I wrote start from 2 and end at 11 and not 10. This is because the range function loops till <code>stop - 1</code>. There is one more parameter in range function other than the start and stop, that is the step. Step determines how many numbers the range have to skip.</p>
<p>Let's say you need to print all even numbers from 2 to 10, in that case, the skip parameter will be 2. By default, it is 1.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>,<span class="hljs-number">11</span>,<span class="hljs-number">2</span>):
    print(i)

<span class="hljs-comment"># OUTPUT: 2 4 6 8 10</span>
</code></pre>
<p>Now let's say that you need to loop through a list. With the knowledge of range(), you might do this:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(cloths))
  print(cloths[i])
</code></pre>
<p>But in python, there is a better way:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> cloth <span class="hljs-keyword">in</span> cloths
  print(cloth)
</code></pre>
<h3 id="heading-b-zip">b. zip()</h3>
<p>Let's say you have two lists, colour and cloths, of different sizes and you want to pair them until the smaller list is over. In this case, you can write a code like this:</p>
<pre><code class="lang-python">colours = [<span class="hljs-string">'pink'</span>, <span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>]
cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

n = min(len(colours), len(cloths))
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n):
    print(colours[i], cloths[i])

<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># pink shirt</span>
<span class="hljs-comment"># red hat</span>
<span class="hljs-comment"># green socks</span>
</code></pre>
<p>Which is good, but you can also use the in-built function <code>zip(*iterables)</code> the best thing about this function is that you can pass any number of lists, not just two.
Let me rewrite the above code and then explain to you how zip works.</p>
<pre><code class="lang-python">colours = [<span class="hljs-string">'pink'</span>, <span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>]
cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> colour, cloth <span class="hljs-keyword">in</span> zip(colours, cloths):
    print(colour, cloth)

<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># pink shirt</span>
<span class="hljs-comment"># red hat</span>
<span class="hljs-comment"># green socks</span>
</code></pre>
<p>You might have guessed, zip takes any number of lists and returns another list that contains one element from each list. As you can see, both version produces the same output but the second one looks cleaner.</p>
<h3 id="heading-c-reversed">c. reversed()</h3>
<p>If you want to loop over a list in reverse order, the traditional method was something like this.</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(cloths)<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>):
  print(cloths[i])


<span class="hljs-comment"># Output</span>
<span class="hljs-comment"># -------</span>
<span class="hljs-comment"># shorts</span>
<span class="hljs-comment"># socks</span>
<span class="hljs-comment"># hat</span>
<span class="hljs-comment"># shirt</span>
</code></pre>
<p>But with Python, you can use the builtin function called reversed(). Take a look at this example:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> cloth <span class="hljs-keyword">in</span> reversed(cloths):
  print(cloth)


<span class="hljs-comment"># Output</span>
<span class="hljs-comment"># -------</span>
<span class="hljs-comment"># shorts</span>
<span class="hljs-comment"># socks</span>
<span class="hljs-comment"># hat</span>
<span class="hljs-comment"># shirt</span>
</code></pre>
<p>The second one is cleaner and faster than the first one.</p>
<h3 id="heading-d-enumerate">d. enumerate()</h3>
<p>You want to loop through a list along with the index. It's pretty straight forward in traditional programming:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(cloths)):
  print(i, cloths[i])


<span class="hljs-comment"># Output</span>
<span class="hljs-comment"># -------</span>
<span class="hljs-comment"># 0 shorts</span>
<span class="hljs-comment"># 1 socks</span>
<span class="hljs-comment"># 2 hat</span>
<span class="hljs-comment"># 3 shirt</span>
</code></pre>
<p>But there is a cleaner and more efficient way in python:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> i, cloth <span class="hljs-keyword">in</span> enumerate(cloths):
  print(i, cloth)


<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># -------</span>
<span class="hljs-comment"># 0 shorts</span>
<span class="hljs-comment"># 1 socks</span>
<span class="hljs-comment"># 2 hat</span>
<span class="hljs-comment"># 3 shirt</span>
</code></pre>
<h3 id="heading-e-sorted">e. sorted()</h3>
<p>You need to loop over a list in sorted order, instead of running a sorting algorithm, you can use the sorted() built-in method.</p>
<pre><code class="lang-python">nums = [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">1</span>,<span class="hljs-number">5</span>,<span class="hljs-number">2</span>]

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> sorted(nums):
  print(i)

<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># ------</span>
<span class="hljs-comment"># 1</span>
<span class="hljs-comment"># 2</span>
<span class="hljs-comment"># 2</span>
<span class="hljs-comment"># 3</span>
<span class="hljs-comment"># 5</span>
</code></pre>
<p>The python sorted function uses Tim Sort with an average complexity of n*log(n)</p>
<p>For reverse sorting, you can use the attribute <code>sorted(nums, reverse=True)</code></p>
<p>What you want to sort a list of strings.</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> cloth <span class="hljs-keyword">in</span> sorted(cloths):
  print(cloth)

<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># ------</span>
<span class="hljs-comment"># hat</span>
<span class="hljs-comment"># shirt</span>
<span class="hljs-comment"># shorts</span>
<span class="hljs-comment"># socks</span>
</code></pre>
<p>It will sort based on letters, but what if you want to sort based on length of the string, you can do that with key attribute. For example:</p>
<pre><code class="lang-python">cloths = [<span class="hljs-string">'shirt'</span>, <span class="hljs-string">'hat'</span>, <span class="hljs-string">'socks'</span>, <span class="hljs-string">'shorts'</span>]

<span class="hljs-keyword">for</span> cloth <span class="hljs-keyword">in</span> sorted(cloths, key=len):
  print(cloth)

<span class="hljs-comment"># OUTPUT</span>
<span class="hljs-comment"># ------</span>
<span class="hljs-comment"># hat</span>
<span class="hljs-comment"># shirt</span>
<span class="hljs-comment"># socks</span>
<span class="hljs-comment"># shorts</span>
</code></pre>
<p>So that was 5 techniques using with you can make your python code more idiomatic.</p>
]]></content:encoded></item><item><title><![CDATA[Perceptrons]]></title><description><![CDATA[What is Perceptron
A perceptron can be represented as a function that takes some input and gives off some output. This function any perceptron performs is same in all scenario, no matter what that perceptron is intended to do.

A perceptron takes the...]]></description><link>https://tanseersaji.com/perceptrons</link><guid isPermaLink="true">https://tanseersaji.com/perceptrons</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Wed, 12 Aug 2020 10:21:54 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-perceptron">What is Perceptron</h2>
<p>A perceptron can be represented as a function that takes some input and gives off some output. This function any perceptron performs is same in all scenario, no matter what that perceptron is intended to do.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074650448/1d435983-2e1f-40bd-adb3-9273d5e75851.png" alt /></p>
<p>A perceptron takes the inputs, which is an (n+1)-dimensional vector containing n <strong>input parameters</strong> and 1 <strong>bias variable</strong> and multiplies with the <strong>weight vector</strong> (an array of size n+1 and the first element being 1) and wraps it around an <strong>activation function</strong> and that becomes the output of the perception.</p>
<p>If that goes straight through your mind, let me explain.</p>
<p>No matter what’s the learning problem is, a machine learning algorithm always plots the inputs in a graph and try to find the optimum line that passes through this plotted points.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074651378/5dd94e5d-322d-48d0-a784-b53b54ad1e6f.png" alt /></p>
<p>A perceptron matches this behavior by multiplying inputs and weights and activating the product. Mathematically, this will only work if the first element of the weight vector is 1 and the first element of the input vector is the bias parameter. Consider the following code, that demonstrates what you just read in this paragraph.</p>
<pre><code class="lang-python"><span class="hljs-comment"># W is for weights vector.</span>
<span class="hljs-comment"># X is for input vector.</span>
X = [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">1</span>,<span class="hljs-number">3</span>,<span class="hljs-number">5</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">5</span>] <span class="hljs-comment"># Just some input vector.</span>
<span class="hljs-comment"># The first element ,ie, X[0] is the bias parameter</span>

W = np.random.rand(len(X))
w[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>
<span class="hljs-comment"># This will initialize the W vector with random numbers</span>
<span class="hljs-comment"># and sets the first element ,ie, W[0] to 1</span>
</code></pre>
<p>Now before we move further, let us talk about some machine learning jargon. We’ll start with</p>
<h4 id="heading-hypothesis-function">Hypothesis Function</h4>
<p>A “Hypothesis Function” is nothing but the mathematical function of the line or curve that fits the given data-set. A function that “fits” the data-set is the one that connects most of the points in the data-set with minimum error. The mathematical function can be demonstrated using the following code.</p>
<pre><code class="lang-python"><span class="hljs-comment"># np is an object of NumPy class</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hypothesis</span>(<span class="hljs-params">X,W</span>):</span>
    <span class="hljs-keyword">return</span> np.matmul(X,np.transpose(W))
</code></pre>
<p>The above hypothesis function gives any real number which is great when you are doing some regression task but when you are performing a classification task, you have to enclose the result of X*W in some function that has a range from 0 to 1. One function that is common and used a lot for this task is called “Sigmoid function”, mathematical code for that is as follows:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Y is the actual values</span>
<span class="hljs-comment"># corresponding to X in the data-set</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cost</span>(<span class="hljs-params">X,Y</span>):</span>
    sum = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i,x <span class="hljs-keyword">in</span> enumerate(hypothesis(X)):
        sum += (x - Y[i])**<span class="hljs-number">2</span>
    <span class="hljs-keyword">return</span> sum/(<span class="hljs-number">2</span>*len(X))
</code></pre>
<p>The above code demonstrate the cost function for a regression task but if you want to find the error in a classification task, you have to consider the following code.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cost</span>(<span class="hljs-params">X,Y</span>):</span>
    sum = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i,x <span class="hljs-keyword">in</span> enumerate(hypothesis(X)):
        sum += -(Y[i]*np.log(sigmoid(x))+(<span class="hljs-number">1</span>-Y[i])*np.log(<span class="hljs-number">1</span>-sigmoig(x)))
    <span class="hljs-keyword">return</span> sum/len(X)
</code></pre>
<p>If you want to learn in depth about cost functions, you can refer this video by Andrew Ng.</p>


<h3 id="heading-perceptron-algorithm">Perceptron algorithm</h3>
<p>The below code demonstrates an algorithm to find the optimum weights for our data set that can plot a line which best divides or fits the training data set, X.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getOptimumWeights</span>(<span class="hljs-params">X,Y,learn_rate,epoch</span>):</span>

    W = np.rand.random(len(X))
    W[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>
    i = <span class="hljs-number">0</span>
    <span class="hljs-keyword">while</span> i &gt; epoch:
        i += i
        error = cost(X,Y)
        <span class="hljs-keyword">for</span> w <span class="hljs-keyword">in</span> W[<span class="hljs-number">1</span>:]:
            w = w - learn_rate*error
    <span class="hljs-keyword">return</span> W
</code></pre>
<p>We first create a variable W and assign it to a list of random number with length equal to your number of training set. Then assign first element of W to 1. This is because <code>W[0]</code> corresponds to the Bias factor, that is, if you plot the hypothesis function as a graph then Bias factor decides the <code>y</code> point at <code>x = 0</code>.</p>
<p>Then we iteratively update the list <code>W</code> according to the <code>learning rate</code> and and <code>error</code>.</p>
<p><strong>Learning Rate</strong> is a tuning parameter in an optimization algorithm that determines the step size at each iteration while moving toward a minimum of a loss function. Take a look at this video.</p>


<p>Now that is done, let’s concentrate on the actual perceptron algorithm, a simple rule of a perceptron or any neural network is <strong><em>take the input, multiply by weights, add the bias and activate.</em></strong> As stated above, we can simulate the add the bias step be fixing the first element of W as 1 and the first element of training data set, X as the bias. The need of activate step or activation is to add a sense of non-linearity to the line that we want to fit, this will improve the accuracy of our model to a great extend and our perceptron or neural network can learn a wide variety of things. Consider the following code.</p>
<pre><code class="lang-python"><span class="hljs-comment"># X*W is basically equal to X*W + b,</span>
<span class="hljs-comment"># Remember take the input, multiply by weights, add the bias and activate</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">perceptron</span>(<span class="hljs-params">X,W</span>):</span>
    <span class="hljs-comment"># We are using sigmoid function to activate our hypothesis</span>
    output = sigmoid(X*W)
    <span class="hljs-keyword">return</span> output
</code></pre>
<p>before using this this function we need to do some pre-processing that is to train the weights vector W, remember the function we made called <em>getOptimumWeights</em> that function does this task. Theoretically, you can use any real number as the learning rate, but ideally, you have to use something that is neither too high nor too low. I always use <strong><em>0.01 or 0.005 as the learning rate</em></strong>.</p>
<h2 id="heading-using-perceptron-as-logical-gates">Using Perceptron as Logical Gates</h2>
<p>The best thing about neural networks or perceptron is that you can teach a computer to do any task by giving it some inputs and corresponding outputs.</p>
<p>First, lets teach this perceptron to learn and tell the outputs of an AND gate.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074652482/946ac0e8-c12f-4e84-b670-fa9f2247d827.png" alt /></p>
<pre><code class="lang-python">X = [[<span class="hljs-number">0</span>,<span class="hljs-number">0</span>],[<span class="hljs-number">0</span>,<span class="hljs-number">1</span>],[<span class="hljs-number">1</span>,<span class="hljs-number">0</span>],[<span class="hljs-number">1</span>,<span class="hljs-number">1</span>]]
Y = [<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>]

W = getOptimumWeights(X,Y,<span class="hljs-number">0.005</span>)
output = perceptron(X,W)

<span class="hljs-keyword">for</span> o <span class="hljs-keyword">in</span> output
    <span class="hljs-keyword">if</span> o &lt; <span class="hljs-number">0.5</span>:
        print(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-number">1</span>)
</code></pre>
<p>We created X and Y variables as per above image and passed it through previously created optimisation function. This gave us the Weights to predict the outputs using perceptron.</p>
<p>The output for above pipeline will be as follows.</p>
<pre><code><span class="hljs-number">0</span>
<span class="hljs-number">0</span>
<span class="hljs-number">0</span>
<span class="hljs-number">1</span>
</code></pre><p>This way, you can make any logical gates and when you combine multiple perceptrons, you’ll end up with a full fledged Neural Network that can be used to learn large data sets such as stock market, or text emotions if you want to make a chat bot that looks just like human chats. You can make Siri or Cortana using Neural Networks. Once you start using NNs or Machine Learning the possibilities are endless.</p>
<p>That is all for this post. If you like my content, make sure to subscribe to this blog and also share this post to your tech community.</p>
<p>Thank You.</p>
]]></content:encoded></item><item><title><![CDATA[Machine Learning – in a nutshell]]></title><description><![CDATA[Machine Learning
Machine learning (ML) is a category of algorithm that allows software applications to become more accurate in predicting outcomes without being explicitly programmed. The basic premise of machine learning is to build algorithms that ...]]></description><link>https://tanseersaji.com/machine-learning-in-a-nutshell</link><guid isPermaLink="true">https://tanseersaji.com/machine-learning-in-a-nutshell</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Wed, 12 Aug 2020 10:08:20 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-machine-learning">Machine Learning</h2>
<p>Machine learning (ML) is a category of algorithm that allows software applications to become more accurate in predicting outcomes without being explicitly programmed. The basic premise of machine learning is to build algorithms that can receive input data and use statistical analysis to predict an output while updating outputs as new data becomes available.</p>
<p>Basically, machine learning is the way that makes your smartphones “smart”, You often see in big corporate conventions they use Machine Learning and AI interchangeably even though these two topics are very different but connect in many ways. The goal of AI or Artificial Intelligence is to make a machine or robot that can mimic the capabilities of a human mind, which of course includes learning abilities but also understanding texts and languages (Natural Language Processing), ability to comprehend images and videos (Computer Vision) and other things a human can do.</p>
<p>[Tom M. Mitchell](https://en.wikipedia.org/wiki/Tom_M._Mitchell "Tom M. Mitchell") provided a widely quoted, more formal definition of the algorithms studied in the machine learning field: “A computer program is said to learn from experience <em>E</em> with respect to some class of tasks <em>T</em> and performance measure <em>P</em> if its performance at tasks in <em>T</em>, as measured by <em>P</em>, improves with experience <em>E</em>.”</p>
<p>In other words, Machine Learning is a <strong>part of AI</strong> that deals only with the learning abilities of a machine. All the algorithms and techniques that are dedicated to the task of teaching a machine to learn based on past experiences like Linear Regression, Support Vector Machines, Logistic Regression, Gradient Descent, etc all come under the field of Machine Learning.</p>
<p>But when these companies like Google or Apple wants to sell something, they use the term Artificial Intelligence or AI and when they talk about their projects to engineers and other experts, they use the term Machine Learning and Neural Networks.</p>
<p>Machine Learning can be split into three categories: Supervised Learning, Unsupervised Learning and Reinforcement Learning.</p>
<p><strong>Supervised Learning</strong> is the machine learning task of learning a function that maps an input to an output based on example input-output pairs. It infers a function from <em>labelled training data</em> consisting of a set of <em>training examples</em>. In supervised learning, each example is a <em>pair</em> consisting of an input object (typically a vector) and the desired output value (also called the <em>supervisory signal</em>). A supervised learning algorithm analyzes the training data and produces an inferred function, which can be used for mapping new examples. An optimal scenario will allow for the algorithm to correctly determine the class labels for unseen instances. This requires the learning algorithm to generalize from the training data to unseen situations in a “reasonable” way.</p>
<p><strong>Unsupervised learning</strong> is a branch of machine learning that learns from test data that has not been labelled, classified or categorized. Instead of responding to feedback, unsupervised learning identifies commonalities in the data and reacts based on the presence or absence of such commonalities in each new piece of data.</p>
<p><strong>Reinforcement learning</strong> (<strong>RL</strong>) is an area of machine learning concerned with how software agents ought to take <em>actions</em> in an <em>environment</em> so as to maximize some notion of cumulative <em>reward</em>. The problem, due to its generality, is studied in many other disciplines, such as game theory, control theory, operations research, information theory, simulation-based optimization, multi-agent systems, swarm intelligence, statistics and genetic algorithms. In the operations research and control literature, reinforcement learning is called <em>approximate dynamic programming,</em> or <em>neuro-dynamic programming.</em> The problems of interest in reinforcement learning have also been studied in the theory of optimal control, which is concerned mostly with the existence and characterization of optimal solutions, and algorithms for their exact computation, and less with learning or approximation, particularly in the absence of a mathematical model of the environment. In economics and game theory, reinforcement learning may be used to explain how equilibrium may arise under bounded rationality. In machine learning, the environment is typically formulated as a Markov Decision Process (MDP), as many reinforcement learning algorithms for this context utilize dynamic programming techniques. The main difference between the classical dynamic programming methods and reinforcement learning algorithms is that the latter does not assume knowledge of an exact mathematical model of the MDP and they target large MDPs where exact methods become infeasible.</p>
<p>We’ll be looking into algorithms for each of these categories in separate posts (due to SEO reasons)</p>
<p>If you paid attention to this post, I wrote something about Neural Network</p>
<h2 id="heading-what-is-a-neural-network">What is a Neural Network?</h2>
<p><strong>Artificial neural networks</strong> (<strong>ANN</strong>) or <strong>Neural Network (NN)</strong> are computing systems vaguely inspired by the biological neural networks that constitute animal brains. The neural network itself is not an algorithm, but rather a framework for many different machine learning algorithms to work together and process complex data inputs. Such systems “learn” to perform tasks by considering examples, generally without being programmed with any task-specific rules. For example, an image recognition, they might learn to identify images that contain cats by analyzing example images that have been manually labelled as “cat” or “no cat” and using the results to identify cats in other images. They do this without any prior knowledge about cats, for example, that they have fur, tails, whiskers and cat-like faces. Instead, they automatically generate identifying characteristics from the learning material that they process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074579106/41a88ca8-6594-4aa4-8288-4ad7ce8dbb31.png" alt /></p>
<p>Naturally, a question will arise in all Machine Learning beginners that if we have ML algorithms that can do almost all work with great accuracy, what is the need of Neural Networks?</p>
<p>One of my favorite Youtuber 3Blue1Brown has made a video about this</p>


<p>You can watch this video if you have 20 mins to spare, but I’ll try to summarize this video as accurate and as simple as possible.</p>
<p>Basically, a Neural Network, unlike a traditional Machine Learning algorithm, resembles more to the actual brain and the cells in a brain. And like the brain, a neural network is capable of learning different tasks. But if we use Machine Learning algorithms then we have to develop different algorithms for different tasks.</p>
<p>A neuron in a neural network is known as a Perceptron, a Perceptron just like any function takes some input and gives some output. And in machine learning, a perceptron is used in supervised learning both regression and classification.</p>
<p>In statistical modelling, <strong>regression</strong> analysis is a set of statistical processes for estimating the relationships among variables. It includes many techniques for modelling and analyzing several variables when the focus is on the relationship between a dependent variable and one or more independent variables.</p>
<p><strong>classification</strong> is the problem of identifying to which of a set of categories (sub-populations) a new observation belongs, on the basis of a training set of data containing observations (or instances) whose category membership is known.</p>
<p>We will learn about Perceptrons in the next post, in that post, we will also discuss a way with which we can make basic logic gates (AND, OR) and an optimization algorithm called Gradient Descent.</p>
<p>If you like my blog, then make sure that you follow this blog and also leave a like and share this post with your friends and colleagues. If you have any query then please leave a comment, I’ll reply to them as soon as possible.</p>
<p>Thank You.</p>
]]></content:encoded></item><item><title><![CDATA[Telegram Trivia Bot]]></title><description><![CDATA[`I was tasked to build a trivia chat-bot, and the upper management wanted to see a POC (Proof of Concept) by end of the day. Which means I had around 3 hours to build this POC. But there was one small problem, I had no idea how this is done.
In this ...]]></description><link>https://tanseersaji.com/telegram-trivia-bot</link><guid isPermaLink="true">https://tanseersaji.com/telegram-trivia-bot</guid><dc:creator><![CDATA[Tanseer Saji]]></dc:creator><pubDate>Sun, 09 Aug 2020 11:30:57 GMT</pubDate><content:encoded><![CDATA[<p>`I was tasked to build a trivia chat-bot, and the upper management wanted to see a POC (Proof of Concept) by end of the day. Which means I had around 3 hours to build this POC. But there was one small problem, I had no idea how this is done.</p>
<p>In this installment of our series TIL (Today I Learned), I will be writing about the story of how I was able to build a decent Quiz bot on telegram in less than 1 hour. (I wrote this post and watched some Youtube videos in the remaining 2 hours of my day)</p>
<p>As any software developer in this planet, I first went to GitHub to see if there is any code that I can straight up copy. But unfortunately, then once that were decent was like 2 years old. I started reading them and got to know about this node.js library for Telegram Bots API called <a target="_blank" href="https://www.npmjs.com/package/telegraf">Telegraf</a>.</p>
<p>Then I quickly built a fresh folder in my Projects directory and initiated npm.</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>After that, I installed telegraf (obviously)</p>
<pre><code class="lang-bash">npm i telegraf
</code></pre>
<p>Copy pasted the example code provided by Telegraf and realised there is a problem.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { Telegraf } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'telegraf'</span>)

<span class="hljs-keyword">const</span> bot = <span class="hljs-keyword">new</span> Telegraf(process.env.BOT_TOKEN)
bot.start(<span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> ctx.reply(<span class="hljs-string">'Welcome!'</span>))
bot.help(<span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> ctx.reply(<span class="hljs-string">'Send me a sticker'</span>))
bot.on(<span class="hljs-string">'sticker'</span>, <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> ctx.reply(<span class="hljs-string">'👍'</span>))
bot.hears(<span class="hljs-string">'hi'</span>, <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> ctx.reply(<span class="hljs-string">'Hey there'</span>))
bot.launch()
</code></pre>
<p>I don't actually have a "BOT TOKEN", the search of which led to me to this Telegram Bot called <a target="_blank" href="https://t.me/botfather">BotFather</a> which made it incredibly easy to get the BOT API Token.</p>
<p>After that I created an environment variable called <code>BOT_TOKEN</code> and assigned the Telegram token to it. Then I started the node serer by</p>
<pre><code class="lang-bash">node index.js
</code></pre>
<p>Searched my BOT on Telegram and ...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074527605/e0e91df4-b591-40e1-a837-2cb6d4c649cd.png" alt="Telegram Chat" /></p>
<p>So, 10 mins into code I have a basic chat bot ready. Since this was just a proof of concept, I didn't want to spend time of setting up database and stuff so I created a dictionary of current players and questions.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> questions = [
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"The tree sends down roots from its branches to the soil is know as:"</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"Oak"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Pine"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Banyan"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o3"</span>
    }
]
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> players = {}
</code></pre>
<p>For I had 5 questions, but for this blog, there is only one. Also, I will initiate the players dynamically later on.</p>
<p>In telegram, you can send predefined commands such as <code>/start</code> or <code>/help</code> and the chatbot manager can send appropriate replies. For this bot I decided, I will send this message whenever a new user sends me <code>/start</code> command.</p>
<pre><code class="lang-javascript">bot.start(<span class="hljs-function">(<span class="hljs-params">ctx</span>)=&gt;</span>{
    ctx.reply(<span class="hljs-string">`Hello, Are you ready to start the quiz?\nThere will be <span class="hljs-subst">${questions.length}</span> question, each scoring 1 points.`</span>)

    <span class="hljs-keyword">const</span> logo = fs.readFileSync(<span class="hljs-string">'img/logo.jpg'</span>)

    ctx.telegram.sendPhoto(ctx.chat.id, {
        <span class="hljs-attr">source</span>: logo
    }).catch(<span class="hljs-function"><span class="hljs-params">reason</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(reason)
    })
})
</code></pre>
<p>Basically, I wrote a custom function on the example code that telegraf provided. Now the chatbot will behave like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074529501/647161ee-006c-4295-baeb-0e44320ad1ae.png" alt /></p>
<blockquote>
<p>The code you're gonna see next is shit and redundant, that's what being a senior develop is all about.</p>
<p>~ Chris (10 years of experience in Software Engineering)</p>
</blockquote>
<p>Whenever the bot gets a message from a user, I want the manager to check if this player is new or have registered to the system. This can be done using a simple if condition since we are using in memory dictionaries.</p>
<pre><code class="lang-javascript">bot.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> userId = ctx.message.from.id;
    <span class="hljs-keyword">if</span> (userId <span class="hljs-keyword">in</span> players){
        <span class="hljs-keyword">if</span> (players[userId][<span class="hljs-string">'last_question'</span>] &gt;= questions.length){
            quiz_end_message = <span class="hljs-string">`You've completed the trivia ❤️❤️❤️, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>

            <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
                Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com/'</span>),
              ])

            ctx.reply(quiz_end_message, Extra.markup(keyboard))
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
              ])

            ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
        }
    } <span class="hljs-keyword">else</span> {
        players[userId] = {
            <span class="hljs-string">"last_question"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-string">"last_answer_time"</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime(),
            <span class="hljs-string">"score"</span>: <span class="hljs-number">0</span>
        }

        <span class="hljs-built_in">console</span>.log(userId)

        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
           [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o3,<span class="hljs-string">"o3"</span>)]
          ])
          ctx.reply(questions[<span class="hljs-number">0</span>].question, Extra.markup(keyboard))
    }
})
</code></pre>
<p>Just read the code, I'll explain what's going on in a minute.</p>
<p>First of all, we can get the ID of the user who just messaged us using</p>
<pre><code class="lang-javascript">ctx.message.from.id
</code></pre>
<p>then we checked if this id is already present in our memory, if it doesn't that means the <code>else</code> block will get executed, where we initiate the player and send the first question to the user.
The <code>keyboard</code> variable defines the option buttons for the quiz, which you can see in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074531220/710b40dd-3fec-4737-a12c-3b7292e5e92d.png" alt /></p>
<p>There are many kinds of Buttons that you can see on Telegraf docs, but I only needed <code>callbackButton</code> because using this I can get to know which button the user clicked.</p>
<p>But if that condition were true, that is, if a user has already registered. This I check if the player has completed the game in which case I just replied the score with a link.</p>
<p>In telegraf, you can define custom actions using <code>callbackButton</code> the one you saw above.</p>
<pre><code class="lang-javascript">Markup.callbackButton(questions[<span class="hljs-number">0</span>].o1,<span class="hljs-string">"o1"</span>)
</code></pre>
<p>The second parameter is the one that defines the name of the action.</p>
<pre><code class="lang-javascript">bot.action(<span class="hljs-string">'o1'</span>, <span class="hljs-keyword">async</span>(ctx) =&gt; {
    <span class="hljs-keyword">let</span> userId = ctx.callbackQuery.message.chat.id;

    updateScore(userId, <span class="hljs-string">'o1'</span>)

    <span class="hljs-keyword">if</span> (players[userId].last_question &gt;= questions.length){
        quiz_end_message = <span class="hljs-string">`You've completed the trivia ❤️❤️❤️, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com'</span>),
          ])

        ctx.reply(quiz_end_message, Extra.markup(keyboard))
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
          ])

        ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
    }

    ctx.deleteMessage()
})
</code></pre>
<p>This is how we create a custom action, this callback function is called when a user clicks option 1 or the first button. I didn't wanted to handle multiple questions  on a screen which led to a possibility that a user might click on a option for previous question. So, I just deleted the question once it's score is checked and updated the score.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateScore</span>(<span class="hljs-params">playerId ,option</span>)</span>{
    <span class="hljs-keyword">const</span> last_question =  players[playerId].last_question;

    <span class="hljs-built_in">console</span>.log(players)

    players[playerId][<span class="hljs-string">'last_question'</span>]++;

    <span class="hljs-keyword">if</span> (questions[last_question].answer === option){
        players[playerId].score++;
    }
}
</code></pre>
<p>With each click of the options, I am also checking if the user have completed the quiz, in which case I sent them the score and a link.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741074532285/9176a349-a18d-403f-8bdf-05158c8ff090.png" alt /></p>
<p>So that is it, it took me about 50 mins to build this and here is the entire code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { Telegraf } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"telegraf"</span>)
<span class="hljs-keyword">const</span> Extra = <span class="hljs-built_in">require</span>(<span class="hljs-string">'telegraf/extra'</span>)
<span class="hljs-keyword">const</span> Markup = <span class="hljs-built_in">require</span>(<span class="hljs-string">'telegraf/markup'</span>)

<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>)

<span class="hljs-keyword">const</span> bot = <span class="hljs-keyword">new</span> Telegraf(process.env.BOT_TOKEN)
bot.start(<span class="hljs-function">(<span class="hljs-params">ctx</span>)=&gt;</span>{
    ctx.reply(<span class="hljs-string">`Hello, Are you ready to start the quiz?\nThere will be <span class="hljs-subst">${questions.length}</span> question, each scoring 1 points.`</span>)

    <span class="hljs-keyword">const</span> logo = fs.readFileSync(<span class="hljs-string">'img/logo.jpg'</span>)

    ctx.telegram.sendPhoto(ctx.chat.id, {
        <span class="hljs-attr">source</span>: logo
    }).catch(<span class="hljs-function"><span class="hljs-params">reason</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(reason)
    })
})

<span class="hljs-keyword">let</span> players = {}

<span class="hljs-keyword">let</span> questions = [
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"The tree sends down roots from its branches to the soil is know as:"</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"Oak"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Pine"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Banyan"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o3"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"Electric bulb filament is made of "</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"Copper"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Lead"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Tungsten"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o3"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"Which of the following is used in pencils?"</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"Graphite"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Lead"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Silicon"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o1"</span>
    }, 
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"The speaker of the Lok Sabha can ask a member of the house to stop speaking and let another member speak. This phenomenon is known as :"</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"Crossing the floor"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Yielding the floor"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Calling Attention Motion"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o2"</span>
    },
    {
        <span class="hljs-string">"question"</span>: <span class="hljs-string">"The Comptroller and Auditor General of India can be removed from office in like manner and on like grounds as :"</span>,
        <span class="hljs-string">"o1"</span>: <span class="hljs-string">"High Court Judge"</span>,
        <span class="hljs-string">"o2"</span>: <span class="hljs-string">"Prime Minister"</span>,
        <span class="hljs-string">"o3"</span>: <span class="hljs-string">"Supreme Court  Judge"</span>,
        <span class="hljs-string">"answer"</span>: <span class="hljs-string">"o3"</span>
    },
]

bot.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> userId = ctx.message.from.id;
    <span class="hljs-keyword">if</span> (userId <span class="hljs-keyword">in</span> players){
        <span class="hljs-keyword">if</span> (players[userId][<span class="hljs-string">'last_question'</span>] &gt;= questions.length){
            quiz_end_message = <span class="hljs-string">`You've completed the trivia      🥳     🥳, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>

            <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
                Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com/'</span>),
              ])

            ctx.reply(quiz_end_message, Extra.markup(keyboard))
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
                [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
              ])

            ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
        }
    } <span class="hljs-keyword">else</span> {
        players[userId] = {
            <span class="hljs-string">"last_question"</span>: <span class="hljs-number">0</span>,
            <span class="hljs-string">"last_answer_time"</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getTime(),
            <span class="hljs-string">"score"</span>: <span class="hljs-number">0</span>
        }

        <span class="hljs-built_in">console</span>.log(userId)

        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
           [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[<span class="hljs-number">0</span>].o3,<span class="hljs-string">"o3"</span>)]
          ])
          ctx.reply(questions[<span class="hljs-number">0</span>].question, Extra.markup(keyboard))
    }
})

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateScore</span>(<span class="hljs-params">playerId ,option</span>)</span>{
    <span class="hljs-keyword">const</span> last_question =  players[playerId].last_question;

    <span class="hljs-built_in">console</span>.log(players)

    players[playerId][<span class="hljs-string">'last_question'</span>]++;

    <span class="hljs-keyword">if</span> (questions[last_question].answer === option){
        players[playerId].score++;
    }
}

bot.action(<span class="hljs-string">'o1'</span>, <span class="hljs-keyword">async</span>(ctx) =&gt; {
    <span class="hljs-keyword">let</span> userId = ctx.callbackQuery.message.chat.id;

    updateScore(userId, <span class="hljs-string">'o1'</span>)

    <span class="hljs-keyword">if</span> (players[userId].last_question &gt;= questions.length){
        quiz_end_message = <span class="hljs-string">`You've completed the trivia      🥳     🥳, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com/'</span>),
          ])

        ctx.reply(quiz_end_message, Extra.markup(keyboard))
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
          ])

        ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
    }

    ctx.deleteMessage()
})

bot.action(<span class="hljs-string">'o2'</span>, <span class="hljs-keyword">async</span>(ctx) =&gt; {
    <span class="hljs-keyword">let</span> userId = ctx.callbackQuery.message.chat.id;

    updateScore(userId, <span class="hljs-string">'o2'</span>)

    <span class="hljs-keyword">if</span> (players[userId].last_question &gt;= questions.length){
        quiz_end_message = <span class="hljs-string">`You completed the trivia, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com/'</span>),
          ])

        ctx.reply(quiz_end_message, Extra.markup(keyboard))
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
          ])

        ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
    }

    ctx.deleteMessage()
})

bot.action(<span class="hljs-string">'o3'</span>, <span class="hljs-keyword">async</span>(ctx) =&gt; {
    <span class="hljs-keyword">let</span> userId = ctx.callbackQuery.message.chat.id;

    updateScore(userId, <span class="hljs-string">'o3'</span>)

    <span class="hljs-keyword">if</span> (players[userId].last_question &gt;= questions.length){
        quiz_end_message = <span class="hljs-string">`You completed the trivia, you scored <span class="hljs-subst">${players[userId].score}</span> out of <span class="hljs-subst">${questions.length}</span>.`</span>
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            Markup.urlButton(<span class="hljs-string">'Click here to get the Prizes'</span>, <span class="hljs-string">'https://idiomaticprogrammers.com/'</span>),
          ])

        ctx.reply(quiz_end_message, Extra.markup(keyboard))
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">const</span> keyboard = Markup.inlineKeyboard([
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o1,<span class="hljs-string">"o1"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o2,<span class="hljs-string">"o2"</span>)],
            [Markup.callbackButton(questions[players[userId][<span class="hljs-string">'last_question'</span>]].o3,<span class="hljs-string">"o3"</span>)]
          ])

        ctx.reply(questions[players[userId][<span class="hljs-string">'last_question'</span>]].question, Extra.markup(keyboard))
    }

    ctx.deleteMessage()
})

bot.launch()
</code></pre>
<p>That is what I learned today.</p>
]]></content:encoded></item></channel></rss>