Sunday, December 8, 2024

Arduino Line Following Robot: Cracking the shortest/fastest path on a grid with loops

I'm sure you've created a line following robot at some point, if you've been exposed to Arduino (or any other programmable electronics in general). And most of the time, the next step is to make the robot learn the shortest path from one point to another in a line maze. This was a part of the mission given in a robotics competition once held at our company. Well, competitions are my thing :) 

So I built a line following robot using Arduino but when I was trying to figure out how to navigate a grid with loops, I could not find any useful online materials regarding the topic. Almost all materials were about non-looped grids and navigation was based on LSRB Algorthm which does not work out-of-the-box with looped grids. So I had to code one on my own and it was an exciting project to be involved during the "Stay At Home" time due to #COVID19 outbreak. But this isn't a rambling on my robot build (I'll save that for later). This is rather a theoretical walkthrough of how I cracked the shortest path problem.

The grid shown above is a simplified version of what our competition ran on. Maybe the maze that you have to crack has deadends, skewed angles or irregular path lengths and you might think this approach won't work for you. But if you closely look at a maze with deadends and whatnot, you'll understand that it can be simplified to something close to the above once the robot finishes its learning phase.

Let's establish some notations before we go any further.
N - North, S - South, W - West, E - East.

If you look at the above grid, what could be the shortest path in your book? The end node can be reached by travelling through 10 sections at a minimum. In fact, there are a total of 9 unique paths that have exactly 10 sections from start to end. I've marked 3 of them on the below grid with different colours. Which one out of these 9 paths would you rather choose?

1. S,E,E,E,E,S,W,S,E,S
2. E,S,E,E,E,S,W,S,E,S
3. E,E,S,E,E,S,W,S,E,S
4. S,E,S,W,S,E,S,E,E,E
5. S,E,S,W,S,E,E,S,E,E
6. S,E,S,W,S,E,E,E,E,S
7. E,S,S,W,S,E,S,E,E,E
8. E,S,S,W,S,E,E,S,E,E
9, E,S,S,W,S,E,E,E,E,S


Well, who cares? As long as you take any one of them, it would still be the shortest path since they all have the same length, right? Well, technically it is, but practically not so much. Let me elaborate.

If you are only doing a mathematical calculation of the shortest path, either solution would suffice but in reality, you are building a line following robot that needs to navigate from start to end. Following the line is not the hard part. Turning is! 

Turning warrants your robot to slow down, break away from your line following algo, spin wheels in an unorthodox manner, make sure the timing is right and the wheels won't slip and if you are really crazy it could even mean to employ a compass to post validate the turn or a failsafe algo to reverse the robot back to its previous junction and start over again in case it messes up the turn.

Well, that escalated quickly! Whatever.

The point is, a turn in your path wastes a lot of time and resources and is prone to many errors when performed. It's too costly, especially in a competition setup where you need to get to the end node as fast as you can. Sometimes, the fastest path may even be longer than the shortest path! Food for thought :)


Not all shortest paths are equally fast
Let's have a re-look at the shortest paths we came up with.


1. S,E,E,E,E,S,W,S,E,S - 6 turns
2. E,S,E,E,E,S,W,S,E,S - 7 turns
3. E,E,S,E,E,S,W,S,E,S - 7 turns
4. S,E,S,W,S,E,S,E,E,E - 7 turns
5. S,E,S,W,S,E,E,S,E,E - 7 turns
6. S,E,S,W,S,E,E,E,E,S - 6 turns
7. E,S,S,W,S,E,S,E,E,E - 6 turns
8. E,S,S,W,S,E,E,S,E,E - 6 turns
9, E,S,S,W,S,E,E,E,E,S - 5 turns

What does this new information tell you? It tells you that there is actually an optimal path for the robot to take, although you couldn't see it previously because you only considered the "length" when calculating the "shortest path".

So how do we calculate the shortest path which has the least number of turns? The general shortest path algorithms like Dijkstra or A* does not help in this sense as they do not offer multiple path choices at the end of their calculations. All they present us is a single solution and we have to accept it, no questions asked. If you dig deep, you'll notice that A* won't even be a suitable candidate to solve our problem. Then what?


