<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>prats.page</title>
  <subtitle></subtitle>
  <link href="https://prats.page/feed.xml" rel="self"/>
  <link href="https://prats.page/"/>
  
    <updated>2026-05-14T00:00:00Z</updated>
  
  <id>https://prats.page</id>
  <author>
    <name>Prateek Rathod</name>
    <email>emaillawrathod@gmail.com</email>
  </author>
  
    
    <entry>
      <title>DNDR - Flutter Reader App</title>
      <link href="https://prats.page/posts/dndr/"/>
      <updated>2020-07-15T00:00:00Z</updated>
      <id>https://prats.page/posts/dndr/</id>
      <content type="html">
        <![CDATA[
      <h1 id="%F0%9F%93%A6" tabindex="-1">📦</h1>
<hr>
<blockquote>
<h3 id="content" tabindex="-1">Content</h3>
<ul>
<li>WHY!</li>
<li>HOW!</li>
<li>WHAT NOW!</li>
</ul>
</blockquote>
<h2 id="why" tabindex="-1">WHY</h2>
<p>Imagine two guys just talking about some tech/framework (very easy to imagine I'm sure) which is fascinating to them and just like anybody else gets too excited to a point where one of them describes an idea for a mini-project on the spot. The descriptions go along the lines of something he himself would want to use and haven't found anything just like that. He proposes that there should be a reader application that should have profiles or some preset settings (like notifications, color tone, brightness. etc.) which are enabled whenever he is in the app, the other guy follows... As they use more words they now have a concept which is what this project is about and the framework in the discussion is a noob-friendly, cross-platform mobile framework we have all heard of, <strong><a href="https://flutter.dev">flutter</a></strong>. Flutter has become very popular and we wanted to try it out. The idea of writing code once and running it on multiple platforms is still very exciting to us and we wanted to give it a try. The guys forget about it the very next day but that's not the point for now. This was <strong>why</strong> this project was built. So let's quickly move on to <strong>how</strong> I built it using flutter and all of what I learned from this very first try at building a mobile application.</p>
<hr>
<h2 id="how" tabindex="-1">HOW</h2>
<p>Finally, the lockdown begins and I decide to come through with this project and write lines of <a href="https://dart.dev/">dart</a> code. To be honest I was more excited about making this project with vim because I had only become more familiar with this editor. I had to <strong>vim flex</strong>, I am not sorry about it.</p>
<h4 id="setup" tabindex="-1">Setup</h4>
<ul>
<li>Linux (latest kernel)</li>
<li>flutter (dev channel)</li>
<li>neovim with coc-flutter</li>
<li>Android Studio emulator</li>
<li>Github and Sourceforge</li>
</ul>
<p>I ran into numerous problems when Linux kernel v5.6 was released. Flutter hot-reload won't work or even <strong>flutter run</strong> won't work for some while. It was fixed soon but didn't reach the stable channel for long enough time therefore, had to make a switch to the dev channel in flutter.</p>
<p>The best thing about flutter is the availability of packages. The first package I had to use was a pdf viewer which I didn't want to write from scratch, then had to use a package for scrollbar and ended up using more packages than I would like. There's a package for even the tiniest of things with flutter.</p>
<h4 id="packages-used" tabindex="-1">Packages used</h4>
<ul>
<li>permission_handler: ^5.0.0+hotfix.6</li>
<li>flutter_full_pdf_viewer: ^1.0.6</li>
<li>path: ^1.7.0</li>
<li>draggable_scrollbar: ^0.0.4</li>
<li>flutter_launcher_icons: ^0.7.3</li>
<li>path_provider: ^1.6.11</li>
</ul>
<p>The package's names are self-explanatory and it's a very simple app so nothing complex is happening in that department.</p>
<h4 id="beginner%E2%80%99s-bad-luck" tabindex="-1">Beginner’s Bad Luck</h4>
<p>I would have loved a way to modularize/structure the code better and that's how I started in the beginning, turned out it became complex quickly, and then I ended up doing most of the things in a single file (since it’s a tiny app, <strong>very tiny</strong>) and minimum modules. The problem was some package classes were easier to instantiate and use without having a separate file for each. It makes the most sense because the packages in themselves are modules and need not be broken down any further.</p>
<p>One big note, flutter comes with dart so please keep it in mind before installing dart yourself separately, it will only waste disk space.</p>
<p>I spent a little longer on the syntax and testing little things which cost more time in the beginning and weren't necessary. Also didn't plan on how to keep persistent data in the beginning and moved ahead to just make things work and hack around to find the best practices.</p>
<p>I should have spent more time thinking about how I am going to implement persistent data storage on the device. I used basic file i/o operations to achieve that since I had to write a list. List isn’t that complex of a data structure but I would have liked it if I could have done it in a more efficient way. I tried finding a better way but failed. I have this feeling that there is a better way to do what I wanted to do and I ain't giving up looking for one anytime soon.</p>
<h4 id="things-which-are-beautiful-about-flutter%2Fdart" tabindex="-1">Things which are beautiful about flutter/dart</h4>
<p>I have read how people say dart is such a failed attempt at a coding language but I found it very easy to get started with. The syntax is very familiar to java or c++ and the standard library is rich which makes the development process much faster as well as more efficient. Flutter builds on top of dart and benefits from all of that. Even the memory management is top class with dart.</p>
<p>Async calls on dart worked for me without any hiccups and basically everything during the project had a positive impact on what I feel about mobile app development with flutter. There are a plethora of inbuilt classes for mostly all the purposes I needed.</p>
<p>How everything is so well integrated makes me appreciate the project even more. I learned that when I was trying to understand how to get storage permissions for my app. The declarative nature made a lot of sense to me.</p>
<h4 id="things-this-app-can-do" tabindex="-1">Things this app can do</h4>
<p>Everything a typical pdf viewer should do and more.</p>
<h4 id="things-i-wish-it-could-do" tabindex="-1">Things I wish it could do</h4>
<p>The things which would have made it a real good app were things like changing the phone sound profile or adjusting the brightness and display tone for the better reading experience, etc. Things like these are the bells and whistles of this project but it's still a good enough utility for someone looking for a very minimal and good looking pdf viewer.</p>
<p>The app cannot share the pdfs with other apps and that's something I want to add very soon as well as better ways to sort all the files in the list. For now, it is sorted based on the last access by the user.</p>
<p>I also am going to refactor the code and add comments for better understanding in the future (I suck at comments as of now; <strong>Update</strong>: I actually refactored the code and added comments, can’t believe myself, haha!).</p>
<h4 id="better-flow-with-github-action" tabindex="-1">Better flow with Github action</h4>
<p>With this project, I also tried Github actions for the first time and it wasn't as smooth of an experience. All of my work was being committed to the development branch of this project and I wanted to have the apk built and released using Github actions. So that's what I did and that's what has been happening for a while. I triggered it on the push to master which happens when dev is merged or something is pushed on the master branch. During this time I was all set to have the app on GitHub releases but found a simpler way to have the releases on Sourceforge. That's how I used Github actions for the first time with this project.</p>
<hr>
<h2 id="what-now" tabindex="-1">WHAT NOW</h2>
<p>This tiny little project was my first attempt with flutter and a few more things. There are missing features I would have loved to incorporate and I might do that in future.</p>
<p>I have some more ideas to try with flutter and that's exciting to me. I want to build something that could stream real time audio from a host to multiple clients using socket connections or something similar, I will start to build that very soon, I am still very confused about trying to make it using flutter or try native app development this time. Some more ideas in the pipeline are a <strong>DRINK WATER</strong> alert app along with a browser extension, a multiplayer math game using flutter, and some more.</p>
<p>If you have made it this far I would like to thank you for reading my very informal project entry and in case you want to collaborate with me on anything please feel free reach out, I would love to do that.</p>
<p><em>Live long and keep building stuff. Peace out!</em></p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>PDWM - Personal DWM Fork</title>
      <link href="https://prats.page/posts/pdwm/"/>
      <updated>2021-03-20T00:00:00Z</updated>
      <id>https://prats.page/posts/pdwm/</id>
      <content type="html">
        <![CDATA[
      <p>A personal dwm fork with a more practical and visually pleasing setup. It's just a bunch of patches and a few personal changes to the source. My <a href="https://github.com/lawRathod/pdwm">fork</a>.</p>
<hr>
<h2 id="brief" tabindex="-1">Brief</h2>
<p>Suckless's dwm is a dynamic window manager for Linux. It's one of the most popular window managers, but because of the suckless mentality, the default dwm is very minimal. It's reasonable and functional but lacks extra features. Luckily, the way patches work with dwm means you can transform it to look like other window managers. There are patches for the core and the bar. I've been using dwm for almost six months and have updated my fork with patches and customized the config. This post describes my dwm setup.</p>
<hr>
<h2 id="what-i've-got" tabindex="-1">What I've Got</h2>
<p>Here are the patches I've applied, in the order I applied them. (You can find a &quot;how-to apply a patch&quot; section at the end of this post.)</p>
<ul>
<li><strong><a href="https://dwm.suckless.org/patches/systray/">systray</a></strong> - Adds the system tray to the right corner of the status bar.</li>
<li><strong><a href="https://dwm.suckless.org/patches/autostart/">autostart</a></strong> - Lets you have a script called <code>~/.dwm/autostart.sh</code> that dwm runs every time it starts.</li>
<li><strong><a href="https://dwm.suckless.org/patches/vanitygaps/">vanitygaps</a></strong> - An eye-candy patch that adds gaps between windows in tile mode.</li>
<li><strong><a href="https://dwm.suckless.org/patches/hide_vacant_tags/">hide_vacant_tags</a></strong> - Hides vacant tags in the status bar.</li>
<li><strong><a href="https://github.com/lawRathod/pdwm/commit/83e517141f3d063e3bad285ca388294ae9f2e052#diff-62eebf5eaf0e6a76a21dfed9da6556ee5413ddb49f06013bd83403cc1a485d98">quickswitch</a></strong> - I made changes to the <code>dwm.c</code> file for this feature. This lets you switch between two windows next to each other with <strong>Alt+Tab</strong> (or whatever keybinding you set). This makes it more comfortable to transition from Windows to Linux and back. I'll try to create a patch from this to submit to suckless.</li>
</ul>
<p>These are the patches I've applied. Some other useful patches are <strong><a href="https://dwm.suckless.org/patches/colorbar/">colorbar</a></strong> and most of the patches related to the status bar. I highly suggest looking at the patches yourself to get the most out of dwm. Linux encourages customization, and dwm is highly customizable, so you can make it whatever you want.</p>
<p>Here are some of my scripts for the statusbar and the autostart script:</p>
<h3 id="autostart.sh" tabindex="-1">autostart.sh</h3>
<pre class="language-bash"><code class="language-bash"> <span class="token comment">#! /bin/bash</span>
 dunst <span class="token operator">&amp;</span>
 copyq <span class="token operator">&amp;</span>
 xss-lock <span class="token parameter variable">-v</span> <span class="token parameter variable">-l</span> xsecurelock <span class="token operator">&amp;</span>
 picom <span class="token operator">&amp;</span>
 nm-applet <span class="token operator">&amp;</span>
 feh --bg-scale /home/law/Downloads/wallpaper.jpg
 /home/law/apps/scripts/statusbar.sh <span class="token operator">&amp;</span></code></pre>
<h3 id="statusbar.sh" tabindex="-1">statusbar.sh</h3>
<pre class="language-bash"><code class="language-bash"> <span class="token comment">#!/bin/sh</span>

 <span class="token keyword">while</span> <span class="token builtin class-name">:</span>
 <span class="token keyword">do</span>
 /home/law/apps/scripts/statusbarnoloop.sh
 <span class="token function">sleep</span> <span class="token number">60</span>
 <span class="token keyword">done</span></code></pre>
<h3 id="statusbarnoloop.sh" tabindex="-1">statusbarnoloop.sh</h3>
<pre class="language-bash"><code class="language-bash"> <span class="token comment">#!/bin/sh</span>

 <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">date</span> <span class="token string">"+ %a, %d  %H:%M"</span><span class="token variable">)</span></span>
 <span class="token assign-left variable">mute</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span>pactl list sinks <span class="token operator">|</span> <span class="token function">awk</span> <span class="token string">'/Mute:/{ print $2 }'</span> <span class="token operator">|</span> <span class="token function">head</span> <span class="token parameter variable">-n</span> <span class="token number">1</span><span class="token variable">)</span></span>
 <span class="token assign-left variable">bat</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span>acpi <span class="token parameter variable">-b</span> <span class="token operator">|</span> <span class="token function">awk</span> <span class="token string">'{ print $4}'</span> <span class="token operator">|</span> <span class="token function">sed</span> <span class="token string">'s/%,//'</span><span class="token variable">)</span></span>
 <span class="token assign-left variable">batStat</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span>acpi <span class="token parameter variable">-b</span> <span class="token operator">|</span> <span class="token function">awk</span> <span class="token string">'{ print $3}'</span> <span class="token operator">|</span> <span class="token function">sed</span> <span class="token string">'s/,//'</span><span class="token variable">)</span></span>

 <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token parameter variable">-lt</span> <span class="token number">15</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token variable">$batStat</span> <span class="token operator">=</span> <span class="token string">'Discharging'</span> <span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token function">notify-send</span> <span class="token string">'Battery Low!'</span> <span class="token string">"Plug in the charger."</span>

 <span class="token keyword">elif</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token operator">=</span> <span class="token number">30</span> <span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token operator">=</span> <span class="token number">25</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token variable">$batStat</span> <span class="token operator">=</span> <span class="token string">'Discharging'</span> <span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token function">notify-send</span> <span class="token string">'Battery Low!'</span> <span class="token string">"Plug in the charger."</span>

 <span class="token keyword">elif</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token operator">=</span> <span class="token number">90</span> <span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token operator">=</span> <span class="token number">85</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token variable">$batStat</span> <span class="token operator">=</span> <span class="token string">'Charging'</span> <span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token function">notify-send</span> <span class="token string">'Charged!'</span> <span class="token string">"Remove the charger."</span>

 <span class="token keyword">elif</span> <span class="token punctuation">[</span> <span class="token variable">$bat</span> <span class="token parameter variable">-gt</span> <span class="token number">95</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">[</span> <span class="token variable">$batStat</span> <span class="token operator">=</span> <span class="token string">'Charging'</span> <span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token function">notify-send</span> <span class="token string">'Charged!'</span> <span class="token string">"Remove the charger."</span>

 <span class="token keyword">fi</span>

 <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token variable">$batStat</span> <span class="token operator">=</span> <span class="token string">'Charging'</span> <span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token assign-left variable">bat</span><span class="token operator">=</span><span class="token variable">$bat</span><span class="token string">" "</span>
 <span class="token keyword">else</span>
 <span class="token assign-left variable">bat</span><span class="token operator">=</span><span class="token variable">$bat</span><span class="token string">" "</span>
 <span class="token keyword">fi</span>

 <span class="token assign-left variable">volume</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span>amixer <span class="token parameter variable">-c</span> <span class="token number">1</span> <span class="token parameter variable">-M</span> <span class="token parameter variable">-D</span> pulse get Master <span class="token operator">|</span> <span class="token function">grep</span> <span class="token parameter variable">-o</span> <span class="token parameter variable">-E</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>:digit:<span class="token punctuation">]</span><span class="token punctuation">]</span>+% <span class="token operator">|</span> <span class="token function">awk</span> <span class="token string">"FNR &lt;= 1"</span><span class="token variable">)</span></span>

 <span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">$1</span> <span class="token operator">=</span> <span class="token string">"--ref"</span> <span class="token punctuation">]</span><span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token assign-left variable">temp</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">curl</span> <span class="token string">"api.openweathermap.org/data/2.5/weather?q=Jaisalmer&amp;appid={YOU_USE_YOURS}&amp;units=metric"</span> <span class="token operator">|</span> jq .main.temp<span class="token variable">)</span></span>
 <span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">$temp</span> <span class="token operator">=</span> <span class="token string">""</span> <span class="token punctuation">]</span><span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 <span class="token assign-left variable">temp</span><span class="token operator">=</span><span class="token string">" "</span>
 <span class="token keyword">else</span>
 <span class="token assign-left variable">temp</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token builtin class-name">printf</span> %0.f $temp<span class="token variable">)</span></span><span class="token string">"°C"</span>
 <span class="token keyword">fi</span>
 <span class="token builtin class-name">echo</span> <span class="token string">"<span class="token variable">$temp</span>"</span> <span class="token operator">></span> /home/law/apps/scripts/temp
 <span class="token keyword">fi</span>

 <span class="token assign-left variable">temp</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">cat</span> /home/law/apps/scripts/temp<span class="token variable">)</span></span>

 <span class="token keyword">if</span> <span class="token punctuation">[</span><span class="token punctuation">[</span> <span class="token variable">$mute</span> <span class="token operator">=</span> <span class="token string">"yes"</span> <span class="token punctuation">]</span><span class="token punctuation">]</span>
 <span class="token keyword">then</span>
 xsetroot <span class="token parameter variable">-name</span> <span class="token string">"  <span class="token variable">$bat</span>  <span class="token variable">$temp</span> 婢 mute <span class="token variable">$time</span> "</span>
 <span class="token keyword">else</span>
 xsetroot <span class="token parameter variable">-name</span> <span class="token string">"  <span class="token variable">$bat</span>  <span class="token variable">$temp</span> 墳 <span class="token variable">$volume</span> <span class="token variable">$time</span> "</span>
 <span class="token keyword">fi</span></code></pre>