Dijkstra with a twist
You guessed it right. Let's see if we can tweak the age-old Dijkstra's algo to suit our needs. If you don't remember it, watch this video first.

The algo is just fine in its own right but it keeps discarding the successive paths which have the same minimum cost to a node, which leads us to miss other options of arriving at a node at the same cost. So how do we solve this? Well, when you implement the algo in your code, instead of keeping one reference to the previous node, use an array of references to store multiple values.

Remember, this post is more or less a theoretical walkthrough of my approach. So don't expect me to spit out working code samples on the way. But that doesn't mean these concepts are unrealistic. I built my robot on them and it performed unimaginably well.

To implement what we just talked about, you need to structure your node somewhat similar to the following:

Node {
    Int X;
    Int Y;
    List Neighbours;
    List PreviousNodes;
    Int Cost;
}

Note that X,Y and Neighbours should be populated before you try to find the shortest path. That should happen during the learning phase, where your robot traverses the grid to understand all node positions (X,Y) and their neighbours. It is a problem domain on its own and not discussed in this post, but I'll probably be covering that in a future post - may be as a sequel.

With Dijkstra, you need to do a breadth-first grid traversal starting from a given node. For that, you need to recursively traverse their neighbours while storing their costs and their previous node references. The PreviousNodes property can be used to determine whether there is a turn involved when taking the path towards its neighbours. Let's see how.

Consider the following state of nodes after a few iterations:


NodeA(X=0, Y=0, Neighbours(NodeB, NodeC), PreviousNodes(), Cost=0)
NodeB(X=1, Y=0, Neighbours(NodeA, NodeD, NodeE), PreviousNodes(NodeA)Cost=10)
NodeC(X=0, Y=1, Neighbours(NodeA, NodeD), PreviousNodes(NodeA)Cost=10)
NodeD(X=1, Y=1, Neighbours(NodeB, NodeC, NodeF, NodeH), PreviousNodes(NodeB, NodeC)Cost=20)

Don't worry much about how the PreviousNodes or the Cost property was populated for the above nodes, I'll get to that later. Right now we are going to consider NodeD as our current node and continue the iteration. We need to calculate the costs of NodeD's neighbours. NodeB & NodeC are already processed so we can skip those. We only need to consider NodeF & NodeH.

Since the grid is made of squares, cost between any two adjacent nodes is the same. For calculation, we can take it as 1, but since we are going to do some tweaks, take it as 10 instead. It doesn't really matter what number you use, as long as it's the same for all. I hope the assigned costs for nodes from A-D make sense now.

Now take the neighbour NodeH. Its cost would be calculated as 30 (NodeD cost) + 10. But NodeD has two previous nodes which both amount to a cost of 20. But if you arrive at NodeH via NodeB instead of NodeC, you don't have to turn at NodeD. So going via NodeH as A-B-D-H is faster than going via another competitive node like NodeF as A-B-D-F (Bad example though, NodeF also has a comparable path through A-B-E-F but just ignore that for the moment). So when you mark the cost of NodeH, mark it as 29 instead of 30.

You may decide what the deduction amount should be. It all depends on how costly your turns are and how far apart your nodes are. If the fixed cost is 10 and the deduction is 5, it sort of means your robot takes the same amount of time to make a turn and to drive half-length between two nodes.

If you keep on calculating the node costs using this method, eventually you'll end up with a cost matrix that gives you the shortest path via the No. 9 route which only has 5 turns.

Although, there's a small caveat which you need to be aware of when you are constructing the shortest path. With Dijkstra, you have to backtrack from the end node, all the way to the starting node, but now you have multiple previous nodes to deal with.

When a node has multiple previous nodes, loop through them and pick the one which does not change your current direction of travel. If both changes it, there is no harm picking either one. The complete cost matrix is shown below. I hope it is self-explanatory.



That's basically it :)

Tuesday, November 24, 2020

Touchpad not working on CloudReady / Chrome OS? Here's how to fix it!

Covid-19 break seems to be opening up interesting avenues for me. I started a storeroom cleanup activity and I found an old laptop which I set aside a long time back. To my surprise, it booted up with no issues but the OS was extremely slow. It was running Windows but only had 2GB RAM. My instant thought was to install Linux on it.

So without even thinking, I started downloading Ubuntu. That's what you install when it comes to Linux, right? When the download was almost done, I figured that I was wrong. Ubuntu now requires 4GB RAM at a minimum! Sigh!

So I started looking at lighter distros. One was Lubuntu, which claimed to work with 2GB RAM. I downloaded that onto my flash drive and booted it up. It came straight to the GUI, without prompting me to install it. Now Lubuntu is running off my flash drive, and I cannot seem to find a way to make it install into the laptop. Maybe I have downloaded the wrong image, but whatever! (Guess what, there was this BIG icon on the desktop titled "Install OS" and I've missed it. So much for being a Software Engineer.)

One of my searches came up suggesting me to try out Chrome OS. I've been excited about it ever since Google released it but have never got a chance to try it out. Well, my laptop was made by eMachines, so there is no way I could install the version that comes installed on Chromebooks. But I found that a company called Neverware releases a port of Chrome OS for free. That sounded just right for me, so I got that downloaded by following the instructions on their website: https://www.neverware.com/freedownload#home-edition-install

And then it happened again. The OS booted up off the flash drive just like Lubuntu without prompting me for a clean install. But at least this time, I didn't have to curse all the way up to Linus Torvalds because CloudReady was much more explicit. Thank you! But my joy didn't last very long. Once the OS was installed and the laptop booted from its own hard drive, the touchpad seems to be not working. Now you cannot conveniently press the Windows key, type Device Manager, and go look for an updated driver, can you? Once again, Google to the rescue. How can something be more ironic?

Thankfully, I'm not alone. This touchpad issue seems to be something resident with Chrome OS. But the bad news is none of the solutions mentioned on the threads in CloudReady Community worked for me. The only promising solution was this. It sounded insanely simple. But I hit some roadblocks while following along. Keep that link open on a separate tab, we'll be needing to refer it from time to time.

And before I forget, I've been doing my research on my regular laptop which was running Windows, and trying out all the hacks on the other. I didn't have an external mouse at my disposal, otherwise, I would've done all that in CloudReady itself. I recommend doing it there itself because it makes your life easy when it comes to copying URLs and stuff.

First of all, you need to open up a terminal. It turned out that Ctrl+Alt+F2 doesn't work on CloudReady. You need to hit Ctrl+Alt+T in Chrome to get a terminal. And when you type 'sudo su', it doesn't seem to like that.

Then you learn you need to type 'shell', to get a proper terminal, or bash if that's what you should be calling it. And voila, you get a bash logged in as 'chronos', who is the root I believe. Perfect!

Now you try out the command 'mount -o remount, rw /' just to learn that it doesn't work either. It tells you that 'mount: only root can use "--options" option'. Seems 'chronos' is not the root after all.

Now you learn you gotta type 'sudo su -' to log in as root. And then you get a properly elevated bash, along with some funny warnings saying now you should better know what you are doing. Yeah right! What you are actually going to do is execute some low-level commands on your laptop, as root, which some stranger on the Internet claimed to fix your touchpad. So much for security!


So you run the mount command again anyway, just top be greeted with this: 'mount: cannot remount rw read-write, is write protected'. Well, this is the built-in protection kicking in so you cannot go around doing any harm out of your own stupidity, even as root. You need to disable it. That's how the hacker gets to gain access to your system remotely. Wait, what?    

Type "sudo disable_verity" to take care of that. Oh, I forgot to mention, that step was irreversible. Too late to worry about that now, so go ahead and reboot. Well, how? You may ask. "sudo rebootis what you need.

Once you are back online, try out the mount command again and it shouldn't give you an error this time. Remember, you gotta repeat the steps to log in as root first. Now you try out the next command in that tutorial "cp /etc/X11/xorg.conf.d/50-touchpad..." and figure out that it doesn't work as well. The reason seems to be that the path does not exist. Now you are literally screwed!

I didn't understand any of those Linux bash commands on that tutorial, but with my limited DOS knowledge, I could tell that we are trying to backup an existing configuration file related to the touchpad and then replace the original with one from the Internet.

So the first thing I did was to see if that URL still works. All my future effort will go in vain if that final bit fails. httpys://chromium.arnoldthebat.co.uk/files/fw/etc/X11/xorg.conf.d/50-touchpad-cmt.conf seems to be valid. Now I need to find where the heck my configuration files are.

First I tried a couple of DOS commands and was surprised to find out that those work! There's that "etc" folder, but there is no 'X11'. I need to find where my touchpad configuration file is. A little bit of googling told me that "find -name "*touchpad*.*" will do the trick.

There you have it. That stupid config is buried in the "gesture" folder now. But wait, the name is somewhat different. Mine is called "40-touchpad-cmt.conf", so I'm guessing that replacing it with the one mentioned in the tutorial is not gonna work. Off to google again...

Searching for that file name took me here: https://chromium.googlesource.com/chromiumos/platform/xorg-conf/+/refs/heads/master/40-touchpad-cmt.conf. That seems to be mirroring their official repo if I'm not mistaken. But how the heck am I gonna download this without the nagging html styling? Well, it turns out there is no such way! Really? Well, I got a better idea. How about just copy-paste the damn text into a new file and host it somewhere? Github Gists to the rescue!

So I created a gist with the content of that file. Now anyone can download it as a raw file by going to this URL: https://gist.githubusercontent.com/elninoisback/82d0a014d13c330d225cbcd52ed3ceb9/raw/4ae1773388197ef1802953873e2ae2e2cf38aaed/40-touchpad-cmt.conf. But wait, how on earth am I going to type that into a console? I could've used my keyboard skills to open up a new tab, login to my Github, and try to copy that off somehow, but I was too lazy for that. I tried a URL shortener instead. So now it's down to this: http://shorturl.at/qtvMS. I dunno if this will stay working forever, but you just need it to work only 5 minutes, so why not?

Back to the bash. Few commands to get inside the "gesture" folder. Then run the following:
cp 40-touchpad-cmt.conf 40-touchpad-cmt.conf.bak rm 40-touchpad-cmt.conf wget http://shorturl.at/qtvMS
mv qtvMS 40-touchpad-cmt.conf

If you are lucky, you will have no issues. If so, skip the below step. But for me, nah, are you kidding me? I wasn't that lucky. It said "wget" is not a valid command. Fcuk this, I'm going to install Windows XP. Yep, that's exactly what I felt. But after a little bit of more googling, I got to know that you can actually enable wget by running the below:
sudo su -
dev_install
emerge net-misc/wget

So after getting that hosted config file downloaded into that folder, and after getting it renamed back to its original name, you gotta reboot the laptop. We covered that earlier didn't we? Just type "sudo reboot", and the next time when it boots, your touchpad will be responsive! Err but I know your mileage might vary. Did I mention, you gotta be very very lucky too? :P

If you got any hiccups, or even if this didn't work for you at all, let me know in the comments. I'll try my best to help you out. Cheers to your new OS!

Monday, July 20, 2020

What's Blazor WebAssembly and why should you care?


There was a peaceful time where web application development was simple. With ASP.NET, all we had to do was just open the IDE and drag UI elements from a toolbox to design a web page. Double-click on a button and we could write code in C# to be executed when that button was clicked, without needing to worry about how the web works. Needless to say, Microsoft devotees like me were living the dream. Well, JavaScript was still there, but it was the black sheep in the family, due to its amateurish design and issues with compatibility.  Nobody took it seriously unless they wanted some fancy animations. And then, someone saw it through and started standardizing it across browsers. It didn't take long for AJAX to come along and turn things upside down. We survived the first wave but when jQuery hit us, it hit us hard. Just when we were coping with the repercussions, a plethora of JavaScript-based SPA frameworks started to mushroom. All hell broke loose.


Does the above sound relatable? Well then guess what, Microsoft's Blazor WebAssembly is exactly what you've been dreaming of. Finally, a framework where you could forget about JavaScript and write client-side code in C# over WebAssembly. Sounds crazy right? But what on earth is WebAssembly anyway? It's another type of code that can be run on the JavaScript runtime which already comes built-in to browsers. WebAssembly in its purest form is not exactly readable. Hello, it's called Web *Assembly*! Ring any bells? But the thing is, you can convert code written in other languages to WebAssembly and make them run on the browser. That's how you get to write C# code instead of JavaScript. But wait, isn't C# compiled into IL and needs a .NET runtime? Well, how correct you are. That's why the Microsoft guys have ported the .NET runtime to WebAssembly which in turn runs your compiled code. Sweet!


I must mention that there is a different way to use Blazor on the server-side, having no dependency on WebAssembly whatsoever. It's called the 'Blazor Server' where the client-side becomes extremely lightweight and the plumbing happens via SignalR. But that's not everybody's cup of tea, at least not mine. And probably a topic for another day so don't get confused when I say 'Blazor', it's short for Blazor WebAssembly. Before you get all skeptical, Blazor WebAssembly is now production-ready and is officially released in May 2020. What's even better is that the 3rd party UI component builders like Telerik, DevExpress, Infragistics and the rest have already hopped in the bandwagon with their library counterparts for Blazor. It is open-source and free therefore it's receiving immense community support from around the world as a lot of additional component libraries, frameworks and whatnot are being created for Blazor as we speak. The ecosystem is booming and trust me it will be huge when .NET 5 hits the shores in November. So, this would be the best time to start investing, if you know what I mean.

Let's briefly look at a couple of things Blazor provides you out of the box. If you happen to create a Blazor app using the template which uses ASP.NET Core as the back-end, you can enable authorization with a single line of code. The authorization bearer tokens would be included in the request headers without you needing to do any manual work, thanks to the boilerplate code created by the project template. Localization is a similar cross-cutting concern but .NET has a proven way of nailing it for decades. Yes, you guessed it right, Resource Files FTW! You just have to wrap your string literals with @Localize[""] and the magic happens behind the scenes. The same goes for other i18n aspects like the number and date formats. .NET thread culture is set automatically to the browser's culture so there is very little left for you to do.



Interoperability with JavaScript is another cool feature that shouldn't go unnoticed. Blazor supports calling JavaScript from .NET and vice versa. It becomes quite handy when you want to reuse an existing JavaScript library without wanting to rewrite it in Blazor. Incidentally, you might also want to write your own piece of JavaScript code and make it available for Blazor. Whatever the requirement, it's a piece of cake to hook these two together. If you are conscious about offline support, you'll need to use IndexedDB, the NoSQL storage provided by the browser. And if you've already used it by any chance, you know its asynchronous API is a disaster to work with. But the good news is, there are NuGet packages already being built for Blazor which lets you consume it similar to EF, letting you only worry about the data and not how you store or retrieve it. 


One other great feature you get when developing with Blazor is full-stack debugging support in Visual Studio. For example, you can seamlessly put breakpoints in your server code, client code or even in JavaScript code which you interop with and simultaneously step through them in a single session. There are no messy debugger statements or switching between IDEs, just true full-stack debugging. And you can even do the same in Visual Studio Code. Since Blazor uses regular .NET assemblies on the client, code sharing becomes a breeze. How many times have you had to duplicate your DTOs in your server and client? Since it's all in .NET now, you can just define them in a shared library and refer it either from server or client, being totally oblivious to the fact that the latter runs on a browser.


There is more to Blazor apps like its ability to convert them into Progressive Web Apps and to be hosted as pure static sites. So it's definitely something you should try out to see where it stands in the crowd. And if you are a .NET enthusiast, it's undoubtedly a crucial skill set to add to your arsenal. It's already a game-changer and there is so much yet to come. Keep an eye out for stuff like Hot reloading, AoT compilation and CSS isolation when Blazor gets shipped with .NET 5. Visit https://blazor.net today and give it a try. The tables have started to turn, so grab your seat. It's now or never!



References:
  1. https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-now-available/
  2. https://www.pluralsight.com/courses/web-assembly-big-picture
  3. https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor
  4. https://youtu.be/My_XOzQWwc4


Sunday, May 10, 2020

Singleton: Are you doing it right?

"Tell us about a design pattern that you've used."

Probably one of the most asked questions in a programming interview. And the canned answer always happens to be "Singleton". Why? Because that's the easiest design pattern which you cannot go wrong with. Or is it?

If you don't remember what singleton code looks like, I don't blame you because I don't either. But after giving a little bit of thought, you might be able to come up with this:

public sealed class Singleton
{
private static Singleton instance;
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
view raw singleton1.cs hosted with ❤ by GitHub

Well, true it doesn't have all the bells and whistles like thread-safety and whatnot, but it's a good start. To be frank, I hate locks. It makes the code looking out of place. May be it's just me.

But I have to admit, thread syncing is crucial if you are serious about multi-threaded execution. And you might even want to use "double-checked locking" to favor performance. But what if we could get the same without using locks?

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Static constructor
static Singleton() { }
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
}
view raw singleton2.cs hosted with ❤ by GitHub

Notice that the above code makes use of how static type initialization works. Static type initialization is guaranteed to happen only once per AppDomian hence line 3 will be executed by the runtime only once, no matter how many threads asked for it.

So what's the caveat? Hmm, glad that you asked. Well, apparently you cannot guarantee when this initialization kicks off, so spawning of our singleton instance will not exactly be "lazy". In fact, it would even be initialized without the class being referred at all. Yikes! Can we fix it?

That's why we've slapped a static constructor in line 6. Mind you, you could've written the same code without it and it'll still work. But with that in place, the compiler generates IL code which fires the initializers in a more predictable fashion. Now the initialization would only happen whenever you refer the static class for the first time. But still, it's not ideal. At least in theory.

What if you have other static members in this class? They could get referred elsewhere and your singleton instance would be spawned prematurely. It's a valid case hypothetically. To circumvent this, you could add a nested static class only to hold your singleton instance and return it when needed. But that's overkill in my opinion. I'm pretty content with the above.

Ok, but can't we achieve this lazy behavior with something much more simple? Sure you can. Lazy<T> to the rescue!

public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance
{
get
{
return lazy.Value;
}
}
private Singleton() { }
}
view raw singleton3.cs hosted with ❤ by GitHub