<hr>
<h2 id="how-to-apply-patches" tabindex="-1">How to Apply Patches</h2>
<p>To apply a patch, use the following command in the project directory (in this case, dwm):</p>
<pre class="language-bash"><code class="language-bash"> patch <span class="token operator">&lt;</span> NAME_OF_THE_DIFF_FILE</code></pre>
<h4 id="did-it-fail-for-you%3F" tabindex="-1">Did it fail for you?</h4>
<p>Patching rarely succeeds on its own. A <strong>.diff</strong> file contains the location of the code that needs to change and what to replace it with. If you've modified those lines of code before, the patch will fail. You'll then have to manually look at the diff file and change the code yourself.</p>
<hr>
<p>That's my dwm fork, available on my <a href="https://github.com/lawRathod/">GitHub</a>. I've tried all the major window managers, but dwm feels the simplest and most extensible. I'm not a fan of the suckless mentality, but you should definitely give dwm a try; it's a great window manager.</p>
<hr>
<p>Thanks for reading! Have a great day.</p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>SyncP - Synchronized Media Player</title>
      <link href="https://prats.page/posts/syncp/"/>
      <updated>2021-09-10T00:00:00Z</updated>
      <id>https://prats.page/posts/syncp/</id>
      <content type="html">
        <![CDATA[
      <h2 id="brief" tabindex="-1">Brief</h2>
<p>SyncP (sync player) is a couple of Python scripts that use an mpv backend to play local media files in sync between hosts and clients. A host and a client are needed because it's a serverless app. A host must port-forward so clients can connect and sync media playback. The mpv backend is the core of the project; I was lucky to get a lot of help from <a href="https://github.com/jaseg/python-mpv">jaseg/python-mpv</a>.</p>
<p>In an age of streaming and screen-sharing applications, this project seems un-innovative, and it doesn't do much more than sync playback and listen for events like toggles (play/pause). But living in a third-world country, I don't have access to high-bandwidth, low-latency, unlimited data. Because of this, I had to think of something that wasn't streaming. Screen sharing and streaming both consume a lot of data, and syncP solves that problem entirely by using encoded text messages for communication between hosts and clients.</p>
<p>Initially, this project was limited to one client per host, but now it can have any number of clients. The project is available on <strong>pypi</strong> and can be installed with <code>pip install syncP</code>. After installation, <code>syncp --help</code> should be enough to get started. Before installing, you must set up mpv for the player to run; a guide is available in the repo at <a href="https://github.com/lawRathod/syncP">lawRathod/syncP</a>.</p>
<hr>
<h2 id="typical-use-case" tabindex="-1">Typical Use Case</h2>
<p>Since it can play any kind of media extension (lovely mpv), you can enjoy watching movies or TV shows or even listening to music with your friends.</p>
<hr>
<h2 id="behind-the-scenes" tabindex="-1">Behind the scenes</h2>
<p>The three major components of the project are the following scripts:</p>
<ul>
<li>host.py</li>
<li>client.py</li>
<li>player.py</li>
</ul>
<h3 id="host-script" tabindex="-1">Host script</h3>
<p>The host script must be started first by a host and will perform the following actions in order:</p>
<ul>
<li>Creates the object of the <code>player</code> class (inside <code>player.py</code>). The class constructor lets the user choose the media file to be played at the very beginning. The function returns a player object, which is later used to control the player.</li>
<li>Opens a port on the system and binds to it to start listening for connections. The app spawns a thread with a method and the socket passed as a parameter. The port is not forwarded yet and must be done using ngrok or manually using the router.</li>
<li>The player object returned at the very beginning is used in a method spawned in another thread. Playback is paused at the beginning, and one of the two threads is still waiting for the first connection.</li>
<li>The moment the socket receives a connection, it's appended to a linked list. This list is shared with <code>player.py</code> and all the threads. Every new connection is then appended to the list.</li>
<li>If any connection is dropped, it's removed from the list.</li>
<li>Playback is paused every time a connection is added or removed.</li>
</ul>
<p>These things are done consistently and allow the host to receive connections anytime while the process is running. The data sent between the host and clients are encoded text messages like <code>&quot;toggle&quot;</code> on playback toggle and <code>&quot;sync: time&quot;</code>, which is a way to sync the time between all the clients and the host. I figured I'd only allow hosts to sync time between connections. When a toggle message is received from a client, the host receives it, sends it to all other connections, and acts as a broadcaster.</p>
<p>The host starts the socket with the <code>keep_alive</code> flag to help the connections sustain the life of the media playback and not drop randomly after some time. I found this out the hard way, but the fix was easy and quick to implement.</p>
<h3 id="client-script" tabindex="-1">Client Script</h3>
<p>The client side of the project does very little compared to the host because I felt it should be kept as light as possible, with the host handling most of the complexities. The following happens on the client side:</p>
<ul>
<li>It prompts for a host URL and port number on which the host is accepting connections. The last connection is stored in a file in the package repository.</li>
<li>The user must select the media from the list of files in the current directory at this point.</li>
<li>After the media is selected, the client tries to connect to the host by spawning a new thread and a separate thread for the player.</li>
<li>If all goes well, the client receives the player's time from the host to seek on the client.</li>
</ul>
<p>That's all that happens. Once the connection is set, the app sends a keep-alive message to keep the connection alive, and now the host and client are in sync.</p>
<h3 id="player-script" tabindex="-1">Player Script</h3>
<p>This is the common module between the client and host that enables playback and sync operations. It primarily uses work from <a href="https://github.com/jaseg/python-mpv">jaseg/python-mpv</a>. The player class keeps event listeners, and media file selection tidy and in a module. The constructor brings all the necessary objects to the class for future use. Some event listeners for toggles and keys are also part of this script.</p>
<hr>
<h2 id="new-stuff-i-learned" tabindex="-1">New stuff I learned</h2>
<p>This was my first shot at working with a couple of things. Mainly, web sockets and threads took a little time to get used to. I learned how to create a systematic design that could come to life and get things done in the desired way. This was a cute little project for me to hack together in a little time to help me watch stuff with my friends. It's always a little challenging to bake an interface and make design choices when you aren't the only one using the app. This app is CLI-based, and I didn't have to design something as complex as a platform, which saved me a lot of time. I took some things for granted, like the abstractions Python has to offer, and I hope to understand them more deeply.</p>
<hr>
<h2 id="things-that-could've-been-better" tabindex="-1">Things that could've been better</h2>
<p>Here's a list of things where I think the app could have shined and provided a better experience. I'm not sure if I'm ever going to implement these because an application is never really &quot;finished.&quot;</p>
<ul>
<li><strong>Lack of a UI</strong>. A GUI could have solved this problem with nifty features like drag-and-drop instead of running the app in the directory where the file is located.</li>
<li><strong>A single point of truth in a cloud DB</strong>. This would eliminate the need for port forwarding on the host side. Everyone would listen for toggle changes and seek times.</li>
<li><strong>A chat window next to the player</strong>.</li>
</ul>
<p>I can think of many more, but it feels like a rabbit hole where you begin to imagine a completely different thing than what the app is right now.</p>
<hr>
<p>Thank you for making it this far. Have a great day! 😄</p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Membership Inference Attacks on Graph Neural Networks</title>
      <link href="https://prats.page/posts/rebMIGraph/"/>
      <updated>2025-09-11T00:00:00Z</updated>
      <id>https://prats.page/posts/rebMIGraph/</id>
      <content type="html">
        <![CDATA[
      <h1 id="can-your-graph-neural-network-keep-a-secret%3F-exploring-membership-inference-attacks-on-gnns" tabindex="-1">Can Your Graph Neural Network Keep a Secret? Exploring Membership Inference Attacks on GNNs</h1>
<p>Machine learning models are increasingly being trained on sensitive data, social networks, medical records, financial transactions. But here's an uncomfortable question: can an attacker figure out whether <em>your</em> data was used to train a model just by querying it?</p>
<p>This is the core question behind <strong>Membership Inference Attacks (MIA)</strong>, and in this project, I implemented a framework to test how vulnerable Graph Neural Networks are to this privacy threat.</p>
<h2 id="the-problem%3A-privacy-leakage-in-gnns" tabindex="-1">The Problem: Privacy Leakage in GNNs</h2>
<p>Graph Neural Networks have become the go-to architecture for learning on relational data, social networks, citation graphs, biological networks. But their very strength, leveraging neighborhood information, might also be their weakness.</p>
<p>When a GNN is trained on a graph, it learns patterns from the training nodes. The hypothesis is that the model behaves <em>differently</em> on data it has seen during training versus data it hasn't. An attacker can exploit this difference to infer membership.</p>
<h2 id="the-approach%3A-train-on-subgraph%2C-test-on-subgraph-(tsts)" tabindex="-1">The Approach: Train on Subgraph, Test on Subgraph (TSTS)</h2>
<p>I implemented the TSTS methodology from <a href="https://arxiv.org/abs/2101.06570">this research paper</a>. The attack works as follows:</p>
<ol>
<li><strong>Target Model</strong>: Train a GNN on the actual training data (the model we want to attack)</li>
<li><strong>Shadow Model</strong>: Train a similar GNN on synthetic data that mimics the real distribution</li>
<li><strong>Attack Model</strong>: Train a binary classifier that learns to distinguish &quot;in training&quot; vs &quot;out of training&quot; based on model outputs</li>
</ol>
<p>The key insight is that the shadow model helps the attacker learn what &quot;training data behavior&quot; looks like, even without access to the actual training data.</p>
<h2 id="implementation-highlights" tabindex="-1">Implementation Highlights</h2>
<h3 id="supported-gnn-architectures" tabindex="-1">Supported GNN Architectures</h3>
<p>The framework supports four popular GNN architectures:</p>
<ul>
<li><strong>GCN</strong> (Graph Convolutional Network) , The classic spectral approach</li>
<li><strong>GAT</strong> (Graph Attention Network) , Attention-based message passing</li>
<li><strong>GraphSAGE</strong> , Sampling-based inductive learning</li>
<li><strong>SGC</strong> (Simplified Graph Convolution) , Efficient linear approximation</li>
</ul>
<h3 id="advanced-feature-engineering" tabindex="-1">Advanced Feature Engineering</h3>
<p>One contribution of this implementation is enhanced feature engineering for the attack model. Beyond basic node features, I compute:</p>
<ul>
<li><strong>Degree statistics</strong>: In-degree, out-degree, normalized degree</li>
<li><strong>Clustering coefficients</strong>: Local clustering and triangle counts</li>
<li><strong>Centrality indicators</strong>: Hub, leaf, and isolated node flags</li>
<li><strong>Ego-network features</strong>: Aggregated neighbor statistics</li>
<li><strong>Feature interactions</strong>: Degree-weighted feature combinations</li>
</ul>
<p>These features help the attack model capture subtle differences in how the target model treats training vs. non-training nodes.</p>
<h3 id="improved-attack-model" tabindex="-1">Improved Attack Model</h3>
<p>The baseline attack model achieved ~70-75% accuracy. I developed an improved version with:</p>
<ul>
<li>5-layer architecture with BatchNorm and Dropout</li>
<li>Temperature scaling for better-calibrated posteriors</li>
<li>Learning rate scheduling for stable convergence</li>
</ul>
<p>This pushed attack accuracy to <strong>80-85%</strong> in some configurations.</p>
<h2 id="datasets" tabindex="-1">Datasets</h2>
<p>The framework works with both standard benchmarks and custom social network data:</p>
<p><strong>Standard Datasets</strong>: Cora, CiteSeer, PubMed, Flickr, Reddit</p>
<p><strong>Custom Datasets</strong>:</p>
<ul>
<li><strong>Twitch</strong>: Streamer networks with affiliate status prediction</li>
<li><strong>Event</strong>: Social event networks with gender prediction</li>
</ul>
<p>Each custom dataset contains ~256 subgraphs with ~120 nodes each, split into training, non-training, and synthetic subsets.</p>
<h2 id="results-summary" tabindex="-1">Results Summary</h2>
<table>
<thead>
<tr>
<th>Model</th>
<th>Dataset</th>
<th>Attack Accuracy</th>
<th>AUROC</th>
</tr>
</thead>
<tbody>
<tr>
<td>GAT</td>
<td>Twitch</td>
<td>48-52%</td>
<td>~0.50</td>
</tr>
<tr>
<td>GAT</td>
<td>Event</td>
<td>48-52%</td>
<td>~0.50</td>
</tr>
<tr>
<td>GCN</td>
<td>Twitch</td>
<td>50-55%</td>
<td>~0.52</td>
</tr>
<tr>
<td>SAGE</td>
<td>Event</td>
<td>48-50%</td>
<td>~0.49</td>
</tr>
</tbody>
</table>
<p>Interestingly, the attack performance varies significantly across configurations. Some subgraphs are highly vulnerable (attack correctly identifies 96% of training samples) while others are resistant.</p>
<h2 id="key-takeaways" tabindex="-1">Key Takeaways</h2>
<ol>
<li><strong>GNNs do leak membership information</strong>, though the extent varies by architecture and data</li>
<li><strong>Feature engineering matters</strong>, advanced graph features significantly improve attack success</li>
<li><strong>Model calibration is crucial</strong>, temperature scaling helps the attack model learn better decision boundaries</li>
<li><strong>Not all data is equally vulnerable</strong>, some subgraphs/nodes are more susceptible than others</li>
</ol>
<h2 id="what's-next%3F" tabindex="-1">What's Next?</h2>
<p>This framework provides a foundation for:</p>
<ul>
<li>Testing new GNN architectures for privacy vulnerabilities</li>
<li>Developing and evaluating defense mechanisms (differential privacy, regularization)</li>
<li>Understanding what makes certain data more vulnerable to membership inference</li>
</ul>
<h2 id="try-it-yourself" tabindex="-1">Try It Yourself</h2>
<p>The full code is available on <a href="https://github.com/lawRathod/uni-project-dec">GitHub</a>.</p>
<p>The code is organized into three main components:</p>
<pre><code>bridge.py          → Data format conversion (pickle → PyG)
rebmi_adapter.py   → Feature engineering &amp; data organization
TSTS.py            → Main attack pipeline
</code></pre>
<p>Configure your experiment in <code>TSTS.py</code>:</p>
<pre class="language-python"><code class="language-python">model_type <span class="token operator">=</span> <span class="token string">"GAT"</span>              <span class="token comment"># GCN/GAT/SAGE/SGC</span>
data_type <span class="token operator">=</span> <span class="token string">"Custom_Event"</span>      <span class="token comment"># Dataset selection</span>
CUSTOM_ADVANCED_FEATURES <span class="token operator">=</span> <span class="token boolean">True</span> <span class="token comment"># Enhanced features</span>
USE_IMPROVED_ATTACK <span class="token operator">=</span> <span class="token boolean">True</span>      <span class="token comment"># Improved attack model</span></code></pre>
<hr>
<p><em>This project was completed as part of my university coursework, implementing and extending the methodology from &quot;Membership Inference Attack on Graph Neural Networks&quot; (arXiv:2101.06570).</em></p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Building Minidote: A Distributed CRDT System in Elixir</title>
      <link href="https://prats.page/posts/minidote/"/>
      <updated>2026-01-23T00:00:00Z</updated>
      <id>https://prats.page/posts/minidote/</id>
      <content type="html">
        <![CDATA[
      <p>Distributed systems are hard. The moment you have multiple nodes trying to maintain consistent state, you face the classic CAP theorem tradeoffs. Do you sacrifice availability for consistency, or vice versa? What if you could have both?</p>
<p>That's where <strong>CRDTs</strong> (Conflict-free Replicated Data Types) come in, and why I built <strong>Minidote</strong> - an Elixir implementation of a distributed CRDT system with causal broadcast guarantees.</p>
<h2 id="the-problem-with-distributed-state" tabindex="-1">The Problem with Distributed State</h2>
<p>Traditional distributed systems rely on consensus protocols like Raft or Paxos to maintain consistency. While these provide strong guarantees, they come at a cost: during network partitions, nodes must either stop accepting writes or risk inconsistency.</p>
<p>For many applications - collaborative editors, shopping carts, social media feeds - availability matters more than linearizability. Users expect their actions to work, even if their connection is flaky.</p>
<h2 id="enter-crdts" tabindex="-1">Enter CRDTs</h2>
<p>CRDTs are data structures with a mathematical property: they can be modified independently on different nodes and always merge deterministically to the same state. No coordination required. No conflicts to resolve manually.</p>
<p>Minidote implements six CRDT types:</p>
<ul>
<li><strong>PN-Counter</strong> (operation &amp; state-based): Increment/decrement counters for metrics and tallies</li>
<li><strong>Add-Wins Set</strong>: Sets where additions beat concurrent removals - perfect for shopping carts</li>
<li><strong>Two-Phase Set</strong>: Sets with permanent deletion guarantees - ideal for blacklists</li>
<li><strong>Multi-Value Register</strong>: Preserves concurrent assignments until causality is established</li>
<li><strong>Enable-Wins Flag</strong>: Boolean flags where enable beats disable - great for feature toggles</li>
</ul>
<h2 id="architecture" tabindex="-1">Architecture</h2>
<p>Minidote is built as a layered system:</p>
<pre><code>┌─────────────────┐
│  Minidote API   │  ← Simple read/update interface
├─────────────────┤
│ Minidote.Server │  ← CRDT state + vector clocks
├─────────────────┤
│ BroadcastLayer  │  ← Causal ordering guarantees
├─────────────────┤
│   LinkLayer     │  ← Network abstraction + retries
├─────────────────┤
│  Persistence    │  ← Disk logs + state snapshots
└─────────────────┘
</code></pre>
<p><strong>Vector clocks</strong> track causal relationships between operations. If Alice's edit depends on Bob's, Minidote ensures Bob's change is applied first on all nodes - even if network delays cause them to arrive out of order.</p>
<p><strong>Causal broadcast</strong> propagates updates to all nodes while respecting these dependencies. Operations are logged to disk before broadcasting, enabling crash recovery through log replay.</p>
<h2 id="real-world-testing" tabindex="-1">Real-World Testing</h2>
<p>The test suite includes scenarios modeling actual distributed applications:</p>
<ul>
<li><strong>Collaborative document editing</strong> with multiple concurrent users</li>
<li><strong>E-commerce shopping carts</strong> with inventory management</li>
<li><strong>Social media platforms</strong> simulated across 10 nodes</li>
<li><strong>Crash recovery</strong> with persistent operation logs</li>
</ul>
<h2 id="honest-limitations" tabindex="-1">Honest Limitations</h2>
<p>Minidote is a learning project that demonstrates CRDT principles, not a production-ready database. Current limitations include:</p>
<ul>
<li><strong>No anti-entropy</strong>: Operations lost during partitions aren't synchronized later</li>
<li><strong>No bootstrap protocol</strong>: New nodes start with empty state</li>
<li><strong>Potential permanent divergence</strong>: Partitioned nodes may never fully converge</li>
</ul>
<p>These are deliberate simplifications to keep the codebase understandable.</p>
<h2 id="built-with-ai-assistance" tabindex="-1">Built With AI Assistance</h2>
<p>This project was developed with AI assistance using Claude Code and Windsurf. The experience demonstrated how AI tools can accelerate systems programming work while maintaining code quality.</p>
<h2 id="try-it-out" tabindex="-1">Try It Out</h2>
<p>Minidote is open source and available on GitHub:</p>
<p><strong><a href="https://github.com/lawRathod/minidote">github.com/lawRathod/minidote</a></strong></p>
<p>The repository includes comprehensive documentation on the design, broadcast model, and testing infrastructure. Clone it, run <code>mix test</code>, and explore how CRDTs enable distributed systems that are both available and eventually consistent.</p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>Master&#39;s in Informatik – Coursework &amp; Technical Archive</title>
      <link href="https://prats.page/posts/masters/"/>
      <updated>2026-02-20T00:00:00Z</updated>
      <id>https://prats.page/posts/masters/</id>
      <content type="html">
        <![CDATA[
      <p>This document is a structured academic record of the courses I completed during my Master’s degree at <a href="https://rptu.de/"><em>RPTU Kaiserslautern</em></a> and the key systems, concepts, and implementations I worked on.<br>
It serves as a comprehensive archive of my coursework.</p>
<hr>
<h1 id="academic-timeline" tabindex="-1">Academic Timeline</h1>
<h2 id="winter-semester-2023%2F24-(1st-semester)" tabindex="-1">Winter Semester 2023/24 (1st Semester)</h2>
<ul>
<li>Network Security</li>
<li>Protocols and Algorithms for Network Security</li>
<li>Database Systems</li>
<li>Very Deep Learning – Recent Methods and Technologies</li>
<li>Social Web Mining</li>
</ul>
<hr>
<h2 id="summer-semester-2024-(2nd-semester)" tabindex="-1">Summer Semester 2024 (2nd Semester)</h2>
<ul>
<li>Machine Learning I</li>
<li>Verification of Reactive Systems</li>
<li>Performance and Security Analysis</li>
</ul>
<hr>
<h2 id="winter-semester-2024%2F25-(3rd-semester)" tabindex="-1">Winter Semester 2024/25 (3rd Semester)</h2>
<ul>
<li>Decentralized Systems</li>
<li>Worst-Case Analysis of Distributed Systems</li>
<li>OS-Based Programming of Embedded Systems</li>
<li>Seminar: Privacy and Security</li>
<li>Programming Distributed Systems</li>
</ul>
<hr>
<h2 id="summer-semester-2025-(4th-semester)" tabindex="-1">Summer Semester 2025 (4th Semester)</h2>
<ul>
<li>Distributed Data Management</li>
<li>Human-Computer Interaction</li>
<li>Practical Machine Learning &amp; NLP with AWS</li>
<li>Engineering with Generative AI</li>
<li>Project: Secure Decentralized Systems</li>
</ul>
<hr>
<h1 id="distributed-systems-%26-infrastructure" tabindex="-1">Distributed Systems &amp; Infrastructure</h1>
<h2 id="programming-distributed-systems" tabindex="-1">Programming Distributed Systems</h2>
<p><strong>Project: MiniDote – Distributed Key-Value Store</strong><br>
Repository: <a href="https://github.com/lawRathod/minidote">https://github.com/lawRathod/minidote</a></p>
<!-- Report: [MiniDote Project Report – To Be Added] -->
<h3 id="covered-topics" tabindex="-1">Covered Topics</h3>
<ul>
<li>RPC / gRPC-based inter-node communication</li>
<li>Replication and synchronization mechanisms</li>
<li>Crash failure models</li>
<li>Network partition simulation</li>
<li>Consistency vs availability trade-offs</li>
<li>Distributed testing methodologies</li>
</ul>
<h3 id="what-i-implemented" tabindex="-1">What I Implemented</h3>
<ul>
<li>A replicated distributed key-value store</li>
<li>Inter-node synchronization logic</li>
<li>Failure scenario simulations</li>
<li>Convergence and correctness evaluation under partial failures</li>
</ul>
<hr>
<h2 id="distributed-data-management" tabindex="-1">Distributed Data Management</h2>
<h3 id="covered-topics-1" tabindex="-1">Covered Topics</h3>
<ul>
<li>Data sharding and partitioning strategies</li>
<li>Replication models</li>
<li>Distributed transactions</li>
<li>Storage consistency models</li>
<li>Trade-offs between performance and correctness</li>
</ul>
<hr>
<h2 id="worst-case-analysis-of-distributed-systems" tabindex="-1">Worst-Case Analysis of Distributed Systems</h2>
<h3 id="covered-topics-2" tabindex="-1">Covered Topics</h3>
<ul>
<li>Adversarial and worst-case system modeling</li>
<li>Latency bounds under failures</li>
<li>Formal reasoning about distributed correctness</li>
<li>Resilience analysis under constrained system assumptions</li>
</ul>
<hr>
<h1 id="decentralized-%26-secure-systems" tabindex="-1">Decentralized &amp; Secure Systems</h1>
<h2 id="decentralized-systems" tabindex="-1">Decentralized Systems</h2>
<p><strong>Project: IPFS Lab &amp; Kubo Modification</strong><br>
Repository: <a href="https://github.com/lawRathod/ipfs-lab">https://github.com/lawRathod/ipfs-lab</a></p>
<!-- Report: [IPFS Lab Report – To Be Added] -->
<h3 id="covered-topics-3" tabindex="-1">Covered Topics</h3>
<ul>
<li>Peer-to-peer networking architectures</li>
<li>Content-addressable distributed storage</li>
<li>Peer discovery and bootstrapping mechanisms</li>
<li>Distributed topology formation</li>
<li>Network convergence behavior</li>
</ul>
<h3 id="additional-work" tabindex="-1">Additional Work</h3>
<ul>
<li>Patched Kubo (IPFS implementation) to disable automatic bootstrapping</li>
<li>Conducted controlled peer topology experiments</li>
<li>Evaluated replication and connectivity dynamics</li>
<li>Observed network behavior under constrained bootstrap conditions</li>
</ul>
<hr>
<h2 id="project%3A-secure-decentralized-systems" tabindex="-1">Project: Secure Decentralized Systems</h2>
<p>Repository: <a href="https://github.com/lawRathod/uni-project-dec">https://github.com/lawRathod/uni-project-dec</a></p>
<!-- Report: [Secure Decentralized Systems Report – To Be Added] -->
<h3 id="covered-topics-4" tabindex="-1">Covered Topics</h3>
<ul>
<li>Threat modeling for distributed systems</li>
<li>Secure multi-node architecture design</li>
<li>Authentication and communication integrity</li>
<li>Adversarial resilience evaluation</li>
<li>Secure protocol integration</li>
</ul>
<hr>
<h2 id="network-security" tabindex="-1">Network Security</h2>
<h3 id="covered-topics-5" tabindex="-1">Covered Topics</h3>
<ul>
<li>TLS and secure channel establishment</li>
<li>Authentication mechanisms</li>
<li>Secure API design principles</li>
<li>Network threat modeling</li>
</ul>
<hr>
<h2 id="protocols-and-algorithms-for-network-security" tabindex="-1">Protocols and Algorithms for Network Security</h2>
<h3 id="covered-topics-6" tabindex="-1">Covered Topics</h3>
<ul>
<li>Cryptographic protocol construction</li>
<li>Secure key exchange mechanisms</li>
<li>Protocol-level security analysis</li>
<li>Formal reasoning about secure communication</li>
<li>Security-performance trade-offs</li>
</ul>
<hr>
<h2 id="seminar%3A-privacy-and-security" tabindex="-1">Seminar: Privacy and Security</h2>
<!-- Report: [Asynchronous Vertical Federated Learning Survey – To Be Added] -->
<h3 id="seminar-focus" tabindex="-1">Seminar Focus</h3>
<p>Asynchronous Vertical Federated Learning (AVFL)</p>
<h3 id="covered-topics-7" tabindex="-1">Covered Topics</h3>
<ul>
<li>Federated learning paradigms (horizontal vs vertical)</li>
<li>Vertically partitioned collaborative training</li>
<li>Asynchronous model update mechanisms</li>
<li>Delayed gradient challenges</li>
<li>Resource heterogeneity in distributed learning systems</li>
<li>Communication constraints in federated environments</li>
</ul>
<h3 id="methods-studied" tabindex="-1">Methods Studied</h3>
<ul>
<li>Asynchronous Stochastic Gradient Descent (ASGD)</li>
<li>Variance reduction techniques (SVRG, SAGA)</li>
<li>Gradient prediction via Taylor approximations</li>
<li>Secure aggregation protocols</li>
<li>Cryptographic privacy-preserving mechanisms</li>
</ul>
<h3 id="key-observations" tabindex="-1">Key Observations</h3>
<ul>
<li>Trade-offs between efficiency, accuracy, and privacy</li>
<li>Convergence behavior under asynchronous updates</li>
<li>Communication-efficient optimization strategies</li>
<li>Resource utilization improvements over synchronous approaches</li>
<li>Architectural considerations for scalable privacy-preserving learning</li>
</ul>
<hr>
<h1 id="systems-performance-%26-verification" tabindex="-1">Systems Performance &amp; Verification</h1>
<h2 id="performance-and-security-analysis" tabindex="-1">Performance and Security Analysis</h2>
<h3 id="covered-topics-8" tabindex="-1">Covered Topics</h3>
<ul>
<li>Latency and throughput benchmarking</li>
<li>Profiling distributed systems</li>
<li>Bottleneck identification</li>
<li>Performance tuning methodologies</li>
<li>Security-performance interaction analysis</li>
</ul>
<hr>
<h2 id="verification-of-reactive-systems" tabindex="-1">Verification of Reactive Systems</h2>
<h3 id="covered-topics-9" tabindex="-1">Covered Topics</h3>
<ul>
<li>Model checking</li>
<li>State machine verification</li>
<li>Formal correctness guarantees</li>
<li>Specification validation of reactive systems</li>
</ul>
<hr>
<h2 id="os-based-programming-of-embedded-systems" tabindex="-1">OS-Based Programming of Embedded Systems</h2>
<h3 id="covered-topics-10" tabindex="-1">Covered Topics</h3>
<ul>
<li>Concurrency primitives</li>
<li>Resource-constrained systems programming</li>
<li>Low-level memory and hardware interaction</li>
<li>Real-time execution considerations</li>
</ul>
<hr>
<h1 id="machine-learning-%26-ai-systems" tabindex="-1">Machine Learning &amp; AI Systems</h1>
<h2 id="machine-learning-i" tabindex="-1">Machine Learning I</h2>
<h3 id="covered-topics-11" tabindex="-1">Covered Topics</h3>
<ul>
<li>Supervised learning algorithms</li>
<li>Model evaluation techniques</li>
<li>Regularization and optimization</li>
<li>Bias-variance trade-offs</li>
<li>Generalization analysis</li>
</ul>
<hr>
<h2 id="very-deep-learning-%E2%80%93-recent-methods-and-technologies" tabindex="-1">Very Deep Learning – Recent Methods and Technologies</h2>
<h3 id="covered-topics-12" tabindex="-1">Covered Topics</h3>
<ul>
<li>Transformer architectures</li>
<li>Deep neural optimization strategies</li>
<li>Scaling considerations for large models</li>
<li>Compute and memory trade-offs</li>
<li>Empirical evaluation of architectures</li>
</ul>
<hr>
<h2 id="practical-machine-learning-%26-nlp-with-aws" tabindex="-1">Practical Machine Learning &amp; NLP with AWS</h2>
<h3 id="covered-topics-13" tabindex="-1">Covered Topics</h3>
<ul>
<li>Cloud-based ML deployment</li>
<li>Model serving architectures</li>
<li>CI/CD pipelines for ML workflows</li>
<li>Monitoring and scaling ML systems</li>
<li>Infrastructure considerations for production ML</li>
</ul>
<hr>
<h2 id="engineering-with-generative-ai" tabindex="-1">Engineering with Generative AI</h2>
<p><strong>Project: Generative AI Portfolio</strong><br>
Repository: <a href="https://github.com/lawRathod/gen-ai-portfolio">https://github.com/lawRathod/gen-ai-portfolio</a></p>
<h3 id="covered-topics-14" tabindex="-1">Covered Topics</h3>
<ul>
<li>LLM orchestration patterns</li>
<li>Prompt engineering strategies</li>
<li>Structured output generation</li>
<li>Inference pipeline design</li>
<li>Latency-aware model integration</li>
</ul>
<h3 id="what-i-built" tabindex="-1">What I Built</h3>
<ul>
<li>Modular LLM-based applications</li>
<li>Inference workflows integrating external APIs</li>
<li>Evaluation mechanisms for output reliability</li>
</ul>
<hr>
<h2 id="social-web-mining" tabindex="-1">Social Web Mining</h2>
<h3 id="covered-topics-15" tabindex="-1">Covered Topics</h3>
<ul>
<li>Large-scale data collection methods</li>
<li>Feature extraction pipelines</li>
<li>Data preprocessing and cleaning</li>
<li>Statistical analysis of heterogeneous and noisy datasets</li>
</ul>
<hr>
<h1 id="databases-%26-human-centered-systems" tabindex="-1">Databases &amp; Human-Centered Systems</h1>
<h2 id="database-systems" tabindex="-1">Database Systems</h2>
<h3 id="covered-topics-16" tabindex="-1">Covered Topics</h3>
<ul>
<li>Indexing strategies</li>
<li>Query optimization</li>
<li>Storage engine fundamentals</li>
<li>Transaction isolation levels</li>
<li>Database performance considerations</li>
</ul>
<hr>
<h2 id="human-computer-interaction" tabindex="-1">Human-Computer Interaction</h2>
<h3 id="covered-topics-17" tabindex="-1">Covered Topics</h3>
<ul>
<li>Usability evaluation methods</li>
<li>Interface design principles</li>
<li>User-centered system design</li>
<li>Interaction modeling and evaluation techniques</li>
</ul>
<hr>
<h1 id="core-themes-across-the-degree" tabindex="-1">Core Themes Across the Degree</h1>
<ul>
<li>Distributed systems implementation</li>
<li>Replication and synchronization</li>
<li>Secure multi-node architectures</li>
<li>Performance benchmarking and tuning</li>
<li>Fault tolerance modeling</li>
<li>Privacy-preserving distributed learning</li>
<li>Cloud-based ML deployment</li>
<li>Deep learning and generative AI systems</li>
<li>Protocol-level security reasoning</li>
<li>Low-level systems programming</li>
</ul>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>bgrem — Running AI Background Removal Entirely in the Browser</title>
      <link href="https://prats.page/posts/bgrem/"/>
      <updated>2026-04-05T00:00:00Z</updated>
      <id>https://prats.page/posts/bgrem/</id>
      <content type="html">
        <![CDATA[
      <p>I've been thinking a lot about what it means to run AI models without a server. Not in the abstract &quot;edge computing&quot; sense, but literally just in the browser, on your own machine, with nothing leaving your computer. That's what bgrem is.</p>
<p>It's a small PWA that runs Hugging Face's background-removal models entirely client-side using ONNX Runtime and WebAssembly. You drop an image in, it generates a mask, and you download it. No uploads, no API keys, no server costs. Just your browser doing the work.</p>
<p>I didn't set out to build the most sophisticated background removal tool. I wanted to see what's actually possible right now in the browser, with real models, on real hardware.</p>
<h2 id="how-it-works" tabindex="-1">How it works</h2>
<p>The app uses <code>@huggingface/transformers</code> to load ONNX models and run inference through WebAssembly. When you open the page, the model downloads and caches locally. After that, everything runs offline.</p>
<p>There are multiple models available — ISNet-ONNX, RMBG-1.4, and MODNet — each with different tradeoffs between size, speed, and quality. You pick one, load an image, and hit generate. The model processes it in the browser and returns a mask PNG.</p>
<p>I also added a benchmark mode that runs all models sequentially against the same image and shows you a comparison table with load times, inference times, and sizes. It's useful if you're trying to figure out which model works best for your use case.</p>
<h2 id="why-no-server" tabindex="-1">Why no server</h2>
<p>The obvious question is why not just send the image to a server and get the result back. There are a few reasons.</p>
<p>Privacy is the main one. You're not uploading your images anywhere. They stay on your machine the entire time. For a lot of use cases, that matters more than people think.</p>
<p>Then there's the cost thing. Running inference on a server means GPUs, infrastructure, scaling, all of that. Running it in the browser means the user's machine does the work, and it's free. The tradeoff is speed — it's not going to be as fast as a GPU server — but for a lot of cases, it's fast enough.</p>
<p>And honestly, I just wanted to see if it could be done well. The answer is yes, with some caveats.</p>
<h2 id="what-i-learned" tabindex="-1">What I learned</h2>
<p>Working with ONNX in the browser is not something I had done before. The Hugging Face transformers library makes it surprisingly straightforward, but there are still details you need to figure out. WASM paths, model loading states, keeping the UI responsive during inference — all of that takes some thought.</p>
<p>One thing that surprised me is how well it works as a PWA. Once the model is cached, the whole thing runs offline. You can close the tab, come back later, and it just works. The service worker handles caching the app shell and the model files, so there's no need to re-download anything.</p>
<p>I also spent time on the UI side of things. There's a network status LED that shows whether you're online, fetching, or offline-ready. Side-by-side preview for the original and the mask. Zoom overlay for inspecting details. Small things, but they make the experience feel more polished.</p>
<h2 id="the-models" tabindex="-1">The models</h2>
<p>Each model has its own characteristics. ISNet-ONNX is a good balance of quality and speed. RMBG-1.4 tends to produce cleaner edges but takes a bit longer. MODNet is lighter and faster but sometimes misses finer details.</p>
<p>The benchmark mode lets you see these differences directly. Load an image, run all models, compare the results. It's not a scientific benchmark — it's just one image on your machine — but it gives you a sense of what to expect.</p>
<h2 id="where-it's-going" tabindex="-1">Where it's going</h2>
<p>Right now it does one thing: remove backgrounds and export masks. I'm not sure there's much more to add honestly. Maybe more models over time as better ones become available. Maybe some quality-of-life improvements.</p>
<p>But I think the interesting part isn't the feature set. It's the approach. Running AI models in the browser changes the whole equation. No server, no data collection, no costs. Just code running on your machine.</p>
<p>That feels like the right direction for a lot of tools.</p>
<p>The app is live at <a href="https://experiments.prats.page/bgrem">experiments.prats.page/bgrem</a> and the code is on <a href="https://github.com/lawRathod/bgrem">GitHub</a> if you want to look at how it's put together.</p>
<hr>
<p>Thank you for making it this far. Have a great day! 😄</p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>KubeCon Europe 2026: First Impressions from the Cloud Native Frontier</title>
      <link href="https://prats.page/posts/kubecon-2026/"/>
      <updated>2026-04-05T00:00:00Z</updated>
      <id>https://prats.page/posts/kubecon-2026/</id>
      <content type="html">
        <![CDATA[
      <p>It's been a week since KubeCon Europe 2026 and I can already feel it slipping away. Not the big moments, but the small details, the random conversations, the exact feeling of being there. So I wanted to write this before it turns into a generic &quot;yeah it was great&quot; memory.</p>
<p>This was my first KubeCon. I went with Juan and Ainhoa from Zondax, and it was their first time too. We didn't go in with a super structured plan, just a simple goal: absorb as much as possible about CNCF projects and the whole cloud native ecosystem.</p>
<p>I don't think I was prepared for how overwhelming it would be.</p>
<p>The moment you walk into the venue, it just hits you. It's huge, loud, dense and every company, every project trying to show why they matter. &quot;Sales pitch&quot; is the easiest way to describe it, but it didn't feel fake. It felt like everyone genuinely believes they're building something important, and this is their shot to show it.</p>
<p>I found myself constantly switching modes, sometimes just listening, sometimes questioning everything, sometimes trying to break down what's actually useful vs what's just well presented. Being a student in distributed systems, I think I naturally leaned into that. I didn't just want to be impressed, I wanted to understand what's actually real.</p>
<p>The keynotes were honestly great. Very much on the edge of what's happening right now in Kubernetes and everything around it. One talk that really stuck with me was Kubernetes at the edge, running on a glider. They literally had a glider on stage, with the pilot there.</p>
<p>That was such a cool moment.</p>
<p>It wasn't just &quot;look at this tech,&quot; it was tech in a real, slightly crazy environment. That mix of engineering and adventure is exactly how I imagine enjoying tech in the future.</p>
<p>AI was everywhere, which was expected, but the vibe around it was interesting. It wasn't doom or hype, it was more like, &quot;okay this is here&quot; and let's figure out how to actually use it properly. Most talks kept it pretty positive, and I liked that. There's already too much negativity around AI outside, mostly because people don't know what the next few years look like.</p>
<p>At KubeCon it felt more grounded.</p>
<p>At some point during the event, I had this weird mix of feelings. On one hand, I felt kind of useless. Like I didn't really have anything to offer there. I was just consuming everything. On the other hand, I felt completely enriched. The ecosystem is way bigger than I had imagined, and just being around people building things at that scale was inspiring.</p>
<p>I think it also made me think a lot about the future, maybe even entrepreneurship. Just seeing how many ideas are out there, how people position them, how they talk about their &quot;moats&quot;, overall it was interesting to observe beyond just the tech.</p>
<p>I spent a lot of time at sponsor booths, talking to engineers and teams. Most people were friendly. Engineers especially, probably because it's easier to relate. With others, you can kind of feel it when you say you're a student. Not in a bad way, just… less interest. It's fine, part of the game I guess.</p>
<p>Some of the best moments were just random conversations. I had lunch with people from German IT companies, a consultant from Iceland, and a really curious guy from Greece. We ended up talking about everything from tech to how close you can get to an active volcano in Iceland. Those were surprisingly warm interactions, the kind you don't plan but remember.</p>
<p>I wouldn't say I'm very extroverted, but I realized I actually enjoy talking to people a lot. I just don't always initiate it. This event kind of pushed me to do that more, and I think I want to carry that forward. Especially talking to engineers.</p>
<p>Also yes, I took a fair amount of swag. And the after parties were fun. KubeTrain was easily the best one.</p>
<p>And then there was Amsterdam.</p>
<p>Outside the event, I spent time exploring the city with Ainhoa. She knew some really nice spots, not just the obvious tourist places, and that made the experience much better. Slowing down a bit in between all the chaos helped.</p>
<p>We went to the Van Gogh Museum, and that was honestly one of the most impactful parts of the trip. Seeing Vincent van Gogh's work in person hits differently. It's beautiful, but also kind of heartbreaking when you think about how his life went.</p>
<p>I don't know, it just makes you reflect a bit. About passion, about timing, about how things unfold. Also what gives a bit of hope is that he started late, so maybe trying new things later in life isn't that crazy.</p>
<p>And yeah, maybe I'll try painting someday. Slightly wishful thinking, but still.</p>
<p>I also got to spend more time with Juan, which I was really looking forward to. We had worked together but not very closely before. He's someone I respect a lot who is very sharp, very curious, and just fun to talk to. Walking around with him, listening to how he thinks about things, you end up learning a lot without it feeling like learning.</p>
<p>I'm glad I got that time.</p>
<p>Overall, KubeCon was a mix of everything quite overwhelming, exciting, slightly intimidating, but very energizing. I learned a lot from the talks, enjoyed the conversations, explored a new city, and came back with a lot to think about.</p>
<p>I went there mostly as a consumer.</p>
<p>I came back feeling like I want to find where I can actually contribute.</p>

    ]]>
      </content>
    </entry>
  
    
    <entry>
      <title>What I&#39;ve Learned About Discrete-Event Simulation</title>
      <link href="https://prats.page/posts/understanding-des/"/>
      <updated>2026-05-14T00:00:00Z</updated>
      <id>https://prats.page/posts/understanding-des/</id>
      <content type="html">
        <![CDATA[
      <p>I've been thinking a lot about discrete-event simulation lately. It's for my master's thesis, but honestly, it's starting to shift how I think about systems in general.</p>
<p>Here's why. Distributed systems fail in really weird ways. Not the obvious stuff — servers going down, networks cutting out. I mean the subtle ones. Retry storms. Timeout cascades. Queue amplification. The kind where things get gradually worse, then suddenly much worse, and by the time you notice, you're already in trouble.</p>
<p>These failures are a nightmare to reproduce. They depend on precise timing, on exactly when a packet arrives, on which goroutine gets scheduled first. You run the same test five times, it fails once, you have no idea why. Change a log line and the bug disappears.</p>
<p>That's what got me looking into DES.</p>
<h2 id="what-it-is" tabindex="-1">What it is</h2>
<p>DES stands for discrete-event simulation. The idea is simple: instead of simulating time continuously, you jump from one event to the next. A packet arrives, a timer fires, a task completes. Nothing changes between events, so there's nothing to simulate.</p>
<p>It's a natural fit for distributed systems. Almost everything in a distributed system is event-driven — messages, timeouts, scheduling decisions. You don't need dense time steps like you would in a physics simulation. You just need a queue of events and a clock that advances when it's time for the next one.</p>
<p>The scheduler is the core piece. It's really just a priority queue. You pop the earliest event, advance the clock, execute the callback. The callback can schedule more events. That's the loop.</p>
<h2 id="the-superpower" tabindex="-1">The superpower</h2>
<p>What makes this useful is determinism. A DES scheduler controls three things that are normally unpredictable:</p>
<ul>
<li><strong>Time</strong> — the clock only moves when the scheduler says so</li>
<li><strong>Ordering</strong> — when two events happen at the same virtual time, the scheduler picks the order</li>
<li><strong>Randomness</strong> — all stochastic decisions come from a seeded source</li>
</ul>
<p>Same seed, same execution. Every time.</p>
<p>This changes the debugging story completely. Normally you're adding log lines, running in staging, praying you can reproduce whatever went wrong. With DES, you record the exact sequence of events that led to the failure and replay it. Like a DVR for your system. You can pause, look at state, step through event by event.</p>
<p>I think that's pretty powerful.</p>
<h2 id="the-hard-part" tabindex="-1">The hard part</h2>
<p>The tricky bit is making this work with real systems. Most distributed services are written in languages with threading, async runtimes, runtime schedulers — all things that fight against determinism. You need to intercept the right layer and route everything through the simulator without changing the application logic.</p>
<p>This is the direction I'm exploring for my thesis. The core question is: how do you make a Go program believe it's been running for five seconds when only fifty microseconds of wall-clock time have passed? I don't know if it'll work yet, but that's kind of the point.</p>
<p>You can't make everything deterministic. A Go program uses the OS scheduler, reads environment variables, touches the filesystem. What you can do is define a clear boundary and guarantee replayability within it. I've been calling this the <strong>determinism envelope</strong>.</p>
<p>The envelope covers simulated time, seeded randomness, and intercepted network I/O. If your code stays within these, replay is guaranteed. Step outside — read the wall clock, open a real socket — and all bets are off. It's not a limitation, it's a contract.</p>
<p>This framing is still early. I'm testing it against real systems to see where it breaks. That might end up being the more interesting part — finding the edge cases where the envelope doesn't hold and understanding why.</p>
<h2 id="other-ways-to-study-systems" tabindex="-1">Other ways to study systems</h2>
<p>There are other approaches. You can build formal models with TLA+ or Alloy and prove properties. Chaos engineering lets you run experiments in production and see what breaks. Unit tests with mocked timeouts cover smaller pieces.</p>
<p>DES sits somewhere between these. You're running actual code, so it's more concrete than a formal model. You can reproduce failures deterministically, which gives you more control than chaos experiments. And it goes further than unit tests because you can simulate complex network conditions across whole systems.</p>
<p>I don't think any of these replace each other. They're different tools for different questions.</p>
<h2 id="why-this-matters-to-me" tabindex="-1">Why this matters to me</h2>
<p>I got into distributed systems because they feel like the most interesting engineering challenge right now. Everything is distributed, everything fails, and most of the time we're flying blind. DES gives us a way to actually see what's happening.</p>
<p>There's something satisfying about watching a complex system unfold deterministically. Every event, every scheduling decision, every random number is exactly what you asked for. It's the opposite of the usual distributed debugging experience, where you're chasing ghosts.</p>
<p>The current plan for my thesis is to build a framework that takes real Go service logic and runs it under a deterministic simulation. The goal is to find metastable failure states before they hit production. But it's early, and honestly, that direction might shift as I learn more. I'm exploring what's possible, what works, and what doesn't. The framework might not come together the way I'm imagining, and that's fine.</p>
<p>Anyway. That's where I'm at right now. A lot of open questions, but that's the exciting part.</p>

    ]]>
      </content>
    </entry>
  
</feed>