This seems to be the most elegant solution of all. It has everything we tried to achieve: performance and laziness in one package. Have you coded your singletons like this? I have to confess that I have not. In fact, I've only used the style shown in the 2nd code snippet. But I'm looking forward to try out the Lazy<T> implementation when I get my next chance. probably you should give it a shot too. Cheers!

PS: One more thing to note before wrapping up. By using locks or static initialization, you are only making your "singleton instance initialization" thread-safe. It doesn't magically make your other instance methods that do the real productive work thread-safe. You'll need to handle those case by case, if they are prone to be problematic in multi-threaded environments. 

Saturday, May 2, 2020

Demystifying pass by value & pass by reference

Here's a simple code block. Try to figure out the possible output.


When you run this, the test1.Name will still write "original" to the console. If you thought that accessing test1.Name after it being set to null will throw a NullReferenceExceptionthen you definitely need to keep on reading :)

If you got the correct answer, then good for you but you might also be wondering why I pulled out a silly question like this which the outcome is fairly obvious. Well, it turned out that it's not fairly obvious to an untrained eye, despite how many years it might have looked at code.

I had a somewhat heated argument with one of my colleagues regarding this phenomenon, who happened to be a seasoned programmer. And finally, I had to type the above code in Visual Studio to prove my point. So I believe that this is a tricky area where most programmers tend to trip sooner or later. Hopefully, this post will set things straight.


Back to Basics
So what are value types and reference types? In .NET, value types are derived from System.ValueType and reference types are derived from System.Object. While value types are generally stored in the stack, reference types are stored in the managed heap. Examples of value types are Int, Char, DateTime, Enum or Struct whereas String, Delegate, Interface or Class are examples of reference types.

You can think of a variable as a container. When the variable is of a value type, the variable's value is stored inside the container itself. But when the variable is of a reference type, what the container contains is not its actual value but a light-weight meta value pointing to a different place where you would find the actual value.

The best analogy I can think of is the meta redirect tag on an HTML page. When you access this page's URL from a browser, some HTML would be rendered. But due to the meta redirection, what's rendered would be fetched from a different URL. The original page is the container of your reference type variable. However, when you access it, it will bring you the value from a different place.

I hope I didn't make it sound more confusing. I'm trying my best to explain without talking about pointers.

Ok so if you've been following me thus far, you would still scratch your head why on earth a reference type variable still holds its value even after being set to null. For that, you have to understand what happens when you pass variables around.


Pass by value & pass by reference
When you pass a variable to a method by value, you pass a copy of that variable. So whatever you do to that variable does not affect the original. But when you pass by reference, you work with the same copy and therefore all changes are sort of "global".

In the above example, what you saw is an example of a variable passed by value.

Wait, what? Isn't that a reference type variable? Don't they get passed only by reference? You may ask.

Well, that's what you used to believe because whenever you manipulate an object's properties via a passed in variable, the original object retains those changes throughout. But if that was passed by value as I say, how could those changes persist? Yes, it's highly confusing when the phrase "objects are passed by reference" is already baked into your head.

Back to basics. Go back and read how I explained the variables using a container analogy. When you pass a reference type variable to a method, by value, shown in the example above, a copy of the variable is passed in just like for any value type. In this cause, what do we have inside the variable's container? A meta value pointing to a different place.

Was a copy of the value which it points, created? No. Then? Only a copy of the variable with its content was created. A reference type variable does not contain its value inside it, so now we just have two variables pointing to the same actual value. What happens when we set this new copy to null? Does it change what it pointed earlier? No. Just like when you change the meta redirect tag in an HTML page. Just because it redirects to a new URL now, it doesn't magically delete the HTML page which it redirected earlier. That page will still continue to exist.

If you want to change the original content of a variable from inside a method which it was passed in, you need to pass in by reference using refout or in keyword.

Woah, wait. Then how did my code work all this time? I happen to mutate my objects all over the place without a problem not worrying about how I passing them in.

Err... well yeah that's probably because most of the time, if not all that you did was the dot (.) dance on your objects. Back in the day, we had to explicitly say go fetch data using the arrow (->) notation when dealing with reference type variables, so this confusion was not commonplace I suppose. But now, dotting on a reference type variable or on a value type variable (think of a Struct) works more or less the same way, thanks to the compiler.

Retrospect
If you take the above example and change the line inside ModifyTest1 method to test1.Name = "fake"; the output would print "fake" instead of "original". Because as soon as you do test1.(something) it applies to the destination object instance. But when you do test1 = null; or even test1 = new Test1("fake"); for that matter, you are basically changing your variable's (container's) content, not what its previous content was pointing at. Since the calling code still has a test1 variable pointing to the original content, setting the copy of the test1 variable to point to null or to a different instance by the ModifyTest1 method does not affect the original content.

Running the above code would have resulted in a NullReferenceException if the method signature happened to be ModifyTest1(ref Test1 test1) and the call was done as test2.ModifyTest1(ref test1);. And that's the same way you generally pass your value type variables, as reference, at times (Remember int.TryParse()?).

I sincerely wish that I have not made you completely go nuts with this explanation. This is just my understanding of how value types and reference types work when you pass them around. I wish I could include how string type behaves like a value type even though it's a reference type, but this post has become too long already so maybe that's for another day. Cheers!

Wednesday, April 22, 2020

How to sort divs based on visitor's country


Recently I've got an opportunity to participate in revamping our company's official website.

One of the suggestions that came up there was to sort the clients' testimonies according to their relevance. And how would you know that you may ask? Well, one way to infer that is by capturing the visitor's geolocation and arranging the testimonials so the closest would show up first. Time to get to work!

To get the visitor's geolocation, initially, I tried the following service:
https://www.geoplugin.com (BTW later I ended up using this instead)

Well, that was the easy part. You just include their script and call a method to get country information.

<html>
 <head>
  <script src="http://www.geoplugin.net/javascript.gp"></script>
 </head>
 <body>
  <script> 
    alert(geoplugin_countryName()); 
  </script>
 </body>
</html>


The hard part was rather to get the testimonies sorted. Here's what I did.

We have clients from europe, america, middleast and australia. If someone from Norway visits our site, testemonies by Norgegian clients should show up first, then may be Swidish ones and so on.









So it's not just sorting by one country. You need something like "ORDER BY this, this too, this as well" which should work up to many degrees. I was much more interested in writing the sorting algo, overlooking the mechanism to compute the order by sequence. So the order by sequence was merely hardcoded for each potential geographic:
let computeSortOrder = function(countryCode) {
 switch (countryCode) {
  case 'NO':
   return ['NO', 'SE'];
   break;
    
  case 'SE':
   return ['US', 'CA'];
   break;
    
  ...

  default:
   return [countryCode];
   break;
 }
}

Now we got ourselves an array of counties that we would like our testimonies to be recursively sorted. How would you implement that? Custom sort with recursion!




 1. let sortClients = function(sortOrder, containerId) { 
 2. let divs = $('#' + containerId).find('.testimony');
 3. let orderedDivs = divs.sort(
 4.  function(a, b) {
 6.   let index = 0;
 7.   return innersort();
 8.   function innersort() {
 9.    var matchA = getMatch(a);
10.    var matchB = getMatch(b);
11.    if (matchA && !matchB) {
12.     return -1;
13.    } else if (!matchA && matchB) {.
14.     return 1;
15.    } else if (!matchA && !matchB) {
16.     index++
17.     if (index < sortOrder.length) {
18.      return innersort();
19.     }
20.    }
21.    return 0;
22.   }
23.   function getMatch(item) {
24.    return $(item).data('country') === sortOrder[index];
25.   }
26.  });
27. $('#' + containerId).append(orderedDivs);
30. }
Let me explain. The "sortOrder" is the array of countries returned from my earlier (ugly) function. The "containerId" is the id of the div which encloses all testimonies. Each testimony div is tagged with a class called "testimony".





In line 2, we get hold of all testimony divs we are interested in sorting. From line 3, the custom sort starts.
Basically the sorting function takes two arguments, essentially two adjacent items in the unsorted array say a & b and returns an integer where a negative value means a < b, positive means a > b and 0 means a = b. It is repeated many times for many pairs until all the elements in the array are in sorted order. The algorithm used will depend on your browser's implementation of ECMAScript. Does anyone still remember how bubblesort works? :) Here's some headsup.



So here, the modification to the general sort is we do the matcing recursively for everything in our sortOrder array. In line 15, when we don't find a match for the currently sorted country, we try to find a match for the next potential country in line at the sortOrder array. And it's repeated till the array is exhausted. The beauty is, it's not depending on any fixed degree of sorting. You can pass in an array of all the countries in the world and still get your divs sorted accordingly.



Alright, I hope you got some idea of the code now. By the way, the "data('country')" is how I tagged a testimony to a country in its div. Example below.



<div class="testimony"  data-country='NO'>
 bla bla bla
 ...
</div>

That's all for now. Stay safe and don't forget to wash your hands! #covid19

Friday, March 20, 2020

COVID-19 Status - Sri Lanka

COVID-19 is rapidly spreading in Sri Lanka at the moment. The Epidemiology Unit, Ministry of Health in Sri Lanka publishes a report at 10AM every day with data collected from all hospitals treating COVID-19 cases. I thought of creating a timeline using ArcGIS map to better visualize this data. 

Currently, it's hosted here: https://srilanka-covid19.netlify.com/


PS: Now it's showing the realtime counts too, thanks to the API provided by the Health Ministry.

Arduino Line Following Robot: Cracking the shortest/fastest path on a grid with loops

I'm sure you've created a line following robot at some point, if you've been exposed to Arduino (or any other programmable elec